summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOverload.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/SemaOverload.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/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp124
1 files changed, 50 insertions, 74 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 22f1a087ca2..74a0bc7c78f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -4412,10 +4412,7 @@ static bool isTypeValid(QualType T) {
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
- bool &DerivedToBase,
- bool &ObjCConversion,
- bool &ObjCLifetimeConversion,
- bool &FunctionConversion) {
+ ReferenceConversions *ConvOut) {
assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
@@ -4426,24 +4423,25 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+ ReferenceConversions ConvTmp;
+ ReferenceConversions &Conv = ConvOut ? *ConvOut : ConvTmp;
+ Conv = ReferenceConversions();
+
// C++ [dcl.init.ref]p4:
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
// reference-related to "cv2 T2" if T1 is the same type as T2, or
// T1 is a base class of T2.
- DerivedToBase = false;
- ObjCConversion = false;
- ObjCLifetimeConversion = false;
QualType ConvertedT2;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (isCompleteType(Loc, OrigT2) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
IsDerivedFrom(Loc, UnqualT2, UnqualT1))
- DerivedToBase = true;
+ Conv |= ReferenceConversions::DerivedToBase;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
- ObjCConversion = true;
+ Conv |= ReferenceConversions::ObjC;
else if (UnqualT2->isFunctionType() &&
IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
// C++1z [dcl.init.ref]p4:
@@ -4452,7 +4450,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
//
// We extend this to also apply to 'noreturn', so allow any function
// conversion between function types.
- FunctionConversion = true;
+ Conv |= ReferenceConversions::Function;
return Ref_Compatible;
} else
return Ref_Incompatible;
@@ -4482,7 +4480,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
- ObjCLifetimeConversion = true;
+ Conv |= ReferenceConversions::ObjCLifetime;
T1Quals.removeObjCLifetime();
T2Quals.removeObjCLifetime();
@@ -4492,6 +4490,9 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
T1Quals.removeUnaligned();
T2Quals.removeUnaligned();
+ if (T1Quals != T2Quals)
+ Conv |= ReferenceConversions::Qualification;
+
if (T1Quals.compatiblyIncludes(T2Quals))
return Ref_Compatible;
else
@@ -4532,11 +4533,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
continue;
if (AllowRvalues) {
- bool DerivedToBase = false;
- bool ObjCConversion = false;
- bool ObjCLifetimeConversion = false;
- bool FunctionConversion = false;
-
// If we are initializing an rvalue reference, don't permit conversion
// functions that return lvalues.
if (!ConvTemplate && DeclType->isRValueReferenceType()) {
@@ -4552,9 +4548,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
Conv->getConversionType()
.getNonReferenceType()
.getUnqualifiedType(),
- DeclType.getNonReferenceType().getUnqualifiedType(),
- DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
- FunctionConversion) == Sema::Ref_Incompatible)
+ DeclType.getNonReferenceType().getUnqualifiedType()) ==
+ Sema::Ref_Incompatible)
continue;
} else {
// If the conversion function doesn't return a reference type,
@@ -4655,14 +4650,36 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// Compute some basic properties of the types and the initializer.
bool isRValRef = DeclType->isRValueReferenceType();
- bool DerivedToBase = false;
- bool ObjCConversion = false;
- bool ObjCLifetimeConversion = false;
- bool FunctionConversion = false;
Expr::Classification InitCategory = Init->Classify(S.Context);
- Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(
- DeclLoc, T1, T2, DerivedToBase, ObjCConversion, ObjCLifetimeConversion,
- FunctionConversion);
+
+ Sema::ReferenceConversions RefConv;
+ Sema::ReferenceCompareResult RefRelationship =
+ S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv);
+
+ auto SetAsReferenceBinding = [&](bool BindsDirectly) {
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = (RefConv & Sema::ReferenceConversions::DerivedToBase)
+ ? ICK_Derived_To_Base
+ : (RefConv & Sema::ReferenceConversions::ObjC)
+ ? ICK_Compatible_Conversion
+ : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.DirectBinding = BindsDirectly;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = InitCategory.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ ICS.Standard.ObjCLifetimeConversionBinding =
+ (RefConv & Sema::ReferenceConversions::ObjCLifetime) != 0;
+ ICS.Standard.CopyConstructor = nullptr;
+ ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ };
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression
@@ -4682,25 +4699,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// has a type that is a derived class of the parameter type,
// in which case the implicit conversion sequence is a
// derived-to-base Conversion (13.3.3.1).
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
- : ObjCConversion? ICK_Compatible_Conversion
- : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- ICS.Standard.DirectBinding = true;
- ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.Standard.BindsToRvalue = false;
- ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
- ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = nullptr;
- ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ SetAsReferenceBinding(/*BindsDirectly=*/true);
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@@ -4738,34 +4737,16 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or
if (RefRelationship == Sema::Ref_Compatible &&
(InitCategory.isXValue() ||
- (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+ (InitCategory.isPRValue() &&
+ (T2->isRecordType() || T2->isArrayType())) ||
(InitCategory.isLValue() && T2->isFunctionType()))) {
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
- : ObjCConversion? ICK_Compatible_Conversion
- : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- // In C++0x, this is always a direct binding. In C++98/03, it's a direct
+ // In C++11, this is always a direct binding. In C++98/03, it's a direct
// binding unless we're binding to a class prvalue.
// Note: Although xvalues wouldn't normally show up in C++98/03 code, we
// allow the use of rvalue references in C++98/03 for the benefit of
// standard library implementors; therefore, we need the xvalue check here.
- ICS.Standard.DirectBinding =
- S.getLangOpts().CPlusPlus11 ||
- !(InitCategory.isPRValue() || T2->isRecordType());
- ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.Standard.BindsToRvalue = InitCategory.isRValue();
- ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
- ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
- ICS.Standard.CopyConstructor = nullptr;
- ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
+ SetAsReferenceBinding(/*BindsDirectly=*/S.getLangOpts().CPlusPlus11 ||
+ !(InitCategory.isPRValue() || T2->isRecordType()));
return ICS;
}
@@ -5084,13 +5065,8 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
}
// Compute some basic properties of the types and the initializer.
- bool dummy1 = false;
- bool dummy2 = false;
- bool dummy3 = false;
- bool dummy4 = false;
Sema::ReferenceCompareResult RefRelationship =
- S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2, dummy1,
- dummy2, dummy3, dummy4);
+ S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2);
if (RefRelationship >= Sema::Ref_Related) {
return TryReferenceInit(S, Init, ToType, /*FIXME*/ From->getBeginLoc(),
OpenPOWER on IntegriCloud