Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Warnings #480

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

[WIP] Warnings #480

wants to merge 7 commits into from

Conversation

jodavies
Copy link
Collaborator

I'm trying to clean up the compilation warnings. Remaining on my system, is a uninitialized and a keyword-macro (with clang 14).

@jodavies
Copy link
Collaborator Author

jodavies commented May 7, 2024

The uninitialized warning comes from the d_u_m_m_y declared here:

PADPOINTER(1,1,1,1);

This warning can be removed by initializing it in the constructor:

for (unsigned i=0; i < sizeof(d_u_m_m_y); i++) {
   d_u_m_m_y[i] = 0;
}

or, by just removing the padding. At least on my system (gcc 11.4.0) sizeof(tree_node) is 48 bytes regardless.

Which do you prefer?

@coveralls
Copy link

coveralls commented May 7, 2024

Coverage Status

coverage: 50.616% (+0.02%) from 50.596%
when pulling 8c36a2e on jodavies:warnings
into 3262c64 on vermaseren:master.

@tueda
Copy link
Collaborator

tueda commented May 7, 2024

You can define copy/move constructors/assignment operators that skip copying the padding:

	tree_node(const tree_node& other):
		childs(other.childs),
		sum_results(other.sum_results),
		num_visits(other.num_visits),
		var(other.var),
		finished(other.finished) {}

	tree_node(const tree_node&& other) noexcept :
		childs(std::move(other.childs)),
		sum_results(other.sum_results),
		num_visits(other.num_visits),
		var(other.var),
		finished(other.finished) {}

	tree_node& operator=(const tree_node& other) {
		if (this != &other) {
			childs = other.childs;
			sum_results = other.sum_results;
			num_visits = other.num_visits;
			var = other.var;
			finished = other.finished;
		}
		return *this;
	}

	tree_node& operator=(tree_node&& other) noexcept {
		if (this != &other) {
			childs = std::move(other.childs);
			sum_results = other.sum_results;
			num_visits = other.num_visits;
			var = other.var;
			finished = other.finished;
		}
	}

@jodavies
Copy link
Collaborator Author

jodavies commented May 7, 2024

Ah, right, now I understand where the warning comes from. You need a return *this; in the second assignment operator. I'll paste these in.

On my system at least, the build is now clean, except the still-disabled stringop-overflow. That one is entirely due to the NCOPY macro, but it is used in many different places. On first inspection, it doesn't look easy to build some kind of bounds check into the macro...

@jodavies
Copy link
Collaborator Author

jodavies commented May 8, 2024

I think we don't want to use -Werror, unless perhaps it can be enabled for 64bit builds only. It looks like the 32bit build throws up a lot of problems due to type conflicts.

(I wonder, if FORM 5 could actually be the time to drop 32bit support? #422 #426 )

The current fix for 12ce0a5 fails on macOS because it needs to be built specifying c++11. We could do that, or change the fix.

@tueda
Copy link
Collaborator

tueda commented May 8, 2024

For the "C++11 extension" errors, we can test if the compiler accepts -std=gnu++11 by AX_CHECK_COMPILE_FLAG and use it if OK. Maybe -std=gnu++14 or higher could generate faster machine code.

@jodavies
Copy link
Collaborator Author

jodavies commented May 8, 2024

That's fine as long as macOS will always support those flags. I don't have a mac to test this.

@tueda
Copy link
Collaborator

tueda commented May 11, 2024

-Werror is not good because we can't guarantee that all future compilers won't give any warnings. Actually, GCC 12.3.0 doesn't work:

docker run -it --rm ubuntu:22.04
apt update
apt-get install -y automake g++-12 git libgmp-dev libmpfr-dev make ruby zlib1g-dev
git clone https://github.com/jodavies/form.git
cd form
git checkout 56f5146d7d43e3d9dc8faddcae42621639274e2e
autoreconf -if
CC=gcc-12 CXX=g++-12 ./configure
make
g++-12 -DHAVE_CONFIG_H -I. -I..    -Wall -Wextra -pedantic -Werror -Wno-stringop-overflow -O3 -fomit-frame-pointer -march=native  -MT form-polyfact.o -MD -MP -MF .deps/form-polyfact.Tpo -c -o form-polyfact.o `test -f 'polyfact.cc' || echo './'`polyfact.cc
In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,
                 from /usr/include/c++/12/bits/allocator.h:46,
                 from /usr/include/c++/12/string:41,
                 from poly.h:33,
                 from polyfact.cc:35:
In member function 'void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = int]',
    inlined from 'static void std::allocator_traits<std::allocator<_CharT> >::deallocate(allocator_type&, pointer, size_type) [with _Tp = int]' at /usr/include/c++/12/bits/alloc_traits.h:496:23,
    inlined from 'void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:387:19,
    inlined from 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:366:15,
    inlined from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:733:7,
    inlined from 'const std::vector<poly> polyfact::factorize_squarefree(const poly&, const std::vector<int>&)' at polyfact.cc:1443:15:
/usr/include/c++/12/bits/new_allocator.h:158:33: error: 'void operator delete(void*, std::size_t)' called on pointer '<unknown>' with nonzero offset [1, 9223372036854775804] [-Werror=free-nonheap-object]
  158 |         _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
      |                                 ^
In member function '_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = int]',
    inlined from 'static _Tp* std::allocator_traits<std::allocator<_CharT> >::allocate(allocator_type&, size_type) [with _Tp = int]' at /usr/include/c++/12/bits/alloc_traits.h:464:28,
    inlined from 'std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:378:33,
    inlined from 'void std::_Vector_base<_Tp, _Alloc>::_M_create_storage(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:395:44,
    inlined from 'std::_Vector_base<_Tp, _Alloc>::_Vector_base(std::size_t, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:332:26,
    inlined from 'std::vector<_Tp, _Alloc>::vector(size_type, const value_type&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]' at /usr/include/c++/12/bits/stl_vector.h:566:47,
    inlined from 'const std::vector<poly> polyfact::factorize_squarefree(const poly&, const std::vector<int>&)' at polyfact.cc:1443:15:
/usr/include/c++/12/bits/new_allocator.h:137:55: note: returned from 'void* operator new(std::size_t)'
  137 |         return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      |                                                       ^
cc1plus: all warnings being treated as errors
make[2]: *** [Makefile:5553: form-polyfact.o] Error 1

@jodavies
Copy link
Collaborator Author

Yes, I will remove that again and clean up this patch series. For 33f7021, should we remove c++11 features, or add it to the build?

@tueda
Copy link
Collaborator

tueda commented May 13, 2024

Perhaps, we may need a consensus on the minimal C/C++ requirements, like C99/C++11. The workshop would be a good opportunity for it.

Even if we do not exclude C++98/C++03, we may use the #if preprocessor directive to check the value of __cplusplus to see whether the compiler supports C++11.

@jodavies
Copy link
Collaborator Author

I cleaned this up somewhat. For now I just removed the cpp11 code, it compiles without warnings without the move constructor anyway. Hopefully macOS is happy this time...

@tueda
Copy link
Collaborator

tueda commented May 21, 2024

Is this PR still in progress? Or is it ready to merge?

@jodavies
Copy link
Collaborator Author

At the moment the build is not completely warning free, depending on which compiler or version you use. I don't think that is necessarily the goal though. Primarily I wanted to clean up things that potentially lead to bugs, such as uninitialized variables and, particularly, misleading indentation (sorting that one out took me several iterations to do correctly, in the SKIPBRA macros -- precisely the reason why it should be resolved, I suppose).

I would say this can be merged, and additional warnings can be cleaned up in the future as and when it seems necessary.

@jodavies
Copy link
Collaborator Author

@tueda : would you want these commits squashed or as they are now: one per warning?

@tueda
Copy link
Collaborator

tueda commented May 28, 2024

I think both options are fine; keeping them as a bunch of separate commits is reasonable for this case. It is just I haven't tried to merge this PR because there are still warnings. Merging it would be OK.

One possible improvement could be: BracketInfo.dummy is a dummy field for padding. Maybe we can skip assigning 0 to this field in the default constructor (thought its costs would be negligible) if we define the copy constructor and the copy assignment operator so that dummy is not copied.

@jodavies
Copy link
Collaborator Author

Which compiler do you see this warning with?

@tueda
Copy link
Collaborator

tueda commented May 28, 2024

I meant the warnings with 32-bit containers in CI. With GCC 14 on Ubuntu 64-bit, there are no warnings. (Warnings for LLP64 are compatibility bugs, so that's another story.)

@jodavies
Copy link
Collaborator Author

jodavies commented Jun 4, 2024

The 32bit build has a number of warnings due to incompatible-pointer-types: some are in the float code and can be ignored. But some are not, and in principle could be fixed.

With gcc-12 (both 32 and 64 bits) I also actually get a free-nonheap-object:

In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,
                 from /usr/include/c++/12/bits/allocator.h:46,
                 from /usr/include/c++/12/string:41,
                 from poly.h:33,
                 from polyfact.cc:35:
In member function ‘void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = int]’,
    inlined from ‘static void std::allocator_traits<std::allocator<_CharT> >::deallocate(allocator_type&, pointer, size_type) [with _Tp = int]’ at /usr/include/c++/12/bits/alloc_traits.h:496:23,
    inlined from ‘void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:387:19,
    inlined from ‘std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:366:15,
    inlined from ‘std::vector<_Tp, _Alloc>::~vector() [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:733:7,
    inlined from ‘const std::vector<poly> polyfact::factorize_squarefree(const poly&, const std::vector<int>&)’ at polyfact.cc:1443:15:
/usr/include/c++/12/bits/new_allocator.h:158:33: warning: ‘void operator delete(void*, std::size_t)’ called on pointer ‘<unknown>’ with nonzero offset [1, 9223372036854775804] [-Wfree-nonheap-object]
  158 |         _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
      |                                 ^
In member function ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = int]’,
    inlined from ‘static _Tp* std::allocator_traits<std::allocator<_CharT> >::allocate(allocator_type&, size_type) [with _Tp = int]’ at /usr/include/c++/12/bits/alloc_traits.h:464:28,
    inlined from ‘std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:378:33,
    inlined from ‘void std::_Vector_base<_Tp, _Alloc>::_M_create_storage(std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:395:44,
    inlined from ‘std::_Vector_base<_Tp, _Alloc>::_Vector_base(std::size_t, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:332:26,
    inlined from ‘std::vector<_Tp, _Alloc>::vector(size_type, const value_type&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:566:47,
    inlined from ‘const std::vector<poly> polyfact::factorize_squarefree(const poly&, const std::vector<int>&)’ at polyfact.cc:1443:15:
/usr/include/c++/12/bits/new_allocator.h:137:55: note: returned from ‘void* operator new(std::size_t)’
  137 |         return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      |                                                       ^

I don't think the code is really doing anything wrong here, probably we can ignore this one:

form/sources/polyfact.cc

Lines 1442 to 1443 in 83e3d41

for (int i=0; i<(int)q.size(); i++)
if (q[i]!=vector<WORD>(q[i].size(),0)) rank++;

@jodavies
Copy link
Collaborator Author

jodavies commented Dec 4, 2024

With the current commits, 64bit form and tform (and vorm and tvorm) build with no warnings on Ubuntu 20.04, 24.04, 24.10.

Parform is OK on 20.04 (mpich), 24.04 (openmpi), but not on 24.10 (mpich), there are maybe-uninitialized and alloc-size-larger-than at link time.

@tueda
Copy link
Collaborator

tueda commented Dec 5, 2024

This looks fine to merge (after rearranging the commits and commit messages). In some cases warnings might still persist or reappear in the future, but it's certainly a step toward better code quality.

@jodavies
Copy link
Collaborator Author

jodavies commented Dec 5, 2024

-Wstringop-overflow can be renabled if NCOPY is modified to:

#define NCOPY(s,t,n) { while ( (n)-- > 0 ) { *s++ = *t++; } }

It took me a little while to work out that the brackets are required on the n here, since the macro is passed dereferenced pointers sometimes and *n-- is not the same as (*n)--...

@tueda
Copy link
Collaborator

tueda commented Dec 5, 2024

*n-- is not the same as (*n)--

Yes, this is very tricky and related to a reason why C++ers prefer using ++it for iterators.

Clean up maybe-uninitialized warnings.

In optimize.cc:
tree_node contains alignment padding, which was "used" uninitialized.
Add copy constructors and assignment ops which ignore the padding, from @tueda.
Add braces to resolve cases of misleading-indentation
Rename "alignof" macro to "form_alignof" to remove clang warning. We can
also then remove the definition of _ALLOW_KEYWORD_MACROS for MSVC.
These bindings are not used. Define the pre-proc variable OMPI_SKIP_MPICXX
which skips their definition.
Add braces around logical not used on LHS of comparison
Use FORM's DUMMYUSE macro to suppress (valid) warning for an unused parameter.
Adjust NCOPY macro to avoid stringop-overflow warning.
@jodavies
Copy link
Collaborator Author

jodavies commented Dec 5, 2024

I made the commit messages a bit more uniform, and merged the two for maybe-uninitialized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants