diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 51 |
2 files changed, 53 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7748b8c8a66..104134cdb0e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -374,10 +374,6 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); - // We can't do lvalue-to-rvalue on atomics yet. - if (T->isAtomicType()) - return Owned(E); - // We don't want to throw lvalue-to-rvalue casts on top of // expressions of certain types in C++. if (getLangOpts().CPlusPlus && @@ -413,6 +409,15 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, 0, VK_RValue)); + // C11 6.3.2.1p2: + // ... if the lvalue has atomic type, the value has the non-atomic version + // of the type of the lvalue ... + if (const AtomicType *Atomic = T->getAs<AtomicType>()) { + T = Atomic->getValueType().getUnqualifiedType(); + Res = Owned(ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, + Res.get(), 0, VK_RValue)); + } + return Res; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 40fb01ac30d..89d4179fceb 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1294,6 +1294,11 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, return false; } +static bool isAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); + /// IsStandardConversion - Determines whether there is a standard /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the /// expression From to the type ToType. Standard conversion sequences @@ -1389,6 +1394,12 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; + // C11 6.3.2.1p2: + // ... if the lvalue has atomic type, the value has the non-atomic version + // of the type of the lvalue ... + if (const AtomicType *Atomic = FromType->getAs<AtomicType>()) + FromType = Atomic->getValueType(); + // If T is a non-class type, the type of the rvalue is the // cv-unqualified version of T. Otherwise, the type of the rvalue // is T (C++ 4.1p1). C++ can't get here with class types; in C, we @@ -1520,13 +1531,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS, CStyle)) { SCS.Second = ICK_TransparentUnionConversion; FromType = ToType; - } else if (const AtomicType *ToAtomicType = ToType->getAs<AtomicType>()) { - // Allow conversion to _Atomic types. These are C11 and are provided as an - // extension in C++ mode. - if (S.Context.hasSameUnqualifiedType(ToAtomicType->getValueType(), - FromType)) - SCS.Second = ICK_Identity; - FromType = ToType; + } else if (isAtomicConversion(S, From, ToType, InOverloadResolution, SCS, + CStyle)) { + // isAtomicConversion has updated the standard conversion sequence + // appropriately. + return true; } else { // No second conversion required. SCS.Second = ICK_Identity; @@ -2765,6 +2774,34 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); } +/// \brief - Determine whether this is a conversion from a scalar type to an +/// atomic type. +/// +/// If successful, updates \c SCS's second and third steps in the conversion +/// sequence to finish the conversion. +static bool isAtomicConversion(Sema &S, Expr *From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + const AtomicType *ToAtomic = ToType->getAs<AtomicType>(); + if (!ToAtomic) + return false; + + StandardConversionSequence InnerSCS; + if (!IsStandardConversion(S, From, ToAtomic->getValueType(), + InOverloadResolution, InnerSCS, + CStyle, /*AllowObjCWritebackConversion=*/false)) + return false; + + SCS.Second = InnerSCS.Second; + SCS.setToType(1, InnerSCS.getToType(1)); + SCS.Third = InnerSCS.Third; + SCS.QualificationIncludesObjCLifetime + = InnerSCS.QualificationIncludesObjCLifetime; + SCS.setToType(2, InnerSCS.getToType(2)); + return true; +} + static bool isFirstArgumentCompatibleWithType(ASTContext &Context, CXXConstructorDecl *Constructor, QualType Type) { |

