Bug 14258

Summary: typename in a using declaration not supported
Product: gcc Reporter: Jim Apple <japple>
Component: c++Assignee: fabien
Status: RESOLVED FIXED    
Severity: normal CC: akim.demaille, fang, gcc-bugs, gcc, ian, igodard, ilpoilves, jbeulich, joao.eiras, jwakely.gcc, l.jirkovsky, pinskia, pipping, reichelt, rleigh, smelkov, starlight
Priority: P2 Keywords: monitored, rejects-valid
Version: 3.3.1   
Target Milestone: 4.7.0   
Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu Known to work:
Known to fail: 2.95.3, 3.0.4, 3.2.3, 3.3.3, 3.4.0, 4.0.0 Last reconfirmed: 2010-06-07 12:43:20
Bug Depends on:    
Bug Blocks: 23211    

Description Jim Apple 2004-02-23 13:29:06 UTC
The following code:

template<typename T>
struct A {
  typedef A type;
};
                                                                               
                            
template<typename T>
struct B : A<T> {
  using typename A<T>::type;
  type f(type);
};

Give a "syntax error before typename." Without typename in the using
declaration, however, type in B<T> is not a typename, so f's declaration is not
well formed.

Because the "typename" is necessary, this is not the same as bug 3033.
Comment 1 Giovanni Bajo 2004-02-23 13:59:43 UTC
Yes. I flag this as a regression since the valid code used to be accepted 
thanks to the implicit typename extension.
Comment 2 Giovanni Bajo 2004-02-23 14:00:56 UTC
Ehm, sorry, this is obviously a regression only for 3.4 and mainline.
Comment 3 Giovanni Bajo 2004-02-27 12:47:01 UTC
The problem is that our USING_DECL doesn't record the "typename", that is the 
fact that it is a type which is imported through it. This used to work thanks 
to the implicit type name extension, I believe.
Comment 4 Mark Mitchell 2004-03-01 02:10:42 UTC
This is expected behavior, given that G++ does not implement the new
using-declaration semantics, but rather the old ARM-style access-declaration
semantics.

This bug will not be fixed in GCC 3.4.x, so I have changed the target milestone
to 3.5.0.
Comment 5 Volker Reichelt 2004-03-18 12:01:02 UTC
It's not a regression. The code never compiled - in some versions we only
get a warning in addition to the error.
I therefore removed the target milestone.
Comment 6 Giovanni Bajo 2004-03-30 01:19:38 UTC
*** Bug 14778 has been marked as a duplicate of this bug. ***
Comment 7 Andrew Pinski 2004-11-18 12:25:59 UTC
*** Bug 18541 has been marked as a duplicate of this bug. ***
Comment 8 Andrew Pinski 2005-05-10 17:42:10 UTC
*** Bug 21484 has been marked as a duplicate of this bug. ***
Comment 9 Andrew Pinski 2007-05-06 23:31:23 UTC
*** Bug 15260 has been marked as a duplicate of this bug. ***
Comment 10 Roger Leigh 2007-05-07 13:04:23 UTC
Also fails with GCC 4.1.3.
Comment 11 starlight 2008-02-16 19:28:11 UTC
Also fails with GCC 4.2.3.
Comment 12 Andrew Pinski 2008-08-16 20:03:02 UTC
*** Bug 37141 has been marked as a duplicate of this bug. ***
Comment 13 Andrew Pinski 2010-11-29 19:13:27 UTC
*** Bug 46690 has been marked as a duplicate of this bug. ***
Comment 14 Andrew Pinski 2010-12-01 15:46:29 UTC
*** Bug 46748 has been marked as a duplicate of this bug. ***
Comment 15 fabien 2011-12-13 18:47:04 UTC
Author: fabien
Date: Tue Dec 13 18:46:58 2011
New Revision: 182292

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=182292
Log:
gcc/testsuite/ChangeLog

2011-12-11  Fabien Chene  <fabien@gcc.gnu.org>

	PR c++/14258
	* g++.dg/template/using16.C: New.
	* g++.dg/template/using17.C: New.

gcc/cp/ChangeLog

2011-12-11  Fabien Chene  <fabien@gcc.gnu.org>

	PR c++/14258
	* cp-tree.h (USING_DECL_TYPENAME_P): New macro.
	* parser.c (cp_parser_nonclass_name): Handle using declarations
	that refer to a dependent type.
	(cp_parser_using_declaration): Set USING_DECL_TYPENAME_P to 1 if
	the using declaration refers to a dependent type.

Added:
    trunk/gcc/testsuite/g++.dg/template/using16.C
    trunk/gcc/testsuite/g++.dg/template/using17.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/parser.c
    trunk/gcc/testsuite/ChangeLog
Comment 16 fabien 2011-12-13 19:29:26 UTC
Fixed.
Comment 17 Jonathan Wakely 2012-03-19 16:31:04 UTC
*** Bug 52620 has been marked as a duplicate of this bug. ***
Comment 18 Elias Pipping 2014-01-22 10:25:57 UTC
I'm a bit confused here. Please consider the following piece of code:

<<SNIP

template <typename T> struct A {
  typedef int type;
};

template <typename T> struct B : public A<T> {
  using typename A<T>::type;
  static const int block_size = type::block_size;
};

<<SNAP

Compiling it with gcc 4.8.2 yields

  foo.hh:9:33: error: ‘type’ is not a class, namespace, or enumeration

whereas clang 3.4 will happily accept it(*).

At a first glance, this bug appears to address issues such as this, so that gcc 4.8.2 should be fine. This does not seem to be the case, however -- the test case provided by Jim Apple compiles but the one above does not; I'll have to assume the bug was only partly fixed?


(*) I orginally thought this was not valid and filed a clang bug: http://llvm.org/bugs/show_bug.cgi?id=18574
Comment 19 Jonathan Wakely 2014-01-22 11:14:56 UTC
That example's a bit misleading, because 'int' really isn't a class, namespace or enumeration, but the error's wrong because there could be a specialization of A<>, and the same error is produced even if A<T>::type is a class type.

Fabien, the fix doesn't seem to work with nested-name-specifiers, do you remember if there's another bug report about that case?
Comment 20 fabien 2014-01-22 11:18:30 UTC
(In reply to Jonathan Wakely from comment #19)

> Fabien, the fix doesn't seem to work with nested-name-specifiers, do you
> remember if there's another bug report about that case?

Yes, it's probably PR58047.
Comment 21 Elias Pipping 2014-01-22 11:59:54 UTC
(In reply to Jonathan Wakely from comment #19)
> That example's a bit misleading, because 'int' really isn't a class,
> namespace or enumeration, but the error's wrong because there could be a
> specialization of A<>, and the same error is produced even if A<T>::type is
> a class type.

You're right. This will reproduce the problem, too:

<<SNIP

struct C;

template <typename T> struct A {
  typedef C type;
};

template <typename T> struct B : public A<T> {
  using typename A<T>::type;
  static const int block_size = type::block_size;
};

<<SNAP
Comment 22 Elias Pipping 2014-01-22 12:03:49 UTC
I guess my test case is a reduction/duplicate of PR37140.