summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2019-12-18 14:01:40 -0800
committerRichard Smith <richard@metafoo.co.uk>2019-12-18 14:05:57 -0800
commit3ced23976aa8a86a17017c87821c873b4ca80bc2 (patch)
tree1a42f80c2dee147ac0b98dccbd27eae4143da3c8 /clang/lib/Sema/SemaInit.cpp
parenta6d57a8cd4cfa2a8395eaa6599fc12f7509f98f0 (diff)
downloadbcm5719-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.cpp88
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;
}
OpenPOWER on IntegriCloud