13

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

Community
  • 1
  • 1
Supremum
  • 542
  • 7
  • 23
  • 1
    Do we have to guess what the error message is? – Lightness Races in Orbit Jul 05 '15 at 18:31
  • I have edited the question to include the error message. I ran it here: http://melpon.org/wandbox/permlink/W3284yJiSuXuahQu – Supremum Jul 05 '15 at 18:57
  • Personally, to me it looks like that code is incorrect - you forward declare `A` outside the class, then define it in the class; without the using statement, those would be two separate classes (ie `class A` and `class Y::A`, but with the using statement, you already have a name `A` in the scope of `class Y`, so the subsequent definition of a `class A` in that scope looks like it should either hide that imported name (and thus compile) _or_ be taken as a definition for it, in which case it _is_ a violation of that rule you posted (well, at least _if_ you remove the word "function"). – celticminstrel Jul 06 '15 at 02:52

1 Answers1

5

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.

Community
  • 1
  • 1
Supremum
  • 542
  • 7
  • 23