Consider the code #define BLOCK_SIZE 4096 #include <linux/fs.h> The header re#defines BLOCK_SIZE. Now, -Wno-system-headers suppresses the warning as it comes in a system header, and the result is that BLOCK_SIZE is silently redefined to 1024. This can probably be fixed by considering all sources of a multi-source warning (like symbol redefinition) when checking whether to suppress the warning or not.
Created attachment 6684 [details] Testcase. Linux specific, but can be readily adapted to other systems.
An obvious workaround is to perform all system #includes before everything else. But there are valid reasons to #include system headers later, and a problem may still remain with #include guard symbols.
And why do you think we should warn here because the redefine is in a system header file? Also you should not be including the kernel headers in user land programs.
(In reply to comment #3) > And why do you think we should warn here because the redefine is in a system header file? The user gets an unexpected value for their define. I wanted BLOCK_SIZE to be 4096, and I wanted the value of BLKBSZGET. I didn't know that linux/fs.h defines BLOCK_SIZE, and I assumed that if it did I'd get a warning. As it was, my code was silently broken. Also you > should not be including the kernel headers in user land programs. I needed an ioctl definition. But this is true for non-kernel headers as well: // define some options: #define O_SCP 1 // use /usr/bin/scp #define O_WGET 2 // use /usr/bin/wget #define O_RSYNC 3 // use /usr/bin/rsync // ... #include <fcntl.h> // oops: silently redefines O_RSYNC The user may not be aware that O_RSYNC exists.
Since O_RSYNC is reserved by the UNIX standard that part is invalid. Yes there is such a thing, see <http://www.opengroup.org/onlinepubs/007908799/xsh/open.html> for the standard definition. If you do not know what the marcos you are being in by using the headers why are you bring in the headers. Also it is always custumary to include system headers first and then do the defines/includes of the user headers and you will never run into this. Again this is invalid as the redefinition is the system header and the system header depends on the macros being defined right.
(In reply to comment #5) > Since O_RSYNC is reserved by the UNIX standard that part is invalid. Yes there is such a thing, see > <http://www.opengroup.org/onlinepubs/007908799/xsh/open.html> for the standard definition. If it is reserved, my code shouldn't compile if I define it. if I do #include <fcntl.h> #define O_RSYNC blah I get a warning. If I switch the order of the lines, I don't. The code compiles after silently overriding my #define. > > If you do not know what the marcos you are being in by using the headers why are you bring in the > headers. Say I wanted O_SYNC, and knew about that. Or I included some other file that included it. In a complex program a very large amount of headers can be expected to be used. It's unreasonable to expect the user to know about all defines in a header (did you know about O_RSYNC? I didn't). Also it is always custumary to include system headers first and then do the defines/includes > of the user headers and you will never run into this. This is a valid workaround. > > Again this is invalid as the redefinition is the system header and the system header depends on the > macros being defined right. The code _is_ invalid, no doubt. I just want a warning, that's all. Shouldn't gcc reject invalid code?
I agree with Avi. The system header doesn't do a #undef + #define, but just a #define and it silently overwrites the previous macro. Even if this is undefined behaviour, we can do better than we do now and emit at least a warning.
Please file this bug with the Linux Kernel people also. And glibc for O_RSYNC.
ISO C treats redefinition of a macro as an error (6.10.3 2). IMHO it is reasonable to add a gcc/cpp option which provides treating redefinition of a macro as an error.
(In reply to niva from comment #9) -Werror turns the warning GCC issues for a macro redefinition into an error. A part of the problem is that warnings in system headers are suppressed by default, without -Wsystem-headers, so -Werror alone doesn't help. What is also missing, though, is a mechanism/option to silence the macro redefinition warning without also suppressing all other warnings (i.e., an option other that -w). For example, there is no way to suppress the warning in the example below without also suppressing the -Wcpp warning. In contrast to GCC, Clang provides the -Wmacro-redefined option that makes it possible to control just the macro redefinition warning. Providing the same feature in GCC might help resolve this problem by enabling warnings for macro redefinitions in user headers without also enabling all other warnings in them. $ cat t.c && gcc -S t.c #define A 1 #define A 2 #warning foo t.c:2:0: warning: "A" redefined #define A 2 t.c:1:0: note: this is the location of the previous definition #define A 1 t.c:3:2: warning: #warning foo [-Wcpp] #warning foo ^~~~~~~
(in reply to Martin Sebor in comment #10) Implementation of -Wmacro-redefined (with possibility of turning this warning to error) would solve the problem of our users.
(In reply to niva from comment #11) > (in reply to Martin Sebor in comment #10) > > Implementation of -Wmacro-redefined (with possibility of turning this > warning to error) would solve the problem of our users. Retitling accordingly