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