Skip to content

Commit 252c83b

Browse files
[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 <[email protected]>
1 parent f7c71f1 commit 252c83b

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ Bug Fixes to C++ Support
173173

174174
Bug Fixes to AST Handling
175175
^^^^^^^^^^^^^^^^^^^^^^^^^
176+
- Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576)
176177

177178
Miscellaneous Bug Fixes
178179
^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15949,7 +15949,7 @@ ExprResult Sema::ActOnStmtExprResult(ExprResult ER) {
1594915949
// FIXME: Provide a better location for the initialization.
1595015950
return PerformCopyInitialization(
1595115951
InitializedEntity::InitializeStmtExprResult(
15952-
E->getBeginLoc(), E->getType().getUnqualifiedType()),
15952+
E->getBeginLoc(), E->getType().getAtomicUnqualifiedType()),
1595315953
SourceLocation(), E);
1595415954
}
1595515955

clang/test/Sema/gh106576.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
3+
typedef _Atomic char atomic_char;
4+
5+
atomic_char counter;
6+
7+
char load_plus_one(void) {
8+
return ({counter;}) + 1; // no crash
9+
}
10+
11+
char type_of_stmt_expr(void) {
12+
typeof(({counter;})) y = ""; // expected-error-re {{incompatible pointer to integer conversion initializing 'typeof (({{{.*}}}))' (aka 'char') with an expression of type 'char[1]'}}
13+
return y;
14+
}

0 commit comments

Comments
 (0)