Bug 37350

Summary: Specialized template base class name not accepted
Product: gcc Reporter: Ian Lance Taylor <ian>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: 3.14159, bangerth, bangerth, fang, gcc-bugs, giovannibajo, ian, jens.maurer, reichelt, s__nakayama, witt
Priority: P3 Keywords: rejects-valid
Version: 4.4.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description Ian Lance Taylor 2008-09-03 14:06:13 UTC
C++98 [temp.local] says "Within the scope of a class template specialization or partial specialization, when the name of the template is neither qualified nor followed by <, it is equivalent to the name of the template followed by the template-arguments enclosed in <>."  That does not work when a template specialization is used as a base class.  In that case g++ does not accept the unqualified base class name as a type.

This test case:

template <class T>
struct base {};

struct derived : base<int> {
  typedef base b;
  base* p;
};

gives these errors:

foo.cc:5: error: invalid use of template-name ‘base’ without an argument list
foo.cc:6: error: ISO C++ forbids declaration of ‘base’ with no type
foo.cc:6: error: expected ‘;’ before ‘*’ token

I believe this is an incorrect rejection of valid C++ code.  At least, I can't find anything in the C++ standard which says that this code is invalid.
Comment 1 Richard Biener 2008-09-03 14:50:36 UTC
I don't read from the sentence that this applies to base class names, it
says "the name of the template" only.
Comment 2 Richard Biener 2008-09-03 14:51:49 UTC
EDG rejects it with

t.C(5): error: argument list for class template "base" is missing
        typedef base b;
                ^

but accepts it if you use derived instead of base (like gcc does).
Comment 3 Ian Lance Taylor 2008-09-04 03:38:18 UTC
Here is further argument from a programmer here.  Any language lawyers want to comment?

14.6.1 Locally declared names [temp.local]
1. Like normal (non-template) classes, class templates have an injected-class-name (clause 9). The injected-class-name can be used with or without a template-argument-list. When it is used without a template-argument-list, it is equivalent to the injected-class-name followed by the template-parameters of the class template enclosed in <>. When it is used with a template-argument-list, it refers to the specified class template specialization, which could be the current specialization or another specialization.

It makes this code valid:
template <class T>
struct base {
  typedef base b;
};

And now according to this:
9 Classes [class]
2  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. A class-specifier is commonly referred to as a class definition. A class is considered defined after the closing brace of its class-specifier has been seen even though its member functions are in general not yet defined.

injected-class-name is public, therefore it is accessible in derived class. It makes the example valid.
Comment 4 Andrew Pinski 2008-09-04 03:59:22 UTC
Looks like this is a dup of bug 9937.
Comment 5 Jonathan Wakely 2009-12-23 23:31:12 UTC

*** This bug has been marked as a duplicate of 189 ***