Hello,
As reminded in the audit trail of this PR, the identifier of an
elaborate specifier should never be a simple-template-id that resolves
to an alias template specialization, but the current implementation
fails to enforce that.
I reused check_elaborated_type_specifier in
cp_parser_elaborated_type_specifier for cases where the later parses a
template-id. I had to make check_elaborate_type_specifier be a bit more
robust, accept bound template template parameters and display relevant
diagnostics for alias template specializations.
Not surprisingly, I had to adjust some tests that were wrongly passing
before.
Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.
gcc/cp/
PR c++/51145
* decl.c (check_elaborated_type_specifier): Gracefully handle
error_mark_node. Accept bound template template parameters.
Update diagnostics for alias template specializations. Update
comment.
* parser.c (cp_parser_elaborated_type_specifier): Use
check_elaborated_type_specifier for simple-template-ids as well.
gcc/testsuite/
PR c++/51145
* g++.dg/cpp0x/alias-decl-2.C: Adjust for tests that were wrongly
passing before.
* g++.dg/cpp0x/alias-decl-10.C: Likewise and adjust for diagnostic
change.
* g++.dg/cpp0x/alias-decl-14.C: New test.
---
gcc/cp/decl.c | 22 ++++++++++++++++++----
gcc/cp/parser.c | 3 ++-
gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C | 16 ++++++++++++----
gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C | 14 ++++++++++++++
gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C | 2 +-
5 files changed, 47 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b77963b..7170072 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11342,6 +11342,9 @@ check_elaborated_type_specifier (enum tag_types
tag_code,
{
tree type;
+ if (decl == error_mark_node)
+ return error_mark_node;
+
/* In the case of:
struct S { struct S *p; };
@@ -11361,10 +11364,15 @@ check_elaborated_type_specifier (enum tag_types
tag_code,
type, tag_name (tag_code));
return error_mark_node;
}
+ /* Accept bound template template parameters. */
+ else if (allow_template_p
+ && TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ ;
/* [dcl.type.elab]
- If the identifier resolves to a typedef-name or a template
- type-parameter, the elaborated-type-specifier is ill-formed.
+ If the identifier resolves to a typedef-name or the
+ simple-template-id resolves to an alias template
+ specialization, the elaborated-type-specifier is ill-formed.
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
@@ -11373,8 +11381,14 @@ check_elaborated_type_specifier (enum tag_types
tag_code,
&& !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
- error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
- error ("%q+D has a previous declaration here", decl);
+ if (alias_template_specialization_p (type))
+ error ("using alias template specialization %qT after %qs",
+ type, tag_name (tag_code));
+ else
+ {
+ error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+ error ("%q+D has a previous declaration here", decl);
+ }
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f839112..08b9c13 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13933,7 +13933,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
type = NULL_TREE;
else
- type = TREE_TYPE (decl);
+ type = check_elaborated_type_specifier (tag_type, decl,
+ /*allow_template_p=*/true);
}
if (!type)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
index 856e429..6adb785 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
@@ -3,16 +3,24 @@
template <class T> using Ptr = T*;
Ptr<unsigned>; // { dg-error "does not declare anything" }
Ptr<char><int>; // { dg-error "not a template|does not declare anything" }
-template class Ptr<int>;//{ dg-error "explicit instantiation|non-class
templ|does not decl|anything" }
+template class Ptr<int>;//{ dg-error "alias
templ|specialization|Ptr<int>|after|class" }
template <class T> using Arg = T;
struct A {};
-template class Arg<A>;// { dg-error "explicit instantiation|non-class templ" }
+template class Arg<A>;// { dg-error "alias
templ|specialization|Arg<A>|after|class" }
template <template <class> class TT, class T> using Instantiate = TT<T>;
template <class> struct Vector {};
-template class Instantiate<Vector, int>; // OK Vector<int> can be explicitely
instantiated
+
+// The below is not OK, because of [dcl.type.elab]:
+//
+// If the identifier resolves to a typedef-name or the
+// simple-template-id resolves to an alias template
+// specialization, the elaborated-type-specifier is ill-formed.
+//
+template class Instantiate<Vector, int>;//{ dg-error "alias templ|after|class"
}
template <class T> struct S {};
template<class T> using SFor = S<T>;
-template class SFor<int>; // OK, S<int> can be explicitely instantiated
+// Likewise, this is not OK.
+template class SFor<int>; //{ dg-error "alias tmpl|after|class" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
new file mode 100644
index 0000000..485802e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
@@ -0,0 +1,14 @@
+// Origin: PR c++/51145
+// { dg-options "-std=c++0x" }
+
+struct A {};
+
+template<class>
+using X = A;
+
+struct X<int>* px; // { dg-error "invalid|alias|specialization|X<int>|after
struct" }
+
+template<int>
+using Y = A;
+
+struct Y<0>* py;// { dg-error "invalid|alias|specialization|Y<0>|after struct"
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
index 2e03dd8..1d5a996 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
@@ -6,7 +6,7 @@ template<class T> using AS0 = S0<T>;
template<template<class> class TT>
void f(TT<int>);
-template class AS0<char>;
+template class AS0<char>; // { dg-error "alias
templ|specialization|after|class" }
void
foo()
--
1.7.6.4
--
Dodji