Search code examples
c++gcclanguage-lawyerusing-declaration

Compile error when defining a member function, but only in GCC


The following program compiles without errors with MSVS, clang and GCC:

class A;

namespace Y {
    using ::A;
    class A {};
}

int main() {}

Now let's define a member function. Now it still compiles with MSVS and clang, but not with GCC:

class A;

namespace Y {
    using ::A;
    class A { void f() {} };
}

int main() {}

GCC gives the following error message:

  • prog.cc:5:22: error: definition of 'void A::f()' is not in namespace enclosing 'A' [-fpermissive]

Why is that? Is this a bug in GCC?

If the second version of the program violates a rule of the c++ standard, what rule does it violate and why doesn't MSVS and clang give a diagnostic message for that violation?

Is this a case of an ambiguity of the c++ standard?

From the error message it looks like GCC incorrectly thinks we have a violation of the following rule:

  • http://eel.is/c++draft/class.mfct#2 "A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition."

We do not have a violation of this rule since the member function definition is inside the class definition. My theory is that GCC confuses the declaration class A; in the global namespace with the class definition class A { ... } in the namespace Y. I think we have a bug in GCC.

With GCC they declare the same entity. This can be seen by observing that in the first version of the program it possible to use ::A as a complete type in main when compiling with GCC. Same for MSVS. With Clang however they declare different entities. This difference may be because of an ambiguity in the c++ standard. Regardless of such an ambiguity we are clearly not violating http://eel.is/c++draft/class.mfct#2 . That rule is very clear.

Related question: Class declaration in same scope as using declaration compiles in GCC but not MSVS


Solution

  • Both of these programs are ill-formed according to the c++ standard. This is because of the same reason as in the related question:

    Class declaration in same scope as using declaration compiles in GCC but not MSVS

    All compilers should give a compile error in both cases: So this indicates a bug in MSVS, clang and GCC.

    The bug in clang has been confirmed and fixed: https://llvm.org/bugs/show_bug.cgi?id=24030

    The reason that GCC gives a strange error message for the second program is that it gets confused when it failed to detect the error that is present in both the first and the second program.