How can an the -I compiler option cause different warnings triggers?

Viewed 220

I was recently tasked with restructuring an application and ran into a rather bizarre issue. I've reduced the issue into example code as best as I can. Consider the following:

offender.h

__attribute__ ((visibility ("default")))
typedef struct A {
    int a;
} A;

test.cpp:

#include <iostream>

#include <offender.h>

int main(void)
{
    A a;
    a.a = 10;
    std::cout << a.a << "\n";
    return 0;
}

If I run:

g++ -Wall -Werror -o test -I. test.cpp
In file included from test.cpp:3:
./offender.h:4:3: error: ‘visibility’ attribute ignored [-Werror=attributes]
    4 | } A;
      |   ^
cc1plus: all warnings being treated as errors
make: *** [Makefile:3: all] Error 1

This makes sense, however, if I move offender.h into a system defined path and compile without the -I. I get this:

sudo mv offender.h /usr/local/include/
g++ -Wall -Werror -o test test.cpp

No Warning is triggered.

How is it possible that a warning occurs if I include the header file from the current directory but works fine if I include it from a pre-defined include directory? What am I missing?

This has been tested with g++ 7.5.0 (Ubuntu 18.04) and 9.3.0 (Ubuntu 20.04), both generate the same output.

Edit: Clarified the problem

1 Answers

The documentation says

The header files declaring interfaces to the operating system and runtime libraries often cannot be written in strictly conforming C. Therefore, GCC gives code found in system headers special treatment. All warnings, other than those generated by ‘#warning’ (see Diagnostics), are suppressed while GCC is processing a system header.

Related