Bug 15503 - [3.4/4.0 regression] nested template problem
Summary: [3.4/4.0 regression] nested template problem
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: 3.4.1
Assignee: Giovanni Bajo
URL:
Keywords: patch, rejects-valid
: 14566 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-05-17 20:12 UTC by Mark Anders
Modified: 2004-10-30 21:11 UTC (History)
5 users (show)

See Also:
Host: i686-pc-gnu-linux
Target: i686-pc-gnu-linux
Build: i686-pc-gnu-linux
Known to work: 3.3.4
Known to fail: 3.4.0 4.0.0
Last reconfirmed: 2004-05-17 20:43:34


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Anders 2004-05-17 20:12:27 UTC
For the following code, the compilation fails at the NProperty constructor.  I 
have tried numerous ways of naming the inherited constructor, none of which 
compile in gcc 3.4.  This compiles with gcc 3.3.3 but not with gcc 3.4. 
 
Thanks 
 
-------------------------------- 
class I { 
public: 
  class Type; 
  template<class T> class Object; 
}; 
 
class I::Type { 
public: 
  class Property; 
}; 
 
template<class T> 
class I::Object { 
public: 
  template<class D> class Property; 
}; 
 
class I::Type::Property { 
}; 
 
template<class T> 
template<class D> 
class I::Object<T>::Property : public I::Type::Property { 
public: 
  Property(D T::*d) : data(d) { } 
private: 
  D T::*data; 
}; 
 
class C : public I::Object<C> { 
public: 
  template<class T> class NProperty :  
    public I::Object<T>::template Property<int> { 
  public: 
    NProperty(int T::*d); 
  }; 
}; 
 
template<class T> 
C::NProperty<T>::NProperty(int T::*d) : 
  I::Object<T>::template Property<int>(d) { } 
 
int main() { 
  return 0; 
}
Comment 1 Andrew Pinski 2004-05-17 20:21:45 UTC
I do not know if this is valid C++ (I think it is not, ICC6.0 rejects it in strict mode).

The way I was able to compile it with 3.4.0, is replace the construtor with:
template<class T>
C::NProperty<T>::NProperty(int T::*d) :
  Property<int>(d) { }
Comment 2 Wolfgang Bangerth 2004-05-17 20:43:34 UTC
I'm sure this is legal, and icc7.1 also accepts it. Here is something 
smaller: 
------------------ 
template <typename> struct O {  
    template <typename> struct I {}; 
}; 
  
template <typename T> 
struct S : O<T>::template I<int> {  
    S() : O<T>::template I<int>() { } ; 
};  
--------------------- 
 
g/x> /home/bangerth/bin/gcc-3.3.4-pre/bin/c++ -c x.cc 
 
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc 
x.cc: In constructor `S<T>::S()': 
x.cc:7: error: expected class-name before "template" 
x.cc:7: error: expected `(' before "template" 
x.cc:7: error: expected `{' before "template" 
 
g/x> /home/bangerth/bin/gcc-3.5-pre/bin/c++ -c x.cc 
x.cc: In constructor `S<T>::S()': 
x.cc:7: error: expected class-name before "template" 
x.cc:7: error: expected `(' before "template" 
x.cc:7: error: expected `{' before "template" 
 
In other words, this is a regression. 
 
W. 
Comment 3 Giovanni Bajo 2004-05-18 10:36:50 UTC
I need to know which way to take with this. In my reading of the standard, the 
keyword 'template' to name nested dependent templates is not allowed in neither 
the base-specifier nor the mem-initializer clause. The grammar explicitally 
says:

base-specifier:
     ::opt nested-name-specifieropt class-name
     virtual access-specifieropt ::opt nested-name-specifier[opt] class-name
     access-specifier virtualopt ::opt nested-name-specifier[opt] class-name

mem-initializer-id:
     ::opt nested-name-specifier[opt] class-name
     identifier

And there is no "template[opt]". After all, it makes sense as a symbol '<' in 
that context can only be the start of a template argument list.

This would also match what happens with typename, which is more explicitally 
disallowed in those contexts ([temp.res]/5): "The keyword typename is not 
permitted in a base-specifier or in a mem-initializer; in these contexts a 
qualified-name that depends on a template-parameter (14.6.2) is implicitly 
assumed to be a type name."

Gaby, do you agree with my reading of the standard? If so, I can make a patch 
that emits a proper diagnostic when 'template' is found in those contexts, and 
fix the rejects-valid shown in this bug (if you remove 'template' from the 
testcase, it still does not accept it).
Comment 4 Mark Mitchell 2004-05-31 19:04:22 UTC
The code in Comment #2 is not allowed by the standard.

This is DR 343, which comes from DR 314, which was opened by me.  It looks like
the committee will eventually allow both the version with the "template"
keyword, and the version without, and that without the keyword the parser should
still assume that it is present.  Right now, the standard provides no way
whatsoever to accomplish the desired functionality.

I'll look into what fixing this would require, but I'm not eager to make major
revisions in this area for 3.4.1; they'll likely be somewhat risky.
Comment 5 Giovanni Bajo 2004-06-01 01:40:55 UTC
I have a patch for this. I'll make the 'template' keyword required in this 
context, much like as we do for the base-specifier.
Comment 6 Giovanni Bajo 2004-06-01 01:54:05 UTC
*** Bug 14566 has been marked as a duplicate of this bug. ***
Comment 7 Giovanni Bajo 2004-06-02 11:19:48 UTC
Patch posted, waiting for review:
http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00101.html
Comment 8 Mark Mitchell 2004-06-05 19:22:08 UTC
Subject: Re:  [3.4/3.5 regression] nested template problem

giovannibajo at libero dot it wrote:

>------- Additional Comments From giovannibajo at libero dot it  2004-06-02 11:19 -------
>Patch posted, waiting for review:
>http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00101.html
>  
>
OK, thanks.

Comment 9 CVS Commits 2004-06-06 02:08:25 UTC
Subject: Bug 15503

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	giovannibajo@gcc.gnu.org	2004-06-06 02:08:19

Modified files:
	gcc/cp         : ChangeLog parser.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/template: meminit2.C 

Log message:
	PR c++/15503
	* parser.c (cp_parser_mem_initializer_id): Gracefully reject
	'typename', and accept 'template'.
	
	PR c++/15503
	* g++.dg/template/meminit2.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4081&r2=1.4082
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.199&r2=1.200
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3811&r2=1.3812
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/meminit2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 10 CVS Commits 2004-06-06 03:22:59 UTC
Subject: Bug 15503

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_4-branch
Changes by:	giovannibajo@gcc.gnu.org	2004-06-06 03:22:56

Modified files:
	gcc/cp         : ChangeLog parser.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/template: meminit2.C 

Log message:
	PR c++/15503
	* parser.c (cp_parser_mem_initializer_id): Gracefully reject
	'typename', and accept 'template'.
	
	PR c++/15503
	* g++.dg/template/meminit2.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.114&r2=1.3892.2.115
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.157.2.30&r2=1.157.2.31
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.196&r2=1.3389.2.197
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/meminit2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1

Comment 11 Giovanni Bajo 2004-06-06 03:23:30 UTC
Fixed for GCC 3.4.1 and GCC 3.5.0. Thank your for your report!