Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating an error if checked boolean macro is not defined

Tags:

c++

c

gcc

macros

I have several configuration files each one containing the definition of some boolean macro, to be set to 0 or 1. Then, in my code, I check the value of such a macro to decide which part of the code to activate. Now comes the tricky part: I want to be sure that the header containing the definition of my macro has been included.

In the following example, if I forget to include the header file containing FOO definition, the compiler will print "world!", while I would like instead that it generated an error.

//in the configuration header file
#define FOO 1

//in a cpp file
#if FOO  //I would like this to generate an error if I forgot to include the header file
#pragma message "Hello"
#else
#pragma message "world!"
#endif

Is it possible to achieve such a behaviour? How?

To clarify, I am not asking how to generate an error if a macro is not defined, but if it is possible to transform the #if FOO line so that, at the same time, it checks the boolean value and generates an error if FOO is not defined.

The point of having this would be that developers would know that their code should contain

SPECIAL_MACRO(FOO)

which, at the same time, check the boolean value of FOO as if it was an #if FOO statement, and prevents them from forgetting the inclusion of the header defining FOO.

like image 511
Antonio Avatar asked Nov 17 '15 14:11

Antonio


4 Answers

Colleagues (hi Hartmut, Kurt) who maintained a large code base which was extensively configured with #defines ran exactly into the same problem. A simple mis-spelling, possibly in a make file, could result in subtle errors which were hard to track down. Their solution: Use function macros! In

#if SOME_COND()
 // ...
#endif

the compiler complains if SOME_COND() is not defined, as opposed to a simple SOME_COND which will be replaced by 0 if undefined. I like it because it can be used to transport several values without cluttering the code up with additional #ifdefs.

like image 162
Peter - Reinstate Monica Avatar answered Nov 18 '22 15:11

Peter - Reinstate Monica


The accepted answer of using function-macros is good, but if you want to keep normal macros - and still use the value of FOO if defined and generate an error otherwise you could do:

#if FOO / defined(FOO)
#else
#endif

If FOO is not defined it will trigger integer division by zero.

like image 24
Hans Olsson Avatar answered Nov 18 '22 13:11

Hans Olsson


What about using the -Wundef gcc preprocessor option? This will only generate a warning, which can easily be turned to an error with -Werror=undef.

like image 3
calandoa Avatar answered Nov 18 '22 14:11

calandoa


Macro CHECK(x) will:

  • fail if macro x is undefined,
  • evaluate to 00 if x is defined to 0
  • evaluate to 01 if x is defined to 1
$ cat main.cpp
#define CAT(x, y) x##y
#define CHECK(x) CAT(0, x)

// usage

#define COND0 0
#define COND1 1

#if CHECK(COND)
#endif

#if CHECK(COND0)
#pragma message "defined 1"
#else
#pragma message "defined 0"
#endif

#if CHECK(COND1)
#pragma message "defined 1"
#else
#pragma message "defined 0"
#endif

$ g++ main.cpp
main.cpp:9:1: error: user-defined literal in preprocessor expression
    9 | #if CHECK(COND)
      | ^~~~~
main.cpp:15:17: note: ‘#pragma message: defined 0’
   15 | #pragma message "defined 0"
      |                 ^~~~~~~~~~~
main.cpp:19:17: note: ‘#pragma message: defined 1’
   19 | #pragma message "defined 1"
      |                 ^~~~~~~~~~~
like image 2
pkarnakov Avatar answered Nov 18 '22 14:11

pkarnakov