From 7eae5d361e34f2286b133096e66bbc69ed191956 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 22 Feb 2014 00:50:12 -0500 Subject: [PATCH] re PR c++/58170 ([c++11] Crash when aliasing a template class that is a member of its template base class.) PR c++/58170 * parser.c (cp_parser_type_name): Always check dependency. (cp_parser_type_specifier_seq): Call cp_parser_parse_and_diagnose_invalid_type_name. From-SVN: r208040 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/parser.c | 13 ++++++-- gcc/testsuite/g++.dg/cpp0x/alias-decl-40.C | 33 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/error8.C | 2 +- gcc/testsuite/g++.dg/cpp0x/override4.C | 8 ++--- gcc/testsuite/g++.dg/ext/underlying_type1.C | 2 +- gcc/testsuite/g++.dg/parse/crash48.C | 2 +- gcc/testsuite/g++.dg/parse/error49.C | 2 +- 8 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-40.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 53f6c2101e0..1b204dcf4be 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2014-02-21 Jason Merrill + PR c++/58170 + * parser.c (cp_parser_type_name): Always check dependency. + (cp_parser_type_specifier_seq): Call + cp_parser_parse_and_diagnose_invalid_type_name. + PR c++/60108 * semantics.c (expand_or_defer_fn_1): Check DECL_DEFAULTED_FN. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 47a67c49320..1e980326306 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14763,7 +14763,7 @@ cp_parser_type_name (cp_parser* parser) instantiation of an alias template... */ type_decl = cp_parser_template_id (parser, /*template_keyword_p=*/false, - /*check_dependency_p=*/false, + /*check_dependency_p=*/true, none_type, /*is_declaration=*/false); /* Note that this must be an instantiation of an alias template @@ -18083,7 +18083,16 @@ cp_parser_type_specifier_seq (cp_parser* parser, type-specifier-seq at all. */ if (!seen_type_specifier) { - cp_parser_error (parser, "expected type-specifier"); + /* Set in_declarator_p to avoid skipping to the semicolon. */ + int in_decl = parser->in_declarator_p; + parser->in_declarator_p = true; + + if (cp_parser_uncommitted_to_tentative_parse_p (parser) + || !cp_parser_parse_and_diagnose_invalid_type_name (parser)) + cp_parser_error (parser, "expected type-specifier"); + + parser->in_declarator_p = in_decl; + type_specifier_seq->type = error_mark_node; return; } diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-40.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-40.C new file mode 100644 index 00000000000..f8bff782032 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-40.C @@ -0,0 +1,33 @@ +// PR c++/58170 +// { dg-require-effective-target c++11 } +// { dg-prune-output "not declared" } +// { dg-prune-output "expected" } + +template +struct base { + template + struct derived; +}; + +template +template +struct base::derived : public base { +}; + +// This (wrong?) alias declaration provokes the crash. +template +using alias = base::derived; // { dg-error "template|typename" } + +// This one works: +// template +// using alias = typename base::template derived; + +template +void f() { + alias m{}; + (void) m; +} + +int main() { + f(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/error8.C b/gcc/testsuite/g++.dg/cpp0x/error8.C index cc4f87791a9..a99207792ae 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error8.C +++ b/gcc/testsuite/g++.dg/cpp0x/error8.C @@ -3,5 +3,5 @@ struct A { - int* p = new foo; // { dg-error "16:expected type-specifier" } + int* p = new foo; // { dg-error "16:foo. does not name a type" } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/override4.C b/gcc/testsuite/g++.dg/cpp0x/override4.C index aec5c2cdf35..695f9a38109 100644 --- a/gcc/testsuite/g++.dg/cpp0x/override4.C +++ b/gcc/testsuite/g++.dg/cpp0x/override4.C @@ -16,12 +16,12 @@ struct B2 struct B3 { - virtual auto f() -> final void; // { dg-error "expected type-specifier" } + virtual auto f() -> final void; // { dg-error "type" } }; struct B4 { - virtual auto f() -> final void {} // { dg-error "expected type-specifier" } + virtual auto f() -> final void {} // { dg-error "type" } }; struct D : B @@ -36,10 +36,10 @@ struct D2 : B struct D3 : B { - virtual auto g() -> override void; // { dg-error "expected type-specifier" } + virtual auto g() -> override void; // { dg-error "type" } }; struct D4 : B { - virtual auto g() -> override void {} // { dg-error "expected type-specifier" } + virtual auto g() -> override void {} // { dg-error "type" } }; diff --git a/gcc/testsuite/g++.dg/ext/underlying_type1.C b/gcc/testsuite/g++.dg/ext/underlying_type1.C index a8f68d3d60a..999cd9f35bd 100644 --- a/gcc/testsuite/g++.dg/ext/underlying_type1.C +++ b/gcc/testsuite/g++.dg/ext/underlying_type1.C @@ -8,7 +8,7 @@ template { typedef __underlying_type(T) type; }; // { dg-error "not an enumeration" } __underlying_type(int) i1; // { dg-error "not an enumeration|invalid" } -__underlying_type(A) i2; // { dg-error "expected" } +__underlying_type(A) i2; // { dg-error "expected|type" } __underlying_type(B) i3; // { dg-error "not an enumeration|invalid" } __underlying_type(U) i4; // { dg-error "not an enumeration|invalid" } diff --git a/gcc/testsuite/g++.dg/parse/crash48.C b/gcc/testsuite/g++.dg/parse/crash48.C index 45415484b4a..020ddf079ac 100644 --- a/gcc/testsuite/g++.dg/parse/crash48.C +++ b/gcc/testsuite/g++.dg/parse/crash48.C @@ -5,5 +5,5 @@ void foo (bool b) { if (b) - try { throw 0; } catch (X) { } // { dg-error "expected type-specifier before" } + try { throw 0; } catch (X) { } // { dg-error "type" } } diff --git a/gcc/testsuite/g++.dg/parse/error49.C b/gcc/testsuite/g++.dg/parse/error49.C index d5ec0c87ef6..9d392afa84f 100644 --- a/gcc/testsuite/g++.dg/parse/error49.C +++ b/gcc/testsuite/g++.dg/parse/error49.C @@ -2,5 +2,5 @@ int main() { - int* p = new foo; // { dg-error "16:expected type-specifier" } + int* p = new foo; // { dg-error "16:type" } }