-I 编译器选项如何导致不同的警告触发器?

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

我最近的任务是重组一个应用程序,运行 变成了一个相当奇怪的问题。我已尽我所能将问题简化为示例代码。考虑以下因素:

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;
}

如果我运行:

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

但是,如果我将 offender.h 移动到系统定义的路径并在没有 -I 的情况下进行编译,这是有道理的。我明白了:

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

没有触发警告。

如果我从当前目录中包含头文件但如果我从预定义的包含目录中包含它却可以正常工作,怎么可能会出现警告?我错过了什么?

已使用 g++ 7.5.0 (Ubuntu 18.04) 和 9.3.0 (Ubuntu 20.04) 进行测试,两者生成相同的输出。

编辑:澄清问题

documentation

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.