[clang] bfa2f25 - [C11] Correct the resulting type for an assignment expression

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 26 05:03:41 PDT 2022


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");
+}


        


More information about the cfe-commits mailing list