Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injected class name compiler discrepancy

Tags:

Consider this code:

struct foo{};  int main() {     foo::foo a; } 

I would expect this to be well-formed, declaring a variable of type foo by the rule in [class]/2 (N4140, emphasis mine):

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.

clang 3.6.0 agrees with me, compiling the above code with no applicable warnings with -Wall -pedantic.

gcc 5.2.0 disagrees, providing the following error message:

main.cpp: In function 'int main()': main.cpp:5:5: error: 'foo::foo' names the constructor, not the type    foo::foo a; 

The above holds no matter how deep the nesting of injected class names, e.g. foo::foo::foo::foo.

Is there a rule which forces that construct to be interpreted as a constructor in that context, or is this agcc bug? Or am I interpreting the standards quote incorrectly?

like image 267
TartanLlama Avatar asked Aug 14 '15 08:08

TartanLlama


1 Answers

It appears that clang is wrong in this case. The relevant exception I was looking for is in [class.qual]/2:

2 In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C:

  • (2.1) if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C, or

  • [...]

the name is instead considered to name the constructor of class C.

The standard has a near-equivalent (non-normative, obviously) example:

struct A { A(); }; struct B: public A { B(); };  A::A() { } B::B() { }  B::A ba;// object of type A A::A a;// error, A::A is not a type name struct A::A a2;// object of type A 

However, clang actually issues a correct diagnostic in this case:

error: qualified reference to 'A' is a constructor name rather than a type wherever a constructor can be declared 

Perhaps clang interprets the line In a lookup in which function names are not ignored as In a lookup in which a constructor declaration is valid, but that doesn't seem to be a correct interpretation.

There is an existing bug for this in the clang bugzilla.

like image 156
TartanLlama Avatar answered Sep 21 '22 05:09

TartanLlama