Skip to content

Commit

Permalink
[C11] Correct the resulting type for an assignment expression
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
AaronBallman committed Mar 26, 2022
1 parent c3b672a commit bfa2f25
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 8 deletions.
4 changes: 3 additions & 1 deletion clang/docs/ReleaseNotes.rst
Expand Up @@ -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>`_,
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/Type.h
Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions clang/lib/Sema/SemaExpr.cpp
Expand Up @@ -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.
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/atomic-expr.c
Expand Up @@ -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");
}

0 comments on commit bfa2f25

Please sign in to comment.