https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88475

Ryan Egesdahl <ryan.egesdahl at mongodb dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ryan.egesdahl at mongodb dot 
com

--- Comment #6 from Ryan Egesdahl <ryan.egesdahl at mongodb dot com> ---
The actual bug here appears to be the fact that "gcc -E" (which I believe
invokes "cpp"?) has different behavior than the integrated preprocessor. If you
compile the code in the initial report with just "gcc", it works irrespective
of passing "-fdirectives-only" to the compiler.

A different way of demonstrating the problem looks like this:

test.cpp:
#define expand(x) x
#define test(...) \
    expand(_test_2(__VA_ARGS__))
#define _test_2(Expression)                 \
    doSomething((Expression))
template <typename T>
inline bool doSomething(
    const T& testOK) {
    if (!testOK) {
        return false;
    }
    return true;
}
int main()
{
    bool condition = true;
    return test(!condition || condition == condition);
}

The above compiles correctly with this:
$ g++ -Wall test.cpp -o test

However, this fails:
$ g++ -Wall -E test.cpp -o test.ii
$ g++ -fpreprocessed -fdirectives-only -Wall -c test.ii -o test
test.cpp: In function ‘int main()’:
test.cpp:21:49: warning: self-comparison always evaluates to true
[-Wtautological-compare]
     return test(!condition || condition == condition);

As does this:
$ g++ -fdirectives-only -Wall -c test.ii -o test
$ g++ -fpreprocessed -Wall -c test.ii -o test
test.cpp: In function ‘int main()’:
test.cpp:21:41: warning: self-comparison always evaluates to true
[-Wtautological-compare]
     return test(!condition || condition == condition);
                               ~~~~~~~~~~^~~~~~~~~~~~
test.cpp:21:12: error: ‘test’ was not declared in this scope
     return test(!condition || condition == condition);
            ^~~~

I understand (from testing) that not passing -fdirectives-only is the actual
cause of the behavior in my test case; however, it is not immediately obvious
why passing -fdirectives-only should be necessary with both the compiler and
preprocessor, nor does the documentation state so. The point is that the
integrated compiler and "gcc -E" (or cpp) behave differently.

Most build wrappers like ccache and icecc (when ICECC_REMOTE_CPP is enabled)
work by taking a gcc command and splitting it into separate preprocessing and
compilation steps, which involves adding -E to the flags for preprocessing and
-c for compiling, then passing the preprocessing results to the compiler.
Because "gcc -E" and the integrated compiler behave differently, some builds
fail with separate preprocessing and compilation steps that otherwise would
have succeeded with a single step. The lack of documentation around
-fdirectives-only and that it must be passed to the compiler (and that it
implies -fpreprocessed to the compiler, for that matter) is making the
confusion worse.

To resolve this report, GCC should not behave differently depending on how you
preprocess source. My personal thought is that "gcc -E" should invoke the
internal preprocessor and just stop before compiling. Also, the documentation
for -fdirectives-only needs to be improved (and maybe added it to the compiler
documentation?) to make clear that the option needs to be passed to the
compiler as well, and that passing it to the compiler with no preprocessed
source is effectively a no-op.

Reply via email to