]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Fix ICEs from invalid atomic compound assignment [PR98195, PR117755]
authorJoseph Myers <josmyers@redhat.com>
Tue, 26 Nov 2024 03:25:44 +0000 (03:25 +0000)
committerJoseph Myers <josmyers@redhat.com>
Tue, 26 Nov 2024 03:25:44 +0000 (03:25 +0000)
As reported in bug 98195, there are ICEs from an _Atomic compound
assignment with an incomplete type on the RHS, arising from an invalid
temporary being created with such a type.  As reported in bug 117755,
there are also (different) ICEs in cases with complete types where the
binary operation itself is invalid, when inside a nested function,
arising from a temporary being created for the RHS, but then not used
because the binary operation returns error_mark_node, resulting in the
temporary not appearing in a TARGET_EXPR, never getting its
DECL_CONTEXT set by the gimplifier and eventually resulting in an ICE
in nested function processing (trying to find a function context for
the temporary) as a result.

Fix the first ICE with an earlier check for a complete type for the
RHS of an assignment so the problematic temporary is never created for
an incomplete type (which changes the error message three existing
tests get for that case; the new message seems as good as the old
one).  Fix the second ICE by ensuring that once a temporary has been
created, it always gets a corresponding TARGET_EXPR even on error.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

PR c/98195
PR c/117755

gcc/c/
* c-typeck.cc (build_atomic_assign): Always create a TARGET_EXPR
for newval even in case of error from binary operation.
(build_modify_expr): Check early for incomplete type of rhs.

gcc/testsuite/
* gcc.dg/pr98195-1.c, gcc.dg/pr117755-1.c: New tests.
* gcc.dg/noncompile/20020207-1.c, gcc.dg/pr14765-1.c,
objc.dg/method-11.m: Update expected error messages.

gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/noncompile/20020207-1.c
gcc/testsuite/gcc.dg/pr117755-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr14765-1.c
gcc/testsuite/gcc.dg/pr98195-1.c [new file with mode: 0644]
gcc/testsuite/objc.dg/method-11.m

index 24ecaa7cfda111d05d7f29e95dbcf3aa69564bc8..a23d83bf41fed02d4c29da24351d2d5ecb1880e2 100644 (file)
@@ -5070,13 +5070,16 @@ cas_loop:
   rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type,
                                rhs, NULL_TREE, ic_assign, false, NULL_TREE,
                                NULL_TREE, 0);
-  if (rhs != error_mark_node)
-    {
-      rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, rhs, NULL_TREE,
-                   NULL_TREE);
-      SET_EXPR_LOCATION (rhs, loc);
-      add_stmt (rhs);
-    }
+  /* The temporary variable for NEWVAL is only gimplified correctly (in
+     particular, given a DECL_CONTEXT) if used in a TARGET_EXPR.  To avoid
+     subsequent ICEs in nested function processing after an error, ensure such
+     a TARGET_EXPR is built even after an error.  */
+  if (rhs == error_mark_node)
+    rhs = old;
+  rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, rhs, NULL_TREE,
+               NULL_TREE);
+  SET_EXPR_LOCATION (rhs, loc);
+  add_stmt (rhs);
 
   /* if (__atomic_compare_exchange (addr, &old, &new, false, SEQ_CST, SEQ_CST))
        goto done;  */
@@ -7048,6 +7051,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 
   /* Types that aren't fully specified cannot be used in assignments.  */
   lhs = require_complete_type (location, lhs);
+  rhs = require_complete_type (location, rhs);
 
   /* Avoid duplicate error messages from operands that had errors.  */
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
index 945eb1b1b97164928ea7a0c69a11a9d1ccc06f78..ada91386f6564b1f6d936d43846631fd5db9304a 100644 (file)
@@ -23,10 +23,10 @@ int main ()
 {
   struct A d;
 
-  d = ({ { bar (); } });               /* { dg-error "void value" } */
-  d = ({ if (1) { bar (); } });                /* { dg-error "void value" } */
-  d = ({ while (0) { bar (); } });     /* { dg-error "void value" } */
-  d = ({ do { bar (); } while (0); }); /* { dg-error "void value" } */
+  d = ({ { bar (); } });               /* { dg-error "invalid use of void expression" } */
+  d = ({ if (1) { bar (); } });                /* { dg-error "invalid use of void expression" } */
+  d = ({ while (0) { bar (); } });     /* { dg-error "invalid use of void expression" } */
+  d = ({ do { bar (); } while (0); }); /* { dg-error "invalid use of void expression" } */
   baz (&d);
   exit (0);
 }
diff --git a/gcc/testsuite/gcc.dg/pr117755-1.c b/gcc/testsuite/gcc.dg/pr117755-1.c
new file mode 100644 (file)
index 0000000..acb5d4e
--- /dev/null
@@ -0,0 +1,15 @@
+/* Test ICE with atomic compound assignment with invalid operands in nested
+   function (bug 117755).  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+_Atomic struct S { char c; } as;
+
+void
+f (void)
+{
+  void g (void)
+  {
+    as += 1; /* { dg-error "invalid operands to binary" } */
+  }
+}
index d2b341839cec43a4fb9cd3488d73338f41cbe9c6..892a0af416639372757e30ab6291660c704d2e99 100644 (file)
@@ -7,5 +7,5 @@ int a;
 void fun ()
 {
        a = 0;
-       a = ({}); /* { dg-error "not ignored" "void stmt expr" } */
+       a = ({}); /* { dg-error "invalid use of void expression" "void stmt expr" } */
 }
diff --git a/gcc/testsuite/gcc.dg/pr98195-1.c b/gcc/testsuite/gcc.dg/pr98195-1.c
new file mode 100644 (file)
index 0000000..fdb7ce0
--- /dev/null
@@ -0,0 +1,12 @@
+/* Test ICE with atomic compound assignment with incomplete type on RHS (bug
+   98195).  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+_Atomic int x;
+
+void
+f (void)
+{
+  x += f (); /* { dg-error "invalid use of void expression" } */
+}
index 60198803e661d1b5aab5f19f7fde9eb5150cc11e..bc59e14f0710adc72bedc4f67007d9682f4475e7 100644 (file)
@@ -29,5 +29,5 @@ void foo(void) {
      /* { dg-message "also found .\\-\\(id\\)initWithData:\\(Object2 \\*\\)data." "" { target *-*-* } Object3_initWithData } */
 
      /* The following error is a consequence of picking the "wrong" method signature.  */
-     /* { dg-error "void value not ignored as it ought to be" "" { target *-*-* } initWithData_message } */
+     /* { dg-error "invalid use of void expression" "" { target *-*-* } initWithData_message } */
 }