-Wundef is not being ignored with pragma in g++ - c++

Given the following code:
#if MACRO_WITHOUT_A_VALUE
int var;
#endif
int main(){}
When compiled with, g++ -std=c++1z -Wundef -o main main.cpp,
it produces the following warning:
main.cpp:1:5: warning: "MACRO_WITHOUT_A_VALUE" is not defined [-Wundef]
#if MACRO_WITHOUT_A_VALUE
^
I'd like to keep the warning flag enabled, but suppress this particular instance.
I apply the following:
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wundef"
#pragma GCC diagnostic push
#endif
#if MACRO_WITHOUT_A_VALUE
int var;
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
int main(){}
This only solves the problem in clang++.
The command clang++ -std=c++1z -Wundef -o main main.cpp builds without warnings.
The command g++ -std=c++1z -Wundef -o main main.cpp builds with the same [-Wundef] warning as before.
How can I suppress -Wundef warnings in g++?
g++ (Ubuntu 5.1.0-0ubuntu11~14.04.1) 5.1.0
clang version 3.8.0

What I've done before when third party headers were inducing warnings was to wrap them in my own private header that uses #pragma GCC system_header to just silence all the warnings from that header. I use my own wrapper to keep the includes neat and allow for an additional customization point in the future if needed.

This isn't disabling the warning, but fixing the preprocessor code to avoid it.
The below tests are based on a similar issue here, using clang -Weverything...
#define ZERO 0
#define ONE 1
#define EMPTY
// warning: 'NOTDEFINED' is not defined, evaluates to 0 [-Wundef]
#if NOTDEFINED
#warning NOTDEFINED
#endif
// false
#if ZERO
#warning ZERO
#endif
// true
#if ONE
#warning ONE
#endif
// error: expected value in expression
#if EMPTY
#warning EMPTY
#endif
// false
#if defined(NOTDEFINED) && NOTDEFINED
#warning NOTDEFINED
#endif
// false
#if defined(ZERO) && ZERO
#warning ZERO
#endif
// true
#if defined(ONE) && ONE
#warning ONE
#endif
// error: expected value in expression
#if defined(EMPTY) && EMPTY
#warning EMPTY
#endif
The one liner #if defined(SOME_MACRO) && SOME_MACRO can avoid this warning. To explicitly handle the case...
#if defined(DEBUG_PRINT)
#if DEBUG_PRINT
... true
#else
... false
#endif
#else
#error DEBUG_PRINT must be defined
#endif
To handle EMPTY see this: How to test if preprocessor symbol is #define'd but has no value?

Related

why doesn't .h file recognize the _cplusplus version I am using?

My .h file has this code for the __cplusplus version in use:
#define CPP14_SUPPORTED (__cplusplus >= 201402L)
#if CPP14_SUPPORTED
#define IS_CPP14_SUPPORTED 1 // BUT THIS IS GREYED OUT in the .h file!
#endif
The main issue is that all my .h files do not see this definition as well.
When I use the definition IS_CPP14_SUPPORTED in my .cpp file it shows that it is true and not greyed out.
I am using keil uvision5 IDE
Try this
#define CPP14_SUPPORTED __cplusplus >= 201402L
#if CPP14_SUPPORTED
#warning "cpp14 supported"
#else
#warning "Cpp14 not supported"
#endif
With -std=c++14 it prints
<source>:3:5: warning: #warning "cpp14 supported" [-Wcpp]
3 | #warning "cpp14 supported"
| ^~~~~~~
With -std=c++11 it prints
<source>:5:5: warning: #warning "Cpp14 not supported" [-Wcpp]
5 | #warning "Cpp14 not supported"
| ^~~~~~~

-Wundef does not warn about an undefined symbol in front of #ifdef

Please consider the following code:
// program.cpp
#include <iostream>
int main() {
#ifdef LINUX
std::cout << "Linux\n";
#elif MAC
std::cout << "Mac\n";
#elif WINDOWS
std::cout << "Windows\n";
#elif BSD
std::cout << "BSD\n";
#else
std::cout << "Something else\n";
#endif
return 0;
}
If I compile it with both clang and gcc,
clang++ -Wundef -DBSD -o program program.cpp
# or
g++ -Wundef -DBSD -o program program.cpp
I will get warnings for not defining symbols MAC and WINDOWS, but no warning for the symbol LINUX:
program.cpp:6:7: warning: 'MAC' is not defined, evaluates to 0 [-Wundef]
#elif MAC
^
program.cpp:8:7: warning: 'WINDOWS' is not defined, evaluates to 0 [-Wundef]
#elif WINDOWS
^
2 warnings generated.
According to the gcc man page:
-Wundef
Warn if an undefined identifier is evaluated in an "#if" directive.
Such identifiers are replaced with zero.
It says in an #if directive. Is it because the LINUX is not inside that structure?
If that's the case, how can I tell compiler to emit warnings for the undefined symbol LINUX?
clang version 12.0.1
gcc (GCC) 11.1.0
Target: x86_64-pc-linux-gnu (artixlinux)
The reason is that your preprocessor code asks if LINUX is defined. But for MAC, WINDOWS and BSD you don’t bother checking whether the symbol is defined; instead, your code assumes it is defined and asks for its value.
Change your code to use #elif defined(…) instead of #elif … to fix the warning.

C++ Compile Error: gnu_printf is an unrecognized format function type

When compiling I am getting the same warning on 3 different lines of code in a .h file such as this:
warning gnu_printf is an unrecognized format function type
My flags look like this:
CFLAGS += -Wall -Wextra -Wformat -Wno-ignored-qualifiers -Wformat-security -Wno-unused-parameter \
Examples of the three lines of code producing this error below:
int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...);
std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...);
bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...);
I have many other uses of printf() in this file that are not producing any errors. I am a bit confused on the error in the formatting.
Apparently the failing code is:
#ifdef __GNUC__
#define ATTR_WARN_PRINTF(X,Y) __attribute__((format(gnu_printf,X,Y)))
#else
#define ATTR_WARN_PRINTF(X,Y)
#endif
int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...);
std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...);
bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...);
It seems that this works on any gcc between versions 4.4.7 and gcc trunk (9.0.0).
GCC 4.1.2 fails with:
<source>:7: warning: 'gnu_printf' is an unrecognized format function type
Also, clang always fails on this:
<source>:7:5: warning: 'format' attribute argument not supported: gnu_printf [-Wignored-attributes]
But from the original question it seems that the issue with a GCC which is too old. To fix this, check GCC version number:
#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
# define ATTR_WARN_PRINTF(X,Y) __attribute__((format(gnu_printf,X,Y)))
#elif defined(__GNUC__)
# define ATTR_WARN_PRINTF(X,Y) __attribute__((format(printf,X,Y)))
#else
# define ATTR_WARN_PRINTF(X,Y)
#endif
Maybe even it is better to restrict the format to printf instead of gnu_printf, and so the above condition can be simplified.
EDIT: As can be found on GCC history, the gnu_printf format was added in gcc-4.4.0
commit r133365. From what I understand, it is merely an alias to printf, and the gnu prefix was added to allow differentiation between printf of different compilers, such as possibly ms_printf.

__extern_inline func results in undefined reference error

When I compile this c++ code with g++ 4.8.5 with -O0 -std=c++11,
#include <stdio.h>
__extern_inline float func(float x) { return x*x; }
int main(int argc, char *argv[])
{
printf("%d\n", func(100));
}
I get this link error
/tmp/ccMiVRIL.o: In function `main':
test.cpp:(.text+0x18): undefined reference to `func(float)'
collect2: error: ld returned 1 exit status
however, if I add -O1 or -O2 to the compiler option, it builds successfully.
Also if I change "__extern_inline" to "extern __inline" or "__extern_always_inline", it also builds. I see similar behavior with clang.
I want to have that code (keep __extern_inline, since the definition lives in a third-party lib and I don't want to touch) to be able to link even under -O0. What can I do? Is there any compiler option or #defines to work this error around?
I've read this document, but it doesn't seem to help for my case
https://clang.llvm.org/compatibility.html#inline
Also it looks like __extern_inline is defined as follows in sys/cdefs.h
#define __extern_inline extern __inline __attribute__ ((__gnu_inline__))
I think it's because following macro in features.h:
/* Decide whether we can define 'extern inline' functions in headers. */
#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
&& !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ \
&& defined __extern_inline
# define __USE_EXTERN_INLINES 1
#endif
As you can see, extern inlines are explicitly allowed only for optimized builds.

Is there a known set of `c++11` features in clang enabled by default not requiring `-std=c++11`?

It appears that clang (3.4) automatically accepts some c++11 (e.g. auto, for(:)) without a special flag (though producing a warning), but not other parts (e.g. lambdas).
For example the following compiles clang++ c++11.success.cpp:
#include <vector>
int main( int argCount, char ** argVec )
{
std::vector<int> vec;
for( auto & item : vec )
{
++item;
}
return 0;
}
but this fails clang++ c++11.failure.cpp:
#include <vector>
int main( int argCount, char ** argVec )
{
std::vector<int> vec;
auto lambda = [] ( int & foo ) { return ++foo; }; //This line fails at []
for( auto & item : vec )
{
lambda( item );
}
return 0;
}
With clang++ c++11.failure.cpp -std=c++11 of course it succeeds.
I couldn't find any specific documentation as to which c++11 features are supported without -std=c++11 and why. Anyone have a clue?
Clang has (as any other C++ compiler) some language extensions (there is a list of C++11 extensions, that are available in C++03). One of this extensions is the range based for loop. You can test it by #if __has_extension(cxx_range_for) .... It will generate a warning anyway (if you do not disable it with -Wno-c++11-extensions). You could test the features with:
#if __has_extension(cxx_range_for)
#warning __has_extension(cxx_range_for) is true
#else
#warning __has_extension(cxx_range_for) is false
#endif
#if __has_feature(cxx_range_for)
#warning __has_feature(cxx_range_for) is true
#else
#warning __has_feature(cxx_range_for) is false
#endif
#if __has_extension(cxx_auto_type)
#warning __has_extension(cxx_auto_type) is true
#else
#warning __has_extension(cxx_auto_type) is false
#endif
#if __has_feature(cxx_auto_type)
#warning __has_feature(cxx_auto_type) is true
#else
#warning __has_feature(cxx_auto_type) is false
#endif
int main()
{
return 0;
}
Curiously this warns, that the type inference extension and feature is off, but it validly compiles the auto pointer (I guess, that this is because of the old meaning of auto as storage class specifier):
main.cpp:2:2: warning: __has_extension(cxx_range_for) is true [-W#warnings]
#warning __has_extension(cxx_range_for) is true
^
main.cpp:10:2: warning: __has_feature(cxx_range_for) is false [-W#warnings]
#warning __has_feature(cxx_range_for) is false
^
main.cpp:16:2: warning: __has_extension(cxx_auto_type) is false [-W#warnings]
#warning __has_extension(cxx_auto_type) is false
^
main.cpp:22:2: warning: __has_feature(cxx_auto_type) is false [-W#warnings]
#warning __has_feature(cxx_auto_type) is false
^
To get fully standard compliant, you should treat warnings as errors by enabling -Werror.