diff options
author | Richard Smith <richard@metafoo.co.uk> | 2019-12-18 14:01:40 -0800 |
---|---|---|
committer | Richard Smith <richard@metafoo.co.uk> | 2019-12-18 14:05:57 -0800 |
commit | 3ced23976aa8a86a17017c87821c873b4ca80bc2 (patch) | |
tree | 1a42f80c2dee147ac0b98dccbd27eae4143da3c8 /clang/lib/Sema/SemaInit.cpp | |
parent | a6d57a8cd4cfa2a8395eaa6599fc12f7509f98f0 (diff) | |
download | bcm5719-llvm-3ced23976aa8a86a17017c87821c873b4ca80bc2.tar.gz bcm5719-llvm-3ced23976aa8a86a17017c87821c873b4ca80bc2.zip |
Refactor CompareReferenceRelationship and its callers in preparation for
implementing the resolution of CWG2352.
No functionality change, except that we now convert the referent of a
reference binding to the underlying type of the reference in more cases;
we used to happen to preserve the type sugar from the referent if the
only type change was in the cv-qualifiers.
This exposed a bug in how we generate code for trivial assignment
operators: if the type sugar (particularly the may_alias attribute)
got lost during reference binding, we'd use the "wrong" TBAA information
for the load during the assignment.
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 88 |
1 files changed, 42 insertions, 46 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index cc9d1a4f625..94d524a63f5 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4229,10 +4229,8 @@ static void TryReferenceListInitialization(Sema &S, return; SourceLocation DeclLoc = Initializer->getBeginLoc(); - bool dummy1, dummy2, dummy3, dummy4; Sema::ReferenceCompareResult RefRelationship - = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, dummy1, - dummy2, dummy3, dummy4); + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2); if (RefRelationship >= Sema::Ref_Related) { // Try to bind the reference here. TryReferenceInitializationCore(S, Entity, Kind, Initializer, cv1T1, T1, @@ -4469,18 +4467,8 @@ static OverloadingResult TryRefInitWithConversionFunction( QualType cv2T2 = Initializer->getType(); QualType T2 = cv2T2.getUnqualifiedType(); - bool DerivedToBase; - bool ObjCConversion; - bool ObjCLifetimeConversion; - bool FunctionConversion; - assert(!S.CompareReferenceRelationship( - Initializer->getBeginLoc(), T1, T2, DerivedToBase, ObjCConversion, - ObjCLifetimeConversion, FunctionConversion) && + assert(!S.CompareReferenceRelationship(Initializer->getBeginLoc(), T1, T2) && "Must have incompatible references when binding via conversion"); - (void)DerivedToBase; - (void)ObjCConversion; - (void)ObjCLifetimeConversion; - (void)FunctionConversion; // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -4604,14 +4592,9 @@ static OverloadingResult TryRefInitWithConversionFunction( // Determine whether we'll need to perform derived-to-base adjustments or // other conversions. - bool NewDerivedToBase = false; - bool NewObjCConversion = false; - bool NewObjCLifetimeConversion = false; - bool NewFunctionConversion = false; + Sema::ReferenceConversions RefConv; Sema::ReferenceCompareResult NewRefRelationship = - S.CompareReferenceRelationship( - DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion, - NewObjCLifetimeConversion, NewFunctionConversion); + S.CompareReferenceRelationship(DeclLoc, T1, cv3T3, &RefConv); // Add the final conversion sequence, if necessary. if (NewRefRelationship == Sema::Ref_Incompatible) { @@ -4641,12 +4624,16 @@ static OverloadingResult TryRefInitWithConversionFunction( Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue); VK = IsLValueRef ? VK_LValue : VK_XValue; - if (NewDerivedToBase) + if (RefConv & Sema::ReferenceConversions::DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, VK); - else if (NewObjCConversion) + else if (RefConv & Sema::ReferenceConversions::ObjC) Sequence.AddObjCObjectConversionStep(cv1T1); - else if (NewFunctionConversion) + else if (RefConv & Sema::ReferenceConversions::Function) Sequence.AddQualificationConversionStep(cv1T1, VK); + else if (RefConv & Sema::ReferenceConversions::Qualification) { + if (!S.Context.hasSameType(cv1T4, cv1T1)) + Sequence.AddQualificationConversionStep(cv1T1, VK); + } return OR_Success; } @@ -4700,17 +4687,15 @@ static void TryReferenceInitializationCore(Sema &S, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); SourceLocation DeclLoc = Initializer->getBeginLoc(); + // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; - bool DerivedToBase = false; - bool ObjCConversion = false; - bool ObjCLifetimeConversion = false; - bool FunctionConversion = false; Expr::Classification InitCategory = Initializer->Classify(S.Context); - Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship( - DeclLoc, cv1T1, cv2T2, DerivedToBase, ObjCConversion, - ObjCLifetimeConversion, FunctionConversion); + + Sema::ReferenceConversions RefConv; + Sema::ReferenceCompareResult RefRelationship = + S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, &RefConv); // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression of type @@ -4730,19 +4715,25 @@ static void TryReferenceInitializationCore(Sema &S, RefRelationship == Sema::Ref_Related))) { // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or - if (T1Quals != T2Quals) - // Convert to cv1 T2. This should only add qualifiers unless this is a - // c-style cast. The removal of qualifiers in that case notionally - // happens after the reference binding, but that doesn't matter. - Sequence.AddQualificationConversionStep( - S.Context.getQualifiedType(T2, T1Quals), - Initializer->getValueKind()); - if (DerivedToBase) - Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); - else if (ObjCConversion) - Sequence.AddObjCObjectConversionStep(cv1T1); - else if (FunctionConversion) - Sequence.AddQualificationConversionStep(cv1T1, VK_LValue); + if (RefConv & (Sema::ReferenceConversions::DerivedToBase | + Sema::ReferenceConversions::ObjC)) { + // If we're converting the pointee, add any qualifiers first; + // these qualifiers must all be top-level, so just convert to "cv1 T2". + if (RefConv & (Sema::ReferenceConversions::Qualification)) + Sequence.AddQualificationConversionStep( + S.Context.getQualifiedType(T2, T1Quals), + Initializer->getValueKind()); + if (RefConv & Sema::ReferenceConversions::DerivedToBase) + Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); + else + Sequence.AddObjCObjectConversionStep(cv1T1); + } else if (RefConv & (Sema::ReferenceConversions::Qualification | + Sema::ReferenceConversions::Function)) { + // Perform a (possibly multi-level) qualification conversion. + // FIXME: Should we use a different step kind for function conversions? + Sequence.AddQualificationConversionStep(cv1T1, + Initializer->getValueKind()); + } // We only create a temporary here when binding a reference to a // bit-field or vector element. Those cases are't supposed to be @@ -4873,14 +4864,19 @@ static void TryReferenceInitializationCore(Sema &S, T4Quals.addAddressSpace(T1Quals.getAddressSpace()); QualType cv1T4WithAS = S.Context.getQualifiedType(T2, T4Quals); Sequence.AddQualificationConversionStep(cv1T4WithAS, ValueKind); + cv1T4 = cv1T4WithAS; } // In any case, the reference is bound to the resulting glvalue (or to // an appropriate base class subobject). - if (DerivedToBase) + if (RefConv & Sema::ReferenceConversions::DerivedToBase) Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind); - else if (ObjCConversion) + else if (RefConv & Sema::ReferenceConversions::ObjC) Sequence.AddObjCObjectConversionStep(cv1T1); + else if (RefConv & Sema::ReferenceConversions::Qualification) { + if (!S.Context.hasSameType(cv1T4, cv1T1)) + Sequence.AddQualificationConversionStep(cv1T1, ValueKind); + } return; } |