diff mbox

C++ PATCH for c++/58170 (ICE with alias template)

Message ID 53083A38.7080300@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 22, 2014, 5:48 a.m. UTC
There's no reason why we wouldn't check for dependent scopes when 
parsing the target of an alias declaration, and indeed not doing so led 
to the ICE here.

The rest of the patch improves the diagnostic for this testcase (and 
some others).

Tested x86_64-pc-linux-gnu, applying to trunk.  Also applying the 
cp_parser_type_name hunk to 4.8.
diff mbox

Patch

commit 21f4a8a5550498513e1235239b69aa5bc537687b
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 21 16:58:21 2014 -0500

    	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.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 47a67c4..1e98032 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 0000000..f8bff78
--- /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 <typename T, typename U>
+struct base {
+  template <typename V>
+  struct derived;
+};
+
+template <typename T, typename U>
+template <typename V>
+struct base<T, U>::derived : public base<T, V> {
+};
+
+// This (wrong?) alias declaration provokes the crash.
+template <typename T, typename U, typename V>
+using alias = base<T, U>::derived<V>; // { dg-error "template|typename" }
+
+// This one works:
+// template <typename T, typename U, typename V>
+// using alias = typename base<T, U>::template derived<V>;
+
+template <typename T>
+void f() {
+  alias<T, bool, char> m{};
+  (void) m;
+}
+
+int main() {
+  f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/error8.C b/gcc/testsuite/g++.dg/cpp0x/error8.C
index cc4f877..a992077 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 aec5c2c..695f9a3 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 a8f68d3..999cd9f 100644
--- a/gcc/testsuite/g++.dg/ext/underlying_type1.C
+++ b/gcc/testsuite/g++.dg/ext/underlying_type1.C
@@ -8,7 +8,7 @@  template<typename T>
   { 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 4541548..020ddf0 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 d5ec0c8..9d392af 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" }
 }