gcc warnings for no-effect statements. - c

I have a logging macro which in release mode becomes:
#define LOG (void)
So statement
LOG("foobar %d", 0xbabecafe);
is expanded to
(void)("foobar %d", 0xbabecafe);
The problem is that the last expression produces an warning under gcc:
warning: left-hand operand of comma expression has no effect [-Wunused-value]
How can I change the logging macro such that no warning is issued? (Note, that I don't want to add compiling flag -Wunused-value).
EDIT I see already a couple of answers involving (...). The same file is compiled under Minix which doesn't support variadic macros. The best would be to have a C89 conforming solution. While your answer is correct (and I upvoted it), it is my fault that I didn't include this small detail.

I think the old school way of dealing with this is to take advantage of double parens. Something like this:
LOG(("message: %d", 10));
Then for your macro, you define it like this:
#define LOG(x) printf x
or
#define LOG(x) (void)0
Because of the double parens, the pre-processor treats the whole inner paren as a single parameter. This at least used to work in visual studio.
EDIT: I did a quick test, it works with gcc with -ansi, so it should be good:
gcc -DNDEBUG -ansi -pedantic -W -Wall test.c -o test
#include <stdio.h>
#ifdef NDEBUG
#define LOG(x) printf x
#else
#define LOG(x) (void)0
#endif
int main() {
LOG(("message: %d\n", 10));
return 0;
}

The easiest should be
#define LOG(...) (void)0
(gcc supports the C99 variadic macros and most other compilers also do these days) That will discard the arguments list, which has two advantages:
it does not create statements with no effect and
the arguments are not evaluated at all (if you call non-inline functions in the argument list, in your version the compiler can't eliminate them, while with the variadic macro, the compiler won't see them at all.

#define LOG(...) seems to do the trick.

For your problems with a non-conforming C implementation (not even C89?) you could do something like
static void LOG(char *format, ...) { /* empty */ }
even a completely dumb compiler should be able to optimize that out.

I've used
#define LOG( t) t
for the development version and
#define LOG( t)
for the release version, with a typical use being
LOG( printf( "here\n"));

Related

how to debug macro?

having this code:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define check(x) ({int _val = (x); (_val ==-1? \
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
"%s\n",__LINE__,strerror(errno)); \
exit(-1);-1;}) : _val); })
int main (int argc, char **argv) {
if (argc!=2){
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
exit(-1);
}
int fd;
fd=open(argv[1], O_RDONLY);
if(fd<0){
perror("open");
fprintf(stderr,"errno = %s\n",strerror(errno));
exit(-1);
}
for(char c;check(read(fd,&c,1))>0;) //macro "check(x)" HERE
fputc(c,stdout);
return 0;
}
It compiles without an error, but I can see the macro does not output error messeges (__FILE__, neither __LINE__), as define it the macro. How to fix that? (And for general, how to debug macro, how at least output some error for it)?
$cc -pedantic a.c
a.c: In function ‘main’:
a.c:10:2: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
^
a.c:30:13: note: in expansion of macro ‘check’
for(char c;check(read(fd,&c,1))>0;)
^~~~~
a.c:9:18: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
#define check(x) ({int _val = (x); (_val ==-1? \
^
a.c:30:13: note: in expansion of macro ‘check’
for(char c;check(read(fd,&c,1))>0;)
not single mention about for loop (only its location, because the macro is in there, but that is not error) statment. Only about macro. So please focus on macro problem and not about the for loop.
EDIT1:
the macro actually comes from this guy:
youtube tutorial (at the end of the video), well he uses clang, so I do not know what clang uses as a preprocessor (and therefor it works for him).
EDIT2 (output from a.i - preprocessed output):
# 304 "/usr/include/fcntl.h" 3 4
# 8 "a.c" 2
# 14 "a.c"
int main (int argc, char **argv) {
I have deleted all the noise. But you can see between #include <fcntl.h> and int main, there is nothing. But there should be the #define check(x).... So it does not tell me WHY is it missing.
how to debug macro?
Read more about C, in particular the Modern C book then this site.
Most C compilers have a way to show the preprocessed form of a translation unit.
Read the documentation of your C compiler.
For GCC, see this. For Clang, see that. The GCC preprocessor is documented here.
If you use gcc as your C compiler on file foo.c run it as gcc -C -E -H -Wall foo.c > foo.i to obtain into foo.i the preprocessed form of foo.c (but most comments are kept, and you could add more of them). Then look with a pager or an editor (I recommend GNU emacs, but feel free to use vim, gedit, more, less, most etc...) into that generated foo.i file.
I can see the macro does not output error messeges
A macro is not outputting any messages, it is just expanded.
If you use a build automation tool such as GNU make or ninja, read its documentation.
If you use some IDE, read its documentation. Many IDEs offer a way to show the preprocessed form, and some might even make the macro expansion on the fly.
Don't forget that in some cases, you may want to use some other preprocessor, such as GPP or GNU m4, or generate some C code programmatically (like GNU bison, or lemon, or SWIG does). Many transpilers (such as Chicken-Scheme or Bigloo) are generating C code, and in Bismon I am doing that at run time, then dynamically loading the generated plugin, using dlopen(3). In RefPerSys we want to generate C++ code at runtime, and later use libgccjit.
You can find lots of open source C preprocessors, even standalone ones like mcpp. You could study their source code and improve them for your needs. And tinycc or nwcc is a small enough open source C compiler (with their preprocessor embedded inside) that you could improve in a few days.
If you use a recent GCC, you could extend it with your own plugin, perhaps adding your own _Pragma (used in your macros) which would display things after preprocessing.
Some clever debuggers (e.g. a suitably configured recent GDB) are capable of macro expansion (thrn compile your C code with gcc -O0 -g3 -Wall)
In Bismon, I use lots of quite long C macros. They might be inspirational. And so is the container-macros library. And also GTK whose macros are very readable.
My experience: to debug a macro, remove many lines from it, till you are satisfied with its expansion. Grow that macro in small steps. Use git on your source code.
$cc -pedantic a.c
I recommend using gcc -Wall -Wextra -g3 -H -pedantic a.c on Linux then use a recent gdb.
Generally speaking you can't debug a macro as macro is not something which is executed.
But there should be the #define check(x).... So it does not tell me
WHY is it missing.
Your macro was preprocessed - ie textually replaced by the preprocessor.
After the preprocessing it is expanded to:
for(char c;({int _val = (read(fd,&c,1)); (_val ==-1? ({fprintf(
stderr
, "Error (" "./example.c" ":%d) -- " "%s\n",30,strerror(
(*__errno_location ())
)); exit(-1);-1;}) : _val); })>0;)
fputc(c,
stdout
);
You can't debug a macro in the sense that a high level debugger will step through the macro code. What you can do is temporarily expand the macro in the source code and use a debugger to see what is going wrong.
One idea is to use a code formatter, like clang-format to beautify the macro so that you can understand it better an use the debugger. Applying this idea, transform the macro into a function and let the formatter do its job:
$ clang-format -i macro.c
results in:
void check1(x) {
({
int _val = (x);
(_val == -1 ? ({
fprintf(stderr,
"Error (" __FILE__ ":%d) -- "
"%s\n",
__LINE__, strerror(errno));
exit(-1);
-1;
})
: _val);
})
}
The code you originally posted actually compiles and executes properly here. I made a version with a few cuts to be able to test the macro:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define check(x) ({int _val = (x); (_val ==-1? \
({fprintf(stderr, "Error (" __FILE__ ":%d) -- " \
"%s\n",__LINE__,strerror(errno)); \
exit(-1);-1;}) : _val); })
int main (int argc, char **argv)
{
check(-1);
return 0;
}
results in:
$ gcc a.c && ./a.out
Error (a.c:13) -- Success
This may be a little late, but I wanted to say that you didn't place a check where you want the code to be checked (opening the file).
Change this:
fd = open(argv[1], O_RDONLY);
To this:
check(fd=open(argv[1], O_RDONLY));
That's what Jacob is doing in its video. He is additionally adding the check in the read operation, but that's completely secondary and aimed to catch errors that came after the file was opened successfully (No example of this kind of errors was shown in the video).

C macros, what's the meaning of ((void)0)?

Given the following code written according to the C99 standard:
#define LOW 1
#define MEDIUM 2
#define HIGH 3
#define LOGGING_LEVEL HIGH
#if LOGGING_LEVEL >= MEDIUM
#define LOG_MEDIUM(message) printf(message)
#else
#define LOG_MEDIUM(message) ((void)0)
#endif
void load_configuration() {
//...
LOG_MEDIUM("Configuration loaded\n");
}
what's the purpose of ((void)0) I searched the web a lot but nothing found regarding this.
Plus, why didn't we wrote ; after using printf(message)
The void-cast fixes a compiler warning. Here's an analogous testcase:
int main(void)
{
0; // generates "foo.c:3:2: warning: statement with no effect"
(void)0;
return 0;
}
and (using a script to add gcc's warning flags) you see a warning for the line without a cast:
$ gcc-stricter -c foo.c
foo.c: In function ‘main’:
foo.c:3:2: warning: statement with no effect [-Wunused-value]
0;
^
The extra parentheses and lack of semicolon allow the macro's result to be used interchangeably with the printf.
Main idea is to exclude all LOG_MEDIUM if the criteria was not meet.
After compilation those calls will not affect functionality.

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).

GCC __func__ gets evaluated to an empty string

Given the following code in a project I'm working on:
/* Pre-definitions in a pre-definitions file to be included in the project */
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
/* My print function */
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
/* Macro usage example function */
void myFunction()
{
if (some_condition)
{
MAC();
}
}
The function name is presented as an empty string.
Any idea why, and how can I fix it?
Code compiled and tested on Linux machine, using GCC compiler.
Use __func__ out of the box. It's been part of the C standard since C99. Change your compiler settings to use at least that standard.
Note that __func__ is not a macro but a predefined identifier which takes the form such that writing it anywhere within a function body is exactly equivalent to using it at that point, having first written
static const char __func__[] = "function-name";
just after the opening brace of a function body.
Formally the behaviour of your current code is undefined. Any symbol containing two consecutive underscores is reserved by the system. (That includes macro names, function names, and variable names.)
Your code as presented gives the expected result (once I'd added the necessary includes and main):
#include <stdio.h>
#ifdef WIN32
#define __FUNCNAME__ __FUNCTION__
#else
#define __FUNCNAME__ __func__
#endif
/* My definitions */
#define MAC() \
MAC1()
#define MAC1() \
myPrintFunction(__FUNCNAME__)
void myPrintFunction(const char * functionName)
{
printf("\n func name: %s \n",functionName);
}
int main()
{
MAC();
}
I compiled this using gcc -std=c11 -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds with no warnings.
You should really post a complete (but minimal) example that actually compiles, along with the compiler flags you used, as something must certainly be different to explain the symptoms you describe.
Also, when writing statements as macros, you may find it helpful to use the do {...} while (0) idiom to avoid unexpected expansions changing the control flow.

Macro to turn off printf statements

What MACRO can be used to switch off printf statements, rather than removing them all for deployment builds, I just want to switch them off, skip them, ignore them.
EDIT: I personally use gcc, but code is part of a larger project which will be compiled on a Panda board running Ubuntu.
Not exactly what you ask for, but I use this construct in my code for debug output when I do not have a proper logging system handy:
#if 1
#define SPAM(a) printf a
#else
#define SPAM(a) (void)0
#endif
So I can do this all over my code
SPAM(("foo: %d\n", 42));
and then disable all of them by changing 1 to 0 in #if above.
But if you have variadic macro support in all compilers that you write code for, then you may go for other answers and just redefine printf. (That being said, I find it useful to distinct debugging prints from regular ones in code — using a different function name helps readability.)
Note that you also can redirect stdout to the /dev/null, but I assume that you want to get rid from runtime overhead as well.
#ifdef IGNORE_PRINTF
#define printf(fmt, ...) (0)
#endif
See also C #define macro for debug printing which discusses some important issues closely related to this.
Two options, either:
#define printf(...)
(requires C99 variadic macro parameters), you need to put it in some common header file which is never included before stdio.h, if there is one..
Or you can tell the linker to link it to something else, in GCC you would define
int wrap_printf(void) {return 0;}
and link using
--wrap printf
All that said, you should probably not be using printf for printing debug output, but rather a macro or utility function (which in turn can use printf if you'd like) which you have better control over.
Hope that helps.
If you want to avoid the potential warning that Jonathan's answer may give you and if you don't mind an empty call to printf you could also do something like
#define printf(...) printf("")
This works because C macros are not recursive. The expanded printf("") will just be left as such.
Another variant (since you are using gcc) would be something like
inline int ignore_printf(char const*, ...)
__attribute__ ((format (printf, 1, 2)));
inline int ignore_printf(char const*, ...) { return 0; }
#define printf ignore_printf
and in one compilation unit
int ignore_printf(char const*, ...)
I use to prefix the debug printf()s (not all of them) with PDEB.
For the debug builds, I compile with -DPDEB= (nothing)
For the release builds, I compile with -DPDEB="0&&" or -DPDEB="0 && "
That way, the following code (test.c):
#include <stdio.h>
void main(void) {
printf("normal print\n");
PDEB printf("debug print\n");
}
outputs:
either (in release mode):
normal print
either (in debug mode):
normal print
debug print
Ideally, one could aim for turning the PDEB into the "//" (comments mark), except that this is not possible under the standard pre-/processing chain.
Another possibility would be something like freopen("/dev/null", "w", stdout);
This doesn't exactly disable printf though -- it's roughly equivalent to running your program with stdout redirected to /dev/null, like: ./myprog > /dev/null at the shell prompt.
I included #define printf // in common header file. It will suppress all the printf.
Below simple function serves the purpose, I use the same.
int printf(const char *fmt, ...)
{
return (0)
}
Use this macro to enable or disable the printf.
//Uncomment the following line to enable the printf function.
//#define ENABLE_PRINTF
#ifdef ENABLE_PRINTF
#define DEBUG_PRINTF(f,...) printf(f,##__VA_ARGS__)
#else
#define DEBUG_PRINTF(f,...)
#endif
Then call "DEBUG_PRINTF" instead of "printf".
For example:
DEBUG_PRINTF("Hello world: %d", whateverCount);
I have used two macros for this. The first one defines the condition to print. In this simple example we print any time the parameter is not zero. More complex expressions can be used.
The second one determines, based on the first macro, to call or not printf.
If the condition can be determined by the compiler (with the right optimization settings) no code is generated.
If the condition cannot be determined at compile time then will be at run time. One of the advantages of this method is that if printf is not going to happen then the whole printf is not evaluated avoiding many conversions to string that can happen in a complex printf statement.
#define need_to_print(flag) ((flag) != 0))
#define my_printf(debug_level, ...) \
({ \
if(need_to_print(debug_level)) \
printf(__VA_ARGS__); \
})
to use it call my_printf instead of printf and add a parameter at the beginning for the print condition.
my_printf(0, "value = %d\n", vv); //this will not print
my_printf(1, "value = %d\n", vv); //this will print
my_printf(print_debug, "value = %d\n", vv); //this will print if print_debug != 0
the ( ... ) parenthesis surrounding the macro make it a single statement.

Resources