https://gcc.gnu.org/g:3eca9b5119f235666a2d97cb77a6cddc567bbe8b

commit r16-3999-g3eca9b5119f235666a2d97cb77a6cddc567bbe8b
Author: Joseph Myers <[email protected]>
Date:   Sat Sep 20 00:24:26 2025 +0000

    c: Implement C2y N3481 constraint against lvalue conversion with incomplete 
type
    
    C2y replaces undefined behavior for lvalue conversion of an lvalue
    with incomplete, non-array type with a constraint violation.
    Implement this in GCC, which means disallowing lvalue conversion of
    qualified or atomic void for C2y.  (Unqualified, non-atomic void is
    excluded from the definition of "lvalue".)
    
    I'm not convinced that the resolution of C90 DR#106 (which said that
    certain cases with qualified void were valid) was really justified
    even based on the wording of C90; nevertheless, this patch takes the
    conservative approach of only disallowing qualified void here for C2y.
    
    The test for this change showed that attempting to access an _Atomic
    void object produced an ICE-after-error attempting the atomic load
    logic for such a type.  require_complete_type returning
    error_mark_node prevents this ICE from occurring any more in C2y mode;
    to avoid it in older modes, a check of COMPLETE_TYPE_P is added to
    really_atomic_lvalue.  I didn't find any existing bug report in
    Bugzilla for this issue.
    
    Bootstrapped with no regressions for x86_64-pc-linux-gnu.
    
    gcc/c/
            * c-typeck.cc (really_atomic_lvalue): Return false for incomplete
            types.
            (convert_lvalue_to_rvalue): Call require_complete_type for
            qualified void for C2y.
    
    gcc/testsuite/
            * gcc.dg/c11-atomic-6.c, gcc.dg/c23-incomplete-1.c,
            gcc.dg/c2y-incomplete-3.c: New tests.

Diff:
---
 gcc/c/c-typeck.cc                       |  6 +++++-
 gcc/testsuite/gcc.dg/c11-atomic-6.c     | 13 ++++++++++++
 gcc/testsuite/gcc.dg/c23-incomplete-1.c | 36 +++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c2y-incomplete-3.c | 34 +++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 1f04a4d7f4f2..624e7a3fa359 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -2512,6 +2512,8 @@ really_atomic_lvalue (tree expr)
     return false;
   if (!TYPE_ATOMIC (TREE_TYPE (expr)))
     return false;
+  if (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
+    return false;
   if (!lvalue_p (expr))
     return false;
 
@@ -2607,7 +2609,9 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr 
exp,
 
   if (convert_p)
     exp = default_function_array_conversion (loc, exp);
-  if (!VOID_TYPE_P (TREE_TYPE (exp.value)))
+  if (!VOID_TYPE_P (TREE_TYPE (exp.value))
+      || (flag_isoc2y
+         && TYPE_QUALS (TREE_TYPE (exp.value)) != TYPE_UNQUALIFIED))
     exp.value = require_complete_type (loc, exp.value);
   if (for_init || !RECORD_OR_UNION_TYPE_P (TREE_TYPE (exp.value)))
     {
diff --git a/gcc/testsuite/gcc.dg/c11-atomic-6.c 
b/gcc/testsuite/gcc.dg/c11-atomic-6.c
new file mode 100644
index 000000000000..4bb771fe5962
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-atomic-6.c
@@ -0,0 +1,13 @@
+/* Test ICE accessing _Atomic void object.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+extern _Atomic void x;
+
+void
+f (void)
+{
+  /* This has undefined behavior (lvalue conversion on an incomplete type) but
+     should not produce an ICE.  */
+  x;
+}
diff --git a/gcc/testsuite/gcc.dg/c23-incomplete-1.c 
b/gcc/testsuite/gcc.dg/c23-incomplete-1.c
new file mode 100644
index 000000000000..c80361a83470
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-incomplete-1.c
@@ -0,0 +1,36 @@
+/* Test C2y constraint against lvalue conversion of lvalues with incomplete
+   type: not applied in C23 mode.  Although it is not clear that these
+   constructs are valid in C23, we allow certain cases of qualified void
+   there.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+
+struct s;
+union u;
+
+extern struct s vs, *ps;
+extern _Atomic struct s vas, *pas;
+extern union u vu, *pu;
+extern _Atomic union u vau, *pau;
+
+extern const void cv, *pcv;
+extern _Atomic void av, *pav;
+
+void
+f ()
+{
+  vs; /* { dg-error "incomplete type" } */
+  *ps; /* { dg-error "invalid use of undefined type" } */
+  vas; /* { dg-error "incomplete type" } */
+  *pas; /* { dg-error "invalid use of undefined type" } */
+  vu; /* { dg-error "incomplete type" } */
+  *pu; /* { dg-error "invalid use of undefined type" } */
+  vau; /* { dg-error "incomplete type" } */
+  *pau; /* { dg-error "invalid use of undefined type" } */
+  cv;
+  *pcv;
+  /* { dg-warning "dereferencing" "dereferencing" { target *-*-* } .-1 } */
+  av;
+  *pav;
+  /* { dg-warning "dereferencing" "dereferencing" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-incomplete-3.c 
b/gcc/testsuite/gcc.dg/c2y-incomplete-3.c
new file mode 100644
index 000000000000..0a18fdadf814
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-incomplete-3.c
@@ -0,0 +1,34 @@
+/* Test C2y constraint against lvalue conversion of lvalues with incomplete
+   type.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+struct s;
+union u;
+
+extern struct s vs, *ps;
+extern _Atomic struct s vas, *pas;
+extern union u vu, *pu;
+extern _Atomic union u vau, *pau;
+
+extern const void cv, *pcv;
+extern _Atomic void av, *pav;
+
+void
+f ()
+{
+  vs; /* { dg-error "incomplete type" } */
+  *ps; /* { dg-error "invalid use of undefined type" } */
+  vas; /* { dg-error "incomplete type" } */
+  *pas; /* { dg-error "invalid use of undefined type" } */
+  vu; /* { dg-error "incomplete type" } */
+  *pu; /* { dg-error "invalid use of undefined type" } */
+  vau; /* { dg-error "incomplete type" } */
+  *pau; /* { dg-error "invalid use of undefined type" } */
+  cv; /* { dg-error "incomplete type" } */
+  *pcv; /* { dg-error "invalid use of void expression" } */
+  /* { dg-warning "dereferencing" "dereferencing" { target *-*-* } .-1 } */
+  av; /* { dg-error "incomplete type" } */
+  *pav; /* { dg-error "invalid use of void expression" } */
+  /* { dg-warning "dereferencing" "dereferencing" { target *-*-* } .-1 } */
+}

Reply via email to