Why do I get c++ compile warnings depending on header order - c++

I'm using compile flags -Wall -Wextra and -Werror. I'm getting a flood of "declared ‘static’ but never defined [-Werror=unused-function] " Warnings (treated as errors) when I compile the following file. No such warnings when I reverse the order of the #include directives. Please help me understand why?
I know I could remove the extra warnings and errors and get my program to compile, clearly that's not my intent or my code would be more interesting. I'm trying to gain a deeper knowledge of C++, and improve my habits through cleaning up warnings in my code.
I understand that argp is really a C library, and iostream is a C++ library, perhaps that's part of the issue. I'd be happy to use a proper C++ library to accomplish what argp does, but I can't find one. If there is one I'd be happy to hear about it.
#include <argp.h>
#include <iostream>
int main(int argc, char **argv)
{
return 0;
}
To be clear, I am working on a non-trivial program, and have specific reasons for wanting to use C++ instead of C. I've boiled down the code shown here to the least possible code to produce the effect I'm trying to understand. Please don't suggest that I don't need one or the other of the headers.
Compiler: gcc
:~/scratch/argp_example$ gcc --version
gcc (Ubuntu 5.2.1-23ubuntu1~12.04) 5.2.1 20151031 Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
compiler invokation:
g++ -o obj/main.o -c src/main.cpp -Wall -Wextra -Werror -pedantic -MMD --std=c++11 -Iinc
Specific compiler feedback:
In file included from /usr/include/x86_64-linux-gnu/c++/5/bits/gthr.h:148:0,
from /usr/include/c++/5/ext/atomicity.h:35,
from /usr/include/c++/5/bits/ios_base.h:39,
from /usr/include/c++/5/ios:42,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from src/main.cpp:2:
/usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h:101:1: warning: ‘int __gthrw_pthread_once(pthread_once_t*, void (*)())’ declared ‘static’ but never defined [-Wunused-function] __gthrw(pthread_once) ^
There are many many more similar errors from gthr.h. This specific copy/paste was from a run without -Werror, but that's the only difference.
SOLUTION:
This was my choice of solution, but of course, you could simply reverse the order of includes. It is a recognized bug, so there is no "correct" answer, all solutions would be workarounds. This one, I think, is least likely to give me or others fits later.
#include <argp.h>
#undef __attributes__
#include <iostream>
...

This is a known bug. The culprit is this chunk of code in argp.h, which is triggered when you use -std=c++xx:
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
# define __attribute__(Spec) /* empty */
# endif
The declarations at issue are normally marked with __attribute__ ((__weakref__("pthread_meow"))), but this macro caused that attribute to vaporize.
Until the bug gets fixed, you might want to compile with -std=gnu++xx, or manually #undef __attribute__ after including argp.h.

Related

Error: Initializer provided for function, __THROW __asm

I am trying to port an ARM-C library to be compiled with x86_64 C++, and I am getting the following error:
In file included from /usr/include/c++/5/cwchar:44:0,
from /usr/include/c++/5/bits/postypes.h:40,
from /usr/include/c++/5/bits/char_traits.h:40,
from /usr/include/c++/5/string:40,
from MyFile.h:19,
/usr/include/wchar.h:226:20: error: initializer provided for function
__THROW __asm ("wcschr") __attribute_pure__;
^
where MyFile.h has the following structure
// comments
#pragma once
// comments
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string> //<<< line 19
…
Initially, instead of it used to be which gave me a similar error:
In file included from MyFile.h:19:
/usr/include/string.h:73:21: error: initializer provided for function
__THROW __asm ("memchr") __attribute_pure__ __nonnull ((1));
^
Compiler version:
GNU C++14 (Ubuntu 5.4.0-6ubuntu1~16.04.11) version 5.4.0 20160609 (x86_64-linux-gnu)
compiled by GNU C version 5.4.0 20160609, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3
ldd (Ubuntu GLIBC 2.23-0ubuntu11) 2.23
Compilation flags:
#g++ -O3 -std=c++14 -fpermissive -Wno-system-headers -w
UPDATE 1:
I've been modifying the Makefile, and the original version contains $#.via. For instance:
#$(COMPILE) -M -MF $(subst .o,.d.tmp,$#) -MT $# -E $(C_FLAGS) $#.via $< -o $#.preprocessed.c
and I changed the $#.via for #$#.via because I saw that in an older project they did it like that. However, if I leave as $#.via I just get:
SomeFile.c:1:1 fatal error: OneHeader.h: No such file or directory
I am starting to think that my Makefile is somewhere wrong...
I misunderstood the compiler option... Few lines above, my makefile creates the #.via files passing DEFINES and INCLUDES
#echo $(patsubst %, '%', $(C_DEFINES)) > $#.via
#echo $(C_INCLUDE) >> $#.via
and those #.via files are passed as additional arguments for the compilation. While for armcc the --via is supported see here, I found that for g++ -according to the gcc doc- the syntax is #<your_file>. Thus, what #$#.via does is simply to parse the $#.via to <your_file>.via.
Now I am still getting the initializer provided for function error message.
UPDATE 2:
I found the problem and I explained what happened in the answer section. See below.
Root cause
The problem was originated because I redefined __asm to be replaced by nothing (e.g. #define __asm) since I didn't want to touch the assembly code yet. Remember that I said I am porting ARM to x86, so I thought that easiest way to get rid of the compile errors was to remove all those __asm instructions, but not considering the effects of doing such a thing.
In other words, when I included the string.h header, the header itself uses assembly call as the error messaged pointed out:
/usr/include/wchar.h:226:20: error: initializer provided for function
__THROW __asm ("wcschr") __attribute_pure__;
and when the preprocessor changed the __asm("wcschr") for ("wcschr") the compiler hits the error -- which makes sense.
Moral of the history
Do not redefine qualifiers since it will also affect other modules that you are not seeing directly and prefer creating a macro to just change them (e.g. __asm for /*__asm*/) or just run sed in you code base.

Error "sigemptyset was not declared in this scope" when using C+11 and Newlib

We are catching compiler errors when using sigemptyset on Cygwin under Newlib. The error occurs with a C++ compiler, but only when -std=XXX is used. Without a standard option, the test program compiles and executes as expected.
The test program is below, and the Cygwin header of interest follows. I don't see anything suspicious in the Cygwin header.
I've tried tricks like #define _GNU_SOURCE and #define _XOPEN_SOURCE 700. I've also tried tricks like using the global and std namespaces. Related, see What does -D_XOPEN_SOURCE do/mean? and Namespace issues in c++11?.
What is causing the compile failure and how do I fix it?
$ cat ~/test.cxx
#include <signal.h>
int main(int argc, char* argv[])
{
struct sigaction new_handler;
return sigemptyset(&new_handler.sa_mask);
}
Without a -std=XXX, it results in:
$ g++ -c test.cxx
$
With a -std=XXX, it results in:
$ g++ -std=c++03 -c test.cxx
test.cxx: In function int main(int, char**):
test.cxx:6:44: error: sigemptyset was not declared in this scope
return sigemptyset(&new_handler.sa_mask);
And when trying to use sigemptyset in the global namespace:
$ g++ -std=c++03 -c test.cxx
test.cxx: In function ‘int main(int, char**)’:
test.cxx:6:12: error: ‘::sigemptyset’ has not been declared
return ::sigemptyset(&new_handler.sa_mask);
^
Things get worse when using -std=gnu++03 and friends.
The function is an extension over the ISO C standard.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigemptyset.html
as such is protected on /usr/include/sys/signal.h by
__XSI_VISIBLE >= 4
see /usr/include/sys/features.h for details.
As defaults the largest definition set is used, but -std=XXX reduces the definition scope
The issue was worked through at Botan 2.1.0 does not compile under Cygwin 2.8.0 with g++ 5.4.0. Here are the two comments of interest.
First, from noloader:
Cygwin uses Newlib, not GNU's libstdc++. When there's no
-std=c++XX, current GCC defaults to -std=gnu++11 (GCC 6 changes
to gnu++14 by default). I
believe GNU sources ensures expected functions, like sigaction, are
available.
You might consider trying -D_XOPEN_SOURCE=600 or
-D_XOPEN_SOURCE=700.
Also see C++ and feature guards Warning
Question on the
Newlib mailing list.
Second, from SideChannel:
Thanks to #noloader. Until now -std=c++11 was set in Makefile. The
important info is in above mentioned thread on the Newlib mailing
list. Yaakov Selkowitz wrote:
G++ defines _GNU_SOURCE on glibc targets, meaning that -std=c++NN is, contrary to the documentation, not strict ISO C++:
So, applying the patch #987
AND setting -std=gnu++11 works for me. I
did not try the other -D options (I think the other fact is more
fundamental). Summarizing, #randombit please apply the PR #987 and set
-std=gnu++11 for gcc under Cygwin.

Which C++ standard header defines SIZE_MAX?

I'm working on an existing C++ codebase that happens to use SIZE_MAX in a couple of places. I did some refactoring and now SIZE_MAX is not defined in one of the modules. This problem appeared when Travis-CI attempted to build the project on Linux. It worked fine before I refactored stuff, but tracing which exact header files were included is difficult.
In an attempt to replicate the problem locally, I installed an Ubuntu VM with the default gcc and was able to reproduce it. Here's the relevant source:
#include <stddef.h>
int main()
{
size_t a = SIZE_MAX;
}
The command line is simply:
g++ a.cpp
The error is:
a.cpp: In function ‘int main()’:
a.cpp:5:16: error: ‘SIZE_MAX’ was not declared in this scope
System info:
$ uname -a
Linux quartz 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
I have tried including cstdint, stdint.h, limits.h, inttypes.h, stdio.h, stdlib.h, and probably some others, and I can't figure out which specific header file I need for SIZE_MAX.
It is important to note that the program I'm working on compiled fine, with SIZE_MAX used in various places, before I made some changes. The changes I made caused it to become undefined in one .cpp source file where it was used (the others continue to be fine). So there exists some header file on my system where it is correctly defined.
It's likely that some header defined __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS before stdint.h was included.
Compiling on Linux with g++ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS a.cpp should fix this issue on the older compilers.
If you'd like to learn more about these macros...
18.4.1 Header <cstdint> synopsis
The header also defines numerous macros of the form:
INT_[FAST LEAST]{8 16 32 64}_MIN
[U]INT_[FAST LEAST]{8 16 32 64}_MAX
INT{MAX PTR}_MIN
[U]INT{MAX PTR}_MAX
{PTRDIFF SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
SIZE_MAX
EDIT
In the current C++11/14 standard, SIZE_MAX is introduced and mentioned only in <cstdint>. It is also part of C99, of which specification C++11 fully includes via the <cxxx> headers. So it seems it was not defined prior to C++11.
Which C++ standard header defines SIZE_MAX?
Its supposed to be defined in <cstdint>, but its optional.
Here are the results on Fedora 22 with GCC 5.1:
#include <cstdint>
// use SIZE_MAX
Results in:
g++ -DNDEBUG -g -O2 -fPIC -march=native -pipe -c filters.cpp
In file included from /usr/include/c++/5.1.1/cstdint:35:0,
from filters.cpp:14:
/usr/include/c++/5.1.1/bits/c++0x_warning.h:32:2: error: #error This file requires
compiler and library support for the ISO C++ 2011 standard. This support is currently
experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support for the \
^
filters.cpp: In constructor ‘Filter::Filter(BufferedTransformation*)’:
filters.cpp:305:36: error: ‘SIZE_MAX’ was not declared in this scope
: Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_M
^
It was simply easier to do the following, and stop worrying about non-portable optional-ness that still causes problems in 2015.
#include <limits>
#ifndef SIZE_MAX
# ifdef __SIZE_MAX__
# define SIZE_MAX __SIZE_MAX__
# else
# define SIZE_MAX std::numeric_limits<size_t>::max()
# endif
#endif
Trying __SIZE_MAX__ gets you back to the compile time constant that you probably crave. You can see if its defined in the preprocessor with cpp -dM < /dev/null | grep __SIZE_MAX__.
(And how/why numeric_limits<size_t>::max() is not a compile time constant is another C++ mystery, but that's a different problem).

Anonymous namespace causes undefined reference here - works there

I've written some C++ code for an embedded system which works like a charm. The current task is to emulate the behaviour of this device on a PC. Some of the code has to be ported: For a first test I'm using mingw (g++) while the Embedded system is an STM32 and uses the KEIL µVision toolchain.
I've run into a problem that is not really related to functional behaviour rather than a compiler specific weirdness. I have 2 classes defined in an anonymous namespace because they are included throughout the whole project. Now on the embedded device this compiles and runs without a problem. g++ complains about an undefined reference!
When I remove the anonymous namespace arround the class it compiles and runs! But why? Here is some example code that reproduces the situation:
main.cpp:
#include "notmain.h"
#include "theclass.h"
A *ourA=NULL;
int main()
{
theA = new A();
theA->dostuff(1024);
sunshine sun;
sun.Init();
}
notmain.cpp:
#include "notmain.h"
#include "theclass.h"
void sunshine::Init()
{
theA->dostuff(127);
}
notmain.h:
#ifndef NOTMAIN_H_
#define NOTMAIN_H_
class sunshine
{
public:
void Init();
};
#endif
theclass.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stdio.h>
#define theA ourA
namespace
{
class A
{
public:
void dostuff(int b)
{
a = b;
printf("Hello: %d\n",a);
}
private:
int a;
};
}
extern A *ourA;
#endif
Compiler/Linker Output:
09:09:57 ** Incremental Build of configuration Debug for project Testo **
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "..\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o notmain.o "..\notmain.cpp"
g++ -o Testo.exe notmain.o main.o
notmain.o: In function ZN8sunshine4InitEv':
D:\Projekte\Testo\Debug/../notmain.cpp:6: undefined reference toourA'
collect2.exe: error: ld returned 1 exit status
09:09:57 Build Finished (took 702ms)
Removing that namespace fixes the problem but why does it compile, link, work in KEIL? Can anyone explain this to me?
I would suggest that that is an abuse of the anonymous namespace feature. It does exactly the opposite of what you are trying to achieve.
Anonymous namespaces are used to localise a definition to a single translation unit. If you place one in a header file, then include that header in multiple translation units, that will result in multiple independent definitions in your code.
What is happening here VC++ is that a global ourA has been instantiated as a pointer to one local definition of A defined in main.cpp, then later that local definition is no longer visible but is distinct from the currently visible local version in notmain.cpp. The name mangling of ZN8sunshine4InitEv distinguishes between independent definitions, but name mangling is compiler defined, and I guess ARM's RealView compiler (used by uVision) has a different scheme that fails to spot this error.
It is unclear in fact what the result if this error is in RealView, but it cannot be correct or at least well defined.
RealView is in fact rather poor at issuing warnings that other compilers do normally, and is somewhat permissive when it comes to undefined behaviour I have found. It is always worth using another toolchain such as MinGW/GCC with -Werror -Wall or using a static analysis tool to clean up your code.
To solve this problem you should use an explicitly named namespace, or no namespace at all.

Standard library header hierarchy

Follow up to my answer to this question: SIGSEGV on declaration
In this question the questioner had a problem with a segmentation fault on some simple code. As it turned out it didn't even compile for me and others. GCC (4.8.1) gave an error due to redeclaration of a variable with name bsearch, which happens to be identical to a function name in std. This resulted in a clash as the code also used using namespace std;. Since the questioner accepted my answer I guess this was somehow related with the runtime error (though strange).
The questioner however said the code would compile fine on codeblocks and others confirmed this. bsearch should be defined in cstdlib, but the code did not include it.
It turned out that gcc includes cstdlib if iostream is included anyway as one can see from the trace:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -Wall -Wextra -pedantic -MMD -MP -MF"src/Test.d" -MT"src/Test.d" -o "src/Test.o" "../src/Test.cpp"
../src/Test.cpp:14:27: error: ‘long long int bsearch’ redeclared as different kind of symbol
long long int bsiter,bsearch;
^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/cstdlib:72:0,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/ext/string_conversions.h:41,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/basic_string.h:2815,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/string:52,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/locale_classes.h:40,
src/subdir.mk:18: recipe for target 'src/Test.o' failed
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/bits/ios_base.h:41,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/ios:42,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/ostream:38,
from /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.1/include/g++-v4/iostream:39,
from ../src/Test.cpp:1:
/usr/include/stdlib.h:754:14: error: previous declaration of ‘void* bsearch(const void*, const void*, size_t, size_t, __compar_fn_t)’
extern void *bsearch (const void *__key, const void *__base,
^
make: *** [src/Test.o] Error 1
It does so only in c++0x and c++11 mode.
Is this structure of includes required, allowed or defined at all in the c++ standards? On cplusplus.com I can find that iostream will include ostream and ios, but there is no information about includes further down.
The C++ standard mandates in certain places that another header has to be included (e.g., <iostream> has to include <istream> and <ostream>). Otherwise, the standard allows headers to be included and to make declaration available which are not required to become available from a specific header.
I'd think it would be useful to have a system of headers which make exactly those declarations available that are required to be made available but I'm not aware of that being available. These headers could be without actual definitions and would only be used to verify that all necessary headers are included. It might be better to have the headers be part of an actual implementation but that would make the declarations quite a bit more complex.