Compiler warning/error when using #if on something that is undefined - c++

Consider the following example:
#define FOO false
#if FOO
void foo(){}
#endif
Obviously, foo() does not exist. But when I forget to define FOO, the result is the same:
#if FOO
void foo(){}
#endif
Is there any way to have foo() {} conditionally, depending on FOO, but automatically yielding a warning or error when FOO has not been defined at all? (I.E. Without manually using something like #ifndef FOO - #error)

Also, although using an undefined macro is not an error (it evaluates to 0), you can make it one by adding the following to your GCC or Clang command line:
-Wundef -Werror
But note that all warnings will now be treated as errors, and you will become reliant on build settings. So I prefer the explicit approach of #else and an #error directive if you intend to rely on this to catch bad configurations.

You might do the following:
#if defined(FOO)
void foo() {}
#else
#error FOO is not defined
#endif
This code will not compile if FOO is not defined. The compiler will report an error.

You can use a macro function and then there will be a warning:
#define FOO() false
#if FOO()

Related

How to avoid warning from nested deprecated function call?

I support a C++ library, and want to declare a number of legacy functions as deprecated. Unfortunately, these functions call one another, and I receive warnings from their compilation. For example:
[[deprecated]] void foo();
[[deprecated]] void bar() { foo(); }
I would like to avoid a warning about calling deprecated function from bar() body compilation, but still has that warning if some outside function (not marked as deprecated) calls foo() or bar(). Is it somehow possible?
While this does not work for OP's circumstance as posted, on account of bar() invoking foo() from within the library's header, there is a straightforward solution that is applicable to anyone facing the same issue without that specific constraint. So it could be useful to other people landing here.
Effectively, you want two different sets of headers. One when users of the library use it, and one when the library itself uses it. We can do this in this case because [[deprecated]] is not supposed to have any influence on the resulting generated code.
You "could" just maintain both of them separately, but that would obviously be very fragile. Thankfully, the language does provide us with a way to have two "versions" of the same header in one single file: The oft-maligned, and to be fair also oft-misused, Macro.
As a bonus, if [[deprecated]] happens to be what forces users to use C++14 or above, you can provide support for older versions of the standard at the same time by checking __cplusplus or the appropriate feature macro.
//mylib.h
#if !defined(MY_LIB_NO_DEPRECATE) && __has_cpp_attribute(deprecated)
#define MY_LIB_DEPRECATED [[deprecated]]
#else
#define MY_LIB_DEPRECATED
#endif
// ...
MY_LIB_DEPRECATED void foo();
MY_LIB_DEPRECATED void bar();
// ...
#undef MY_LIB_DEPRECATED
Compile the library with -DMY_LIB_NO_DEPRECATE, and it's like the deprecation warnings are not there for that specific phase of the process. Users will still get all the deprecation warnings, unless they explicitly opt out of them by also defining MY_LIB_NO_DEPRECATE.
Don't get spooked by the use of macros here. Using them to distinguish between internal/external versions of the same header is a common and well established practice. Windows dlls would be practically impossible to write without it.
In OP's case, if moving bar()'s definition from the header into the library's implementation is a possibility, then they should be good to go as well.
You can ignore the deprecation warnings. It's not technically portable, but it works on all 4 major compilers, at least:
#if defined(__GNUC__)
#define MY_LIB_IGNORE_DEPRECATED_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define MY_LIB_IGNORE_DEPRECATED_END \
_Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
#define MY_LIB_IGNORE_DEPRECATED_BEGIN \
_Pragma("warning(push)") \
_Pragma("warning(disable : 4996)")
#define MY_LIB_IGNORE_DEPRECATED_END \
_Pragma("warning(pop)")
#else
#define MY_LIB_IGNORE_DEPRECATED_BEGIN
#define MY_LIB_IGNORE_DEPRECATED_END
#endif
You can do it library-wide:
MY_LIB_IGNORE_DEPRECATED_BEGIN
[[deprecated]] void foo();
[[deprecated]] void bar() { foo(); }
MY_LIB_IGNORE_DEPRECATED_END
Or you can guard just the offending calls:
[[deprecated]] void foo();
[[deprecated]] void bar()
{
MY_LIB_IGNORE_DEPRECATED_BEGIN
foo();
MY_LIB_IGNORE_DEPRECATED_END
}

How to trigger a warning when a certain function is called (not compiled)?

If we write:
void foo() {
#warning "Danger Will Robinson!"
}
we'll get a warning when compiling foo(). Now, What I want to do is for the compilation not to emit a warning, but for a warning to be emitted if foo() is called.
Is that possible, using g++ and/or clang++?
Note: This question is somewhat similar to this one, about marking functions as "deprecated" (a-la C++14's [[deprecated]] attribute). However, it's a different semantic. I do not want people to get the notion that my function is deprecated, but rather get a custom warning.
C++11 added _Pragma, which is like #pragma but macros can expand to it. So, you can make a macro, that expands to this warning and the function:
#include <cstdio>
void foo() {
std::puts("foo is called!");
}
#define foo(...) _Pragma("message \"Danger Will Robinson!\"") \
foo(__VA_ARGS__)
int main() {
foo();
}
The main issue with this approach is that it will not respect overloads and warn on any function with the name foo.
A suggestion from #StoryTeller in the comments, which works - partially - in GCC:
__attribute__ ((warning ("Danger Will Robinson!")))
void foo() { }
int bar() {
const int x = 123;
foo();
return x;
}
Why "partially"? As #StoryTeller says:
Dead code elimination can remove the warning should the call be on the eliminated branch
Have look at This GodBolt example: When you enable optimizations so that the function is inlined - the warning attribute is ignored.

Better way to nullify debug functions in C++

My program used many #ifdef _DEBUG_ ... #endif blocks, to nullify the debugging functions for the release build.
However, it clogs the codes, and makes the codes unpleasant to read.
Is there any better way?
One way I can think of is to nullify it by define the function to empty, such as:
#ifdef _DEBUG_
void foo(int bar)
{
do_somthing();
}
#else
#define foo(a) do {; } while(0)
#endif
So that we have only one #ifdef _DEBUG_ ... #endif. All the places where foo() is called, we don't have to add #ifdef _DEBUG_ ... #endif.
However, there are exceptions:
When a debug function has a return value, the above strategy will not work. e.g. the codes calling the function may be in this pattern: bar = foo();
When a debug function is in the form of a member function of a class, again, the above said strategy will not work.
Any idea?
How about moving the #ifdef's into the function itself? i.e.
// In a .h file somewhere...
inline int foo(int bar)
{
#ifdef DEBUG
return do_something();
#else
(void) bar; // this is only here to prevent a compiler warning
return 1; // or whatever trivial value should be returned when not debugging
#endif
}
... as long as the function can be inlined (i.e. as long as the function body is in a header file), the compiler will optimize it all away in the non-DEBUG case, so there shouldn't be any additional overhead in the non-debug build from doing it this way.
If the function is too big to inline normally, Jeremy's solution won't work and you'd still need the two definitions.
// In .h file
#ifndef NDEBUG
int foo(int bar); // Definition in .cpp file
#else
inline int foo(int) {
return 42;
}
#endif
Note that by assert convention, NDEBUG is defined for release builds.

Define a macro then undefine it if it was previously undefined

I'm including header files which require certain pro-processor #defines to be present, however I do not want this to pollute the rest of my code e.g.:
// FOO may or may not already be defined here
#define FOO
#include "Bar.h"
#undef FOO
// FOO should be defined or not, as per the starting state
I'm thinking along the lines of:
#ifdef FOO
#define FOO_DEFINED
#endif
#define FOO
#include "Bar.h"
#ifndef FOO_DEFINED
#undef FOO
#else
#undef FOO_DEFINED
#endif
Questions:
Will the above work i.e. restore all macro definitions (or lack of) to the state they were in beforehand?
Is there perhaps a simpler solution?
Does it matter if FOO was already defined when I #define it? Should I add another #ifndef to protect against this?
It appears that in your example, Bar.h cares only whether FOO is defined or not, and not the actual expression bound to it. Furthermore, if someone else (I presume your code example is, itself, in a header file) defines FOO and cares about the expression bound to it, you don't want to make the mistake of redefining FOO with an empty expression. If so, you might want to simplify:
#ifndef FOO
#define FOO
#define UNDEF_FOO
#endif
#include "Bar.h"
#ifdef UNDEF_FOO
#undef FOO
#endif
yes it should work.
I have #pragma push_macro/pop_macro("macro_name") in mind, but it might work only in gcc and MS VC++
yes, it matters, you'll get a warning if it is defined again with a different value. As you state, you can shield it with #ifndef.

suppress warnings on multiple compiler builds

Is there a generic suppress warning that i can use?
The problem is that there are times i may build using one compiler version (gcc) and then i have a partner that uses some of the common things but uses a different compiler. So the warning # are different.
The only way i could think of doing was making a macro that was defined in a file that i would pass in some generic value:
SUPPRESS_WARNING_BEGIN(NEVER_USED)
//code
SUPPRESS_WARNING_END
then the file would have something like:
#if COMPILER_A
NEVER_USED = 245
#endif
#if COMPILER_B
NEVER_USED = 332
#endif
#define SUPPRESS_WARNING_BEGIN(x) /
#if COMPILER_A
//Compiler A suppress warning x
#endif
#if COMPILER_B
//Compiler B suppress warning x
#endif
#define SUPPRESS_WARNING_END /
#if COMPILER_A
// END Compiler A suppress warning
#endif
#if COMPILER_B
// END Compiler A suppress warning
#endif
Don't know if there is an easier way? Also i know ideally we all would just use the same compiler but that is unfortunately not an option. Just trying to find the least complicated way to support something like this and am hoping there is a simpler way then mentioned above.
thanks
There's no portable way to do that. Different compilers do it in different ways (e.g. #pragma warning, #pragma GCC diagnostic, etc.).
The easiest and best thing to do is to write code that does not generate any warnings with at compiler at any warning level.
If your goal is to suppress warnings about unused variables, I recommend using a macro:
#define UNUSED(x) ((void)sizeof(x))
...
void some_function(int x, int y)
{
// No warnings will be generated if x is otherwise unused
UNUSED(x);
....
}
The sizeof operator is evaluated at compile-time, and the cast to void produces no result, so any compiler will optimize the UNUSED statement away into nothing but consider the operand to be used.
GCC also has the unused attribute`:
// No warnings will be generated if x is otherwise unused
int x __attribute__((unused));