#pragma GCC dependency
#pragma GCC dependency
allows you to check the relative dates of the current file and another file. If the other file is more recent than the current file, a warning is issued. This is useful if the current file is derived from the other file, and should be regenerated. The other file is searched for using the normal include search path. Optional trailing text can be used to give more information in the warning message.
#pragma GCC dependency "parse.y" #pragma GCC dependency "/usr/include/time.h" rerun fixincludes
#pragma GCC poison
#pragma GCC poison
is followed by a list of identifiers to poison. If any of those identifiers appears anywhere in the source after the directive, it is a hard error. For example,
#pragma GCC poison printf sprintf fprintf sprintf(some_string, "hello");
will produce an error.
If a poisoned identifier appears as part of the expansion of a macro which was defined before the identifier was poisoned, it will not cause an error. This lets you poison an identifier without worrying about system headers defining macros that use it.
For example,
#define strrchr rindex #pragma GCC poison rindex strrchr(some_string, 'h');
will not produce an error.
#pragma GCC system_header
This pragma takes no arguments. It causes the rest of the code in the current file to be treated as if it came from a system header. See System Headers.
gcc attribute keyword
__attribute__ format
This __attribute__ allows assigning printf-like or scanf-like characteristics to the declared function, and this enables the compiler to check the format string against the parameters provided throughout the code. This is exceptionally helpful in tracking down hard-to-find bugs.
There are two flavors:
- __attribute__((format(printf,m,n)))
- __attribute__((format(scanf,m,n)))
but in practice we use the first one much more often.
The (m) is the number of the "format string" parameter, and (n) is the number of the first variadic parameter. To see some examples:
/* like printf() but to standard error only */ extern void eprintf(const char *format, ...) __attribute__((format(printf, 1, 2))); /* 1=format 2=params */ /* printf only if debugging is at the desired level */ extern void dprintf(int dlevel, const char *format, ...) __attribute__((format(printf, 2, 3))); /* 2=format 3=params */
With the functions so declared, the compiler will examine the argument lists
$ cat test.c 1 extern void eprintf(const char *format, ...) 2 __attribute__((format(printf, 1, 2))); 3 4 void foo() 5 { 6 eprintf("s=%s\n", 5); /* error on this line */ 7 8 eprintf("n=%d,%d,%d\n", 1, 2); /* error on this line */ 9 } $ cc -Wall -c test.c test.c: In function `foo': test.c:6: warning: format argument is not a pointer (arg 2) test.c:8: warning: too few arguments for format
Note that the "standard" library functions - printf and the like - are already understood by the compiler by default.