Author: Aaron Ballman Date: 2022-03-26T08:03:11-04:00 New Revision: bfa2f25d350c1015b74b8a14684e68efa6500bbc
URL: https://github.com/llvm/llvm-project/commit/bfa2f25d350c1015b74b8a14684e68efa6500bbc DIFF: https://github.com/llvm/llvm-project/commit/bfa2f25d350c1015b74b8a14684e68efa6500bbc.diff LOG: [C11] Correct the resulting type for an assignment expression In C, assignment expressions result in an rvalue whose type is the type of the lhs of the assignment after it undergoes lvalue to rvalue conversion. lvalue to rvalue conversion in C strips all qualifiers including _Atomic. We used getUnqualifiedType() which does not strip the _Atomic qualifier when we should have used getAtomicUnqualifiedType(). This corrects the usage and adds some comments to getUnqualifiedType() to make it more clear that it does not strip _Atomic and that's on purpose (see C11 6.2.5p27). This addresses Issue 48742. Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/Type.h clang/lib/Sema/SemaExpr.cpp clang/test/Sema/atomic-expr.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9e7958918b2dc..3f37dfe6027a4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -82,7 +82,9 @@ Bug Fixes alias, target) identifier instead of only processing one such ``#pragma weak`` per identifier. Fixes `Issue 28985 <https://github.com/llvm/llvm-project/issues/28985>`_. - +- Assignment expressions in C11 and later mode now properly strip the _Atomic + qualifier when determining the type of the assignment expression. Fixes + `Issue 48742 <https://github.com/llvm/llvm-project/issues/48742>`_. - Unevaluated lambdas in dependant contexts no longer result in clang crashing. This fixes Issues `50376 <https://github.com/llvm/llvm-project/issues/50376>`_, `51414 <https://github.com/llvm/llvm-project/issues/51414>`_, diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index bc66ffbf735e2..56869c17bd5cf 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -931,6 +931,10 @@ class QualType { /// The resulting type might still be qualified if it's sugar for an array /// type. To strip qualifiers even from within a sugared array type, use /// ASTContext::getUnqualifiedArrayType. + /// + /// Note: In C, the _Atomic qualifier is special (see C2x 6.2.5p29 for + /// details), and it is not stripped by this function. Use + /// getAtomicUnqualifiedType() to strip qualifiers including _Atomic. inline QualType getUnqualifiedType() const; /// Retrieve the unqualified variant of the given type, removing as little diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1547a34b5c730..c5ede6eb3f908 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13637,15 +13637,15 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, } } - // C99 6.5.16p3: The type of an assignment expression is the type of the - // left operand unless the left operand has qualified type, in which case - // it is the unqualified version of the type of the left operand. - // C99 6.5.16.1p2: In simple assignment, the value of the right operand - // is converted to the type of the assignment expression (above). + // C11 6.5.16p3: The type of an assignment expression is the type of the + // left operand would have after lvalue conversion. + // C11 6.3.2.1p2: ...this is called lvalue conversion. If the lvalue has + // qualified type, the value has the unqualified version of the type of the + // lvalue; additionally, if the lvalue has atomic type, the value has the + // non-atomic version of the type of the lvalue. // C++ 5.17p1: the type of the assignment expression is that of its left // operand. - return (getLangOpts().CPlusPlus - ? LHSType : LHSType.getUnqualifiedType()); + return getLangOpts().CPlusPlus ? LHSType : LHSType.getAtomicUnqualifiedType(); } // Only ignore explicit casts to void. diff --git a/clang/test/Sema/atomic-expr.c b/clang/test/Sema/atomic-expr.c index 3afcebd0d6cce..097ed4fd39ee4 100644 --- a/clang/test/Sema/atomic-expr.c +++ b/clang/test/Sema/atomic-expr.c @@ -61,3 +61,17 @@ int func_13 (int x, unsigned y) { int func_14 (void) { return data1 == 0; } + +void func_15(void) { + // Ensure that the result of an assignment expression properly strips the + // _Atomic qualifier; Issue 48742. + _Atomic int x; + int y = (x = 2); + int z = (int)(x = 2); + y = (x = 2); + z = (int)(x = 2); + y = (x += 2); + + _Static_assert(__builtin_types_compatible_p(__typeof__(x = 2), int), "incorrect"); + _Static_assert(__builtin_types_compatible_p(__typeof__(x += 2), int), "incorrect"); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits