c++: Improve error recovery for =.
authorJason Merrill <jason@redhat.com>
Thu, 21 May 2020 14:27:11 +0000 (10:27 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 21 May 2020 22:04:22 +0000 (18:04 -0400)
In a template we were happily embedding error_mark_node in a MODOP_EXPR,
leading to confusion later.

gcc/cp/ChangeLog:

* typeck.c (build_x_modify_expr): Handle error_mark_node arguments.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/lambda/lambda-ice30.C: Adjust.
* g++.dg/cpp0x/lambda/lambda-ice31.C: Adjust.
* g++.dg/ext/fixed1.C: Adjust.
* g++.dg/template/crash107.C: Adjust.
* g++.dg/template/error35.C: Adjust.
* g++.dg/template/sizeof-template-argument.C: Adjust.

gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice30.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice31.C
gcc/testsuite/g++.dg/ext/fixed1.C
gcc/testsuite/g++.dg/template/crash107.C
gcc/testsuite/g++.dg/template/error35.C
gcc/testsuite/g++.dg/template/sizeof-template-argument.C

index 0181984bb99578cd1c9c9f24e2f8e2da8707277a..f01ae6562546470cbd872c5325c375dcc2365f97 100644 (file)
@@ -8768,6 +8768,9 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
   tree overload = NULL_TREE;
   tree op = build_nt (modifycode, NULL_TREE, NULL_TREE);
 
+  if (lhs == error_mark_node || rhs == error_mark_node)
+    return cp_expr (error_mark_node, loc);
+
   if (processing_template_decl)
     {
       if (modifycode == NOP_EXPR
index 46350bd1d52246289b65260be1fd391953c78a27..7b0a155a31a723513cf997c33d34695f98179dea 100644 (file)
@@ -3,11 +3,11 @@
 
 template<int> void foo()
 {
-  int x[=];  // { dg-error "expected" }
+  int x[=];  // { dg-error "" }
   [&x]{};
 }
 
 void bar()
 {
-  foo<0>();
+  foo<0>();                    // { dg-prune-output "not declared" }
 }
index 54ded7bb2822f272cdcf822234d550eee4adb0f5..f0ecf8cc26f9f16cb40590a5f5a98933b47765a6 100644 (file)
@@ -4,5 +4,5 @@
 template<typename T> void foo()
 {
   T x[=];  // { dg-error "expected" }
-  [&x]{};
+  [&x]{};  // { dg-prune-output "not declared" }
 }
index 5a479d6891abeddabd0288191dd9699783cdb66b..92e3184ea5917ebdcb93358b47b4ccbd5e73dce0 100644 (file)
@@ -6,3 +6,5 @@ template<int> struct A {};
 template<typename> struct B : A<sizeof(0=0r)> {};      // { dg-error "not supported" }
 
 template<typename> struct C : A<sizeof(0=0r)> {};      // { dg-error "not supported" }
+
+// { dg-prune-output "template argument" }
index 932a3a680592e9780e884be59efd3c9a86d39f17..aab882d8446e1330eb4a41340773c970fc15b6a2 100644 (file)
@@ -10,9 +10,9 @@ template<typename FP_> struct Vec { // { dg-message "note" "" { target c++17_dow
         X = y*rhs.z() - z*rhs.y(); // { dg-error "not declared|no member" }
     }
     Vec& operator^(Vec& rhs) {
-        return Vec(*this)^=rhs; // { dg-message "required" }
+        return Vec(*this)^=rhs;
     }
 };
 Vec<double> v(3,4,12); // { dg-error "no matching|too many initializers" }
 Vec<double> V(12,4,3);  // { dg-error "no matching|too many initializers" }
-Vec<double> c = v^V;   // { dg-message "required" }
+Vec<double> c = v^V;
index d52e599315e2155d3a36ca755de83e0cab5768e5..0ba8635507be6d9d7a770d90dc889f502697752d 100644 (file)
@@ -1,3 +1,3 @@
 // PR c++/33494
 
-template<int> void foo(int(*f=0)()); // { dg-error "declared void|scope|erroneous-expression" }
+template<int> void foo(int(*f=0)()); // { dg-error "declared void|scope|cannot be used as a function" }
index 2bfff6d9a18a4495a8cffb33da8398dc2d428fd4..b5e12d699ae1ad6ce8d07cb9e2e4b019e9a01965 100644 (file)
@@ -3,9 +3,9 @@
 
 template<int> struct A {};
 
-template<typename> struct B : A <sizeof(=)> {}; /* { dg-error "expected primary-expression" } */
+template<typename> struct B : A <sizeof(=)> {}; /* { dg-error "" } */
 
-template<typename> struct C : A <sizeof(=)> {}; /* { dg-error "expected primary-expression" } */
+template<typename> struct C : A <sizeof(=)> {}; /* { dg-error "" } */
 
 int a;