Forward-define a pragma for GCC - c

I am looking for a solution to forward-declare/define a pragma for GCC.
I use message pragmas as todo list (#pragma message "do this and that").
However, i would like the option to enable/disable the messages completely by a construct as follows:
Warning, this is pseudo-code:
// Definition
#if 1 // generate todo list
#define ADD_TODO(msg) #pragma message "[todo]" msg
#else
#define ADD_TODO(msg) /*empty*/
#endif
// Usage
ADD_TODO("this may result in unitialized variables, fix this")
Has someone experience with such constructs?

You want the _Pragma preprocessing operator (introduced in C99):
// Definition
#define PRAGMA(...) _Pragma(#__VA_ARGS__)
#if 1 // generate todo list
#define ADD_TODO(msg) PRAGMA( message "[todo]" msg)
#else
#define ADD_TODO(msg) /*empty*/
#endif
// Usage
ADD_TODO("this may result in unitialized variables, fix this")
The operator solves the problem of not being able to use preprocessor directives (such as #pragma) inside a #define). It takes a string-literal argument, which is quite impractical to construct by hand, and that is why you'll pretty much always see it wrapped in macro that constructs the string using the # (stringification) operator as shown in the above snippet.

Related

Print a deprecation warning when using a macro in a #if statement

I want to deprecate a macro in such a way that it will print a nice warning even if used inside of a #if statement.
This answer is very nearly what I want, but it throws an error when the macro is accessed from within a #if statement.
#include <stdio.h>
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") 0
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT
return 1;
#else
return 2;
#endif
}
The error is:
error: missing binary operator before token "("
Bonus points if you can find me a cross-platform compatible solution!
EDIT
I'm trying to handle a breaking change in a library gracefully - I want users to have a nice, clear warning (or error) whenever they use an old macro, so it will be clear that they need to migrate their code to using the new macro. These pragma solutions only work if the value of that constant is used in code, not if the value is accessed in a preprocessor directive.
According to the answers provided below, it seems like there's not a solution to this problem (except possibly when using clang?). Thanks, everyone.
I want to deprecate a macro in such a way that it will print a nice
warning even if used inside of a #if statement.
I was going to suggest the comma operator, but that doesn't seem to work because the _Pragma macro probably yields no real code. Also, gcc, at least, explicitly says you can't do what you suggested with _Pragma():
https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
The standard is unclear on where a _Pragma operator can appear. The
preprocessor does not accept it within a preprocessing conditional
directive like ‘#if’. To be safe, you are probably best keeping it out
of directives other than ‘#define’, and putting it on a line of its
own.
PS - clang 8.1.0 didn't error on your program and gave the warnings you want ...
As #jschultz410 mentions, what you are trying to do is explicitly forbidden in gcc (see https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html).
Nested macros seem appropriate for such a use case:
#include <stdio.h>
#define DEPRECATED_CONSTANT_VALUE 0
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") DEPRECATED_CONSTANT_VALUE
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT_VALUE
return 1;
#else
return 2;
#endif
}
Yes, this is kind of gross, but in the land of preprocessor logic we're already giving up on any kind of design elegance in the first place. At least this way the macro interface is maintained in non-preprocessor code. (Yes, this would not print the preprocessor warning in the #if statement, but unfortunately that's not possible with gcc).

Check for concatenated define in C preprocessor

I access registers by concatenated defines unsing the function GETREG
#define NUMBER 1 //changes
#define REG1 register.N1
#define REG2 register.N2
#define REG8 register.N8
#define GETREG_(N) REG ## N
#define GETREG(N) GETREG_(N)
Sometimes the registers for that NUMBER are not defined so i want to make sure the macro correctly expands before inserting it in the code so i tried to do:
#define NUMBER 5
#ifdef GETREG(NUMBER)
GETREG(NUMBER) = 0
#endif
However this always seems to evaluate as true and the compiler prints
Warning:extra tokens at end of #ifdef directive
Background Story:
In my projects I create libraries to interface with a HAL to abstract the hardware level. Often from one project to another the codebasis in the HAL stays exactly the same but just the location of pins changes. For that reason i would like to use macro-expansion to access the pins. The following macro does the job for me at adressing the analog features of the pin:
#define ANSEL_(Pin) _ANS ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
that way i can turn on or off analog features by:
#define PIN_RX A0
ANSEL(PIN_RX)= 0;
and other registers by similar macros. The problem i am facing now is that some pins for example do not have analog features (e.g. Pin A5). Because of that i would like to test if the define in the library esists. I was tryin to do this by:
#ifdef ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
However this simple approach is not working.
The microcontroller (PIC33) lib:
Edit: Shipped from the manufactorer
#define ANSELA ANSELA
extern volatile unsigned int ANSELA __attribute__((__sfr__));
typedef struct tagANSELABITS {
unsigned ANSA0:1;
unsigned ANSA1:1;
unsigned ANSA2:1;
unsigned ANSA3:1;
unsigned ANSA4:1;
unsigned :4;
unsigned ANSA9:1;
} ANSELABITS;
extern volatile ANSELABITS ANSELAbits __attribute__((__sfr__));
/* ANSELA */
#define _ANSA0 ANSELAbits.ANSA0
#define _ANSA1 ANSELAbits.ANSA1
#define _ANSA2 ANSELAbits.ANSA2
#define _ANSA3 ANSELAbits.ANSA3
#define _ANSA4 ANSELAbits.ANSA4
#define _ANSA9 ANSELAbits.ANSA9
You have the wrong expectation for the behavior of the #ifdef directive. That directive is equivalent to #if defined, where defined is a preprocessing operator in that context. Although the condition of an overall #if directive is evaluated only after the line is fully macro-expanded, the defined operator operates on the next preprocessing token, which must have the form of an identifier, before macro expansion:
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator) [...]
[C2011, 6.10.1/4]
Thus, your
#ifdef GETREG(NUMBER)
tests whether GETREG is a defined macro, and the (NUMBER) constitutes a sequence of unexpected extra tokens.
The defined operator therefore cannot serve your purpose. It is conceivable that there is a way to use a more general #if directive to achieve your aim, but I'm not seeing it at the moment. Instead, I'm inclined to suggest letting the compiler find such errors for you, instead of expecting the preprocessor to do it. If compile time is too late, then perhaps you need to look to a build configuration system such as the Autotools or CMake could help you create.
You can do more or less what you want if you are prepared to use two #defines instead of one for each pin:
#define HAS_ANS_A0 1
#define ANS_A0 ANSELAbits.ANSA0
#define HAS_ANS_A1 1
#define ANS_A1 ANSELAbits.ANSA1
#define HAS_ANS_A5 1
#define ANS_A5 ANSELAbits.ANSA5
#define HAS_ANSEL_(Pin) HAS_ANS_ ## Pin
#define HAS_ANSEL(...) HAS_ANSEL_(__VA_ARGS__)
#define ANSEL_(Pin) ANS_ ## Pin
#define ANSEL(...) ANSEL_(__VA_ARGS__)
#if HAS_ANSEL(PIN_RX)
ANSEL(PIN_RX)= 0;
#endif
This works because in an #if, an undefined identifier token (that is, an identifier token which has not been #defined) has the value 0. It is not an error, or even a warning.
Note: I changed the symbols starting _ANS to conform with §7.1.3 (Reserved Names), paragraph 1:
All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

#define IDENTIFIER without a token

What does the following statement mean:
#define FAHAD
I am familiar with the statements like:
#define FAHAD 1
But what does the #define statement without a token signify?
Is it that it is similar to a constant definition?
Defining a constant without a value acts as a flag to the preprocessor, and can be used like so:
#define MY_FLAG
#ifdef MY_FLAG
/* If we defined MY_FLAG, we want this to be compiled */
#else
/* We did not define MY_FLAG, we want this to be compiled instead */
#endif
it means that FAHAD is defined, you can later check if it's defined or not with:
#ifdef FAHAD
//do something
#else
//something else
#endif
Or:
#ifndef FAHAD //if not defined
//do something
#endif
A real life example use is to check if a function or a header is available for your platform, usually a build system will define macros to indicate that some functions or headers exist before actually compiling, for example this checks if signal.h is available:
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif/*HAVE_SIGNAL_H*/
This checks if some function is available
#ifdef HAVE_SOME_FUNCTION
//use this function
#else
//else use another one
#endif
Any #define results in replacing the original identifier with the replacement tokens. If there are no replacement tokens, the replacement is empty:
#define DEF_A "some stuff"
#define DEF_B 42
#define DEF_C
printf("%s is %d\n", DEF_A, DEF_B DEF_C);
expands to:
printf("%s is %d\n", "some stuff", 42 );
I put a space between 42 and ) to indicate the "nothing" that DEF_C expanded-to, but in terms of the language at least, the output of the preprocessor is merely a stream of tokens. (Actual compilers generally let you see the preprocessor output. Whether there will be any white-space here depends on the actual preprocessor. For GNU cpp, there is one.)
As in the other answers so far, you can use #ifdef to test whether an identifier has been #defined. You can also write:
#if defined(DEF_C)
for instance. These tests are positive (i.e., the identifier is defined) even if the expansion is empty.
#define FAHAD
this will act like a compiler flag, under which some code can be done.
this will instruct the compiler to compile the code present under this compiler option
#ifdef FAHAD
printf();
#else
/* NA */
#endif

Is there a way to both check a macro is defined and it equals a certain value at the same time

I regularly use object-like preprocessor macros as boolean flags in C code to turn on and off sections of code.
For example
#define DEBUG_PRINT 1
And then use it like
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
However, it comes a problem if the header file that contains the #define is forgotten to be included in the source code. Since the macro is not declared, the preprocessor treats it as if it equals 0, and the #if statement never runs.
When the header file is forgotten to be included, non-expected, unruly behaviour can occur.
Ideally, I would like to be able to both check that a macro is defined, and check that it equals a certain value, in one line. If it is not defined, the preprocessor throws an error (or warning).
I'm looking for something along the lines of:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
It's like a combination of #ifdef and #if, and if it doesn't exist, uses #error.
I have explored a few avenues, however, preprocessor directives can't be used inside a #define block, and as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
This may not work for the general case (I don't think there's a general solution to what you're asking for), but for your specific example you might consider changing this sequence of code:
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
to:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
It's no more verbose and will fail to compile if DEBUG_PRINT is not defined or if it's defined to be something that cannot be compared with 1.
as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
It can't be an error because the C standard specifies that behavior is legal. From section 6.10.1/3 of ISO C99 standard:
After all replacements due to macro expansion and the defined unary
operator have been performed, all remaining identifiers are replaced with the pp-number
0....
As Jim Balter notes in the comment below, though, some compilers (such as gcc) can issue warnings about it. However, since the behavior of substituting 0 for unrecognized preprocessor tokens is legal (and in many cases desirable), I'd expect that enabling such warnings in practice would generate a significant amount of noise.
There's no way to do exactly what you want. If you want to generate a compilation failure if the macro is not defined, you'll have to do it explicitly
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
for each source file that cares. Alternatively, you could convert your macro to a function-like macro and avoid using #if. For example, you could define a DEBUG_PRINT macro that expands to a printf call for debug builds but expands to nothing for non-debug builds. Any file that neglects to include the header defining the macro then would fail to compile.
Edit:
Regarding desirability, I have seen numerous times where code uses:
#if ENABLE_SOME_CODE
...
#endif
instead of:
#ifdef ENABLE_SOME_CODE
...
#endif
so that #define ENABLE_SOME_CODE 0 disables the code rather than enables it.
Rather than using DEBUG_PRINT directly in your source files, put this in the header file:
#if !defined(DEBUG_PRINT)
#error DEBUG_PRINT is not defined
#endif
#if DEBUG_PRINT
#define PrintDebug([args]) [definition]
#else
#define PrintDebug
#endif
Any source file that uses PrintDebug but doesn't include the header file will fail to compile.
If you need other code than calls to PrintDebug to be compiled based on DEBUG_PRINT, consider using Michael Burr's suggestion of using plain if rather than #if (yes, the optimizer will not generate code within a false constant test).
Edit:
And you can generalize PrintDebug above to include or exclude arbitrary code as long as you don't have commas that look like macro arguments:
#if !defined(IF_DEBUG)
#error IF_DEBUG is not defined
#endif
#if IF_DEBUG
#define IfDebug(code) code
#else
#define IfDebug(code)
#endif
Then you can write stuff like
IfDebug(int count1;) // IfDebug(int count1, count2;) won't work
IfDebug(int count2;)
...
IfDebug(count1++; count2++;)
Yes you can check both:
#if defined DEBUG && DEBUG == 1
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
In this example even when #define DEBUG 0 but it is not equal to 1 thus nothing will be printed.
You can do even this:
#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
Here if you #define DEBUG 0 and then D(1,2,3) also nothing will be printed
DOC
Simply create a macro DEBUG_PRINT that does the actual printing:
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
If the macro isn't defined, then you will get a compiler error because the symbol is not recognized.
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
So when "if 0" it'll do nothing and when "if 1" it'll execute the defined macro.

Using if clause instead of processor #ifdef

I am using a #ifdef block to conditionally include a block of code based on -Dflag passed to the compiler.
Is there a way to implement this with an if?
Something along the lines of:
if (defined(flag)) {
}
You use preprocessor to produce a different flag, which could be tested with a run-time if statement, like this:
#ifdef flag
#define flag_defined 1
#else
#define flag_defined 0
#endif
Now you can do this:
if (flag_defined) ...
If you define a macro so that it evaluates to either zero or nonzero, then you can use it in the condition of the if statement. Since it's a compile-time constant, in case it's zero, the dead code eliminator pass in the compiler will remove the unreachable code anyway.
If you are willing to give flag a value (0 or 1) instead of defining it or not, you can do
cc -Dflag=1 file.c
with
if (flag) { ... }
without messing up your code with ugly #ifdefs. You are also protected against forgetting to define flag at all: in this case your compiler treats flag as an identifier. Since you never declared it, you'll get a compile time error about an undeclared or undefined symbol flag.
No, you can't use a C if statement to check if a preprocessor token is defined.
You can use one of these forms though
#ifdef flag
...
#endif
#if defined(flag)
...
#endif
You can however check if the token evaluates to a true/false C expression,
if you use -Dflag=1 you can do
if (flag) {
...
}
And if you want to turn it off, you can define the macro as -Dflag=0
Following this you can define a new preprocessor token that you can check with a C if statement. e.g.
#ifdef flag
#define FLAG_SET 1
#else
#define FLAG_SET 0
#endif
if(FLAG_SET) { //the flag macro was defined
...
}
If all you want to do is is check whether the flag is defined, there's no point to all of this, just use #ifdef. With a C if statement, the most C compilers will optimize away the code, there's nothing you could change at runtime to get any benefit of not using the preprocessor.
#ifdef FLAG
#define FLAG_VALUE 1
#else
#define FLAG_VALUE 0
#endif
int flag = FLAG_VALUE;
...
if(flag)
{
....
}
Alternatively just use -DFLAG_VALUE=1 or -DFLAG_VALUE=0 as appropriate and use FLAG_VALUE directly.
If you plan on being able to change the FLAG_VALUE at runtime you will need a variable. If you change in non-obvious ways (e.g. via a debugger or through other loader trickery) make sure to declare it volatile, otherwise the compiler might be able to do dead-code elimination and remove huge chunks of code.
Also, if you don't plan on changing the value of flag after initializing, then you should probably make it const.

Resources