[clang] 252c83b - [clang][Sema] Fix type of an statement expression ending with an atomic type (#119711)

via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 18 00:52:35 PST 2025


Author: Alejandro Álvarez Ayllón
Date: 2025-02-18T09:52:31+01:00
New Revision: 252c83bc9ef9fc885e9e6517f1b4423188bb919f

URL: https://github.com/llvm/llvm-project/commit/252c83bc9ef9fc885e9e6517f1b4423188bb919f
DIFF: https://github.com/llvm/llvm-project/commit/252c83bc9ef9fc885e9e6517f1b4423188bb919f.diff

LOG: [clang][Sema] Fix type of an statement expression ending with an atomic type (#119711)

When a statement expression's last statement is an atomic variable, GCC
and Clang disagree on the type of the expression. This can be made
apparent using `typeof` and forcing a diagnostic message:

```cpp
_Atomic int a = 0;
typeof(({a;})) x = "0";
```

* GCC complains about initializing `int` with `char*`
* Clang complains about initializing `_Atomic(int)` with a `char[2]`

Due to the type of the statement expression being deduced to be atomic,
we end with three implicit casts inside the `StmtExpr` on the AST:

* `LValueToRValue` -> `AtomicToNonAtomic`  ->  `NonAtomicToAtomic`

In some situations, this can end on an assertion inside
`IntExprEvaluator`, as reported in #106576.

With this patch, we now have two implicit casts, since the type of the
statement expression is deduced to be non-atomic:

* `LValueToRValue` -> `AtomicToNonAtomic`

This is consistent with the C standard (6.7.2.4, p4)

> The properties associated with atomic types are meaningful only for
expressions that are lvalues.

But a statement expression is an rvalue.

`IntExprEvaluator` assumptions are now satisfied and there is no
assertion error.
Additionally, the `typeof` trick mentioned above shows that the type is
consistently deduced between GCC and Clang.

Fixes #106576

---------

Co-authored-by: John McCall <rjmccall at gmail.com>

Added: 
    clang/test/Sema/gh106576.c

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaExpr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6272f32fa845a..a91c764860ccd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -173,6 +173,7 @@ Bug Fixes to C++ Support
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
+- Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576)
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1e660d7770dc6..fad15bf95c415 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15949,7 +15949,7 @@ ExprResult Sema::ActOnStmtExprResult(ExprResult ER) {
   // FIXME: Provide a better location for the initialization.
   return PerformCopyInitialization(
       InitializedEntity::InitializeStmtExprResult(
-          E->getBeginLoc(), E->getType().getUnqualifiedType()),
+          E->getBeginLoc(), E->getType().getAtomicUnqualifiedType()),
       SourceLocation(), E);
 }
 

diff  --git a/clang/test/Sema/gh106576.c b/clang/test/Sema/gh106576.c
new file mode 100644
index 0000000000000..a72592aac0129
--- /dev/null
+++ b/clang/test/Sema/gh106576.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef _Atomic char atomic_char;
+
+atomic_char counter;
+
+char load_plus_one(void) {
+  return ({counter;}) + 1; // no crash
+}
+
+char type_of_stmt_expr(void) {
+  typeof(({counter;})) y = ""; // expected-error-re {{incompatible pointer to integer conversion initializing 'typeof (({{{.*}}}))' (aka 'char') with an expression of type 'char[1]'}}
+  return y;
+}


        


More information about the cfe-commits mailing list