diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-07-31 06:31:19 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-07-31 06:31:19 +0000 |
commit | 77be48ac4744554b08b9a6587a4ade8601c9cc90 (patch) | |
tree | c1087a1b801effbd2418a6b09d1e749410ea6590 /clang/lib/Sema/SemaInit.cpp | |
parent | c537bd2da4c07c56dfa49a8bc593e4e61a84c5d2 (diff) | |
download | bcm5719-llvm-77be48ac4744554b08b9a6587a4ade8601c9cc90.tar.gz bcm5719-llvm-77be48ac4744554b08b9a6587a4ade8601c9cc90.zip |
PR18097: Support initializing an _Atomic(T) from an object of C++ class type T
or a class derived from T. We already supported this when initializing
_Atomic(T) from T for most (and maybe all) other reasonable values of T.
llvm-svn: 214390
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 947be780e02..d9f86c6e4fc 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2767,6 +2767,7 @@ void InitializationSequence::Step::Destroy() { case SK_QualificationConversionRValue: case SK_QualificationConversionXValue: case SK_QualificationConversionLValue: + case SK_AtomicConversion: case SK_LValueToRValue: case SK_ListInitialization: case SK_UnwrapInitList: @@ -2919,6 +2920,13 @@ void InitializationSequence::AddQualificationConversionStep(QualType Ty, Steps.push_back(S); } +void InitializationSequence::AddAtomicConversionStep(QualType Ty) { + Step S; + S.Kind = SK_AtomicConversion; + S.Type = Ty; + Steps.push_back(S); +} + void InitializationSequence::AddLValueToRValueStep(QualType Ty) { assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers"); @@ -4174,12 +4182,11 @@ static void TryDefaultInitialization(Sema &S, /// which enumerates all conversion functions and performs overload resolution /// to select the best. static void TryUserDefinedConversion(Sema &S, - const InitializedEntity &Entity, + QualType DestType, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence, bool TopLevelOfInitList) { - QualType DestType = Entity.getType(); assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); assert((DestType->isRecordType() || SourceType->isRecordType()) && @@ -4596,7 +4603,6 @@ void InitializationSequence::InitializeFrom(Sema &S, Initializer) || S.ConversionToObjCStringLiteralCheck(DestType, Initializer)) Args[0] = Initializer; - } if (!isa<InitListExpr>(Initializer)) SourceType = Initializer->getType(); @@ -4741,7 +4747,7 @@ void InitializationSequence::InitializeFrom(Sema &S, (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, - Entity.getType(), *this); + DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), // user-defined conversion sequences that can convert from the source // type to the destination type or (when a conversion function is @@ -4749,7 +4755,7 @@ void InitializationSequence::InitializeFrom(Sema &S, // 13.3.1.4, and the best one is chosen through overload resolution // (13.3). else - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this, + TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); return; } @@ -4763,9 +4769,22 @@ void InitializationSequence::InitializeFrom(Sema &S, // - Otherwise, if the source type is a (possibly cv-qualified) class // type, conversion functions are considered. if (!SourceType.isNull() && SourceType->isRecordType()) { - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this, + // For a conversion to _Atomic(T) from either T or a class type derived + // from T, initialize the T object then convert to _Atomic type. + bool NeedAtomicConversion = false; + if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) { + if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || + S.IsDerivedFrom(SourceType, Atomic->getValueType())) { + DestType = Atomic->getValueType(); + NeedAtomicConversion = true; + } + } + + TryUserDefinedConversion(S, DestType, Kind, Initializer, *this, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); + if (!Failed() && NeedAtomicConversion) + AddAtomicConversionStep(Entity.getType()); return; } @@ -4774,16 +4793,16 @@ void InitializationSequence::InitializeFrom(Sema &S, // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. - + ImplicitConversionSequence ICS - = S.TryImplicitConversion(Initializer, Entity.getType(), + = S.TryImplicitConversion(Initializer, DestType, /*SuppressUserConversions*/true, /*AllowExplicitConversions*/ false, /*InOverloadResolution*/ false, /*CStyle=*/Kind.isCStyleOrFunctionalCast(), allowObjCWritebackConversion); - - if (ICS.isStandard() && + + if (ICS.isStandard() && ICS.Standard.Second == ICK_Writeback_Conversion) { // Objective-C ARC writeback conversion. @@ -4804,7 +4823,7 @@ void InitializationSequence::InitializeFrom(Sema &S, AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0)); } - AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy); + AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy); } else if (ICS.isBad()) { DeclAccessPair dap; if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) { @@ -4816,7 +4835,7 @@ void InitializationSequence::InitializeFrom(Sema &S, else SetFailed(InitializationSequence::FK_ConversionFailed); } else { - AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList); + AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList); MaybeProduceObjCObject(S, *this, Entity); } @@ -5772,6 +5791,7 @@ InitializationSequence::Perform(Sema &S, case SK_QualificationConversionLValue: case SK_QualificationConversionXValue: case SK_QualificationConversionRValue: + case SK_AtomicConversion: case SK_LValueToRValue: case SK_ConversionSequence: case SK_ConversionSequenceNoNarrowing: @@ -6062,6 +6082,13 @@ InitializationSequence::Perform(Sema &S, break; } + case SK_AtomicConversion: { + assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic"); + CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, + CK_NonAtomicToAtomic, VK_RValue); + break; + } + case SK_LValueToRValue: { assert(CurInit.get()->isGLValue() && "cannot load from a prvalue"); CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, @@ -7033,6 +7060,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "qualification conversion (lvalue)"; break; + case SK_AtomicConversion: + OS << "non-atomic-to-atomic conversion"; + break; + case SK_LValueToRValue: OS << "load (lvalue to rvalue)"; break; |