Hi Richard, I see the commit message mentions type sugar here; does this change affect the AST at all?
We're seeing test failures in IWYU based on recent Clang, and I'm suspecting this commit (it takes me a while to bisect because of Clang build times on my laptop). Thanks, - Kim On Wed, Dec 18, 2019 at 11:06 PM Richard Smith via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > > Author: Richard Smith > Date: 2019-12-18T14:05:57-08:00 > New Revision: 3ced23976aa8a86a17017c87821c873b4ca80bc2 > > URL: > https://github.com/llvm/llvm-project/commit/3ced23976aa8a86a17017c87821c873b4ca80bc2 > DIFF: > https://github.com/llvm/llvm-project/commit/3ced23976aa8a86a17017c87821c873b4ca80bc2.diff > > LOG: 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. > > Added: > > > Modified: > clang/include/clang/Sema/Sema.h > clang/lib/CodeGen/CGExprCXX.cpp > clang/lib/Sema/SemaCast.cpp > clang/lib/Sema/SemaExprCXX.cpp > clang/lib/Sema/SemaInit.cpp > clang/lib/Sema/SemaOverload.cpp > clang/test/AST/ast-dump-expr-json.cpp > clang/test/Index/print-type.cpp > > Removed: > > > > ################################################################################ > diff --git a/clang/include/clang/Sema/Sema.h > b/clang/include/clang/Sema/Sema.h > index 2730eef0bdd8..07eba0306c98 100755 > --- a/clang/include/clang/Sema/Sema.h > +++ b/clang/include/clang/Sema/Sema.h > @@ -31,6 +31,7 @@ > #include "clang/AST/StmtCXX.h" > #include "clang/AST/TypeLoc.h" > #include "clang/AST/TypeOrdering.h" > +#include "clang/Basic/BitmaskEnum.h" > #include "clang/Basic/ExpressionTraits.h" > #include "clang/Basic/Module.h" > #include "clang/Basic/OpenMPKinds.h" > @@ -10703,11 +10704,26 @@ class Sema final { > Ref_Compatible > }; > > + // Fake up a scoped enumeration that still contextually converts to bool. > + struct ReferenceConversionsScope { > + /// The conversions that would be performed on an lvalue of type T2 when > + /// binding a reference of type T1 to it, as determined when evaluating > + /// whether T1 is reference-compatible with T2. > + enum ReferenceConversions { > + Qualification = 0x1, > + Function = 0x2, > + DerivedToBase = 0x4, > + ObjC = 0x8, > + ObjCLifetime = 0x10, > + > + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime) > + }; > + }; > + using ReferenceConversions = > ReferenceConversionsScope::ReferenceConversions; > + > ReferenceCompareResult > CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2, > - bool &DerivedToBase, bool &ObjCConversion, > - bool &ObjCLifetimeConversion, > - bool &FunctionConversion); > + ReferenceConversions *Conv = nullptr); > > ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, > Expr *CastExpr, CastKind &CastKind, > > diff --git a/clang/lib/CodeGen/CGExprCXX.cpp > b/clang/lib/CodeGen/CGExprCXX.cpp > index 269b80b43403..3fc86136c529 100644 > --- a/clang/lib/CodeGen/CGExprCXX.cpp > +++ b/clang/lib/CodeGen/CGExprCXX.cpp > @@ -241,16 +241,28 @@ RValue > CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( > } > } > > + bool TrivialForCodegen = > + MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion()); > + bool TrivialAssignment = > + TrivialForCodegen && > + (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) && > + !MD->getParent()->mayInsertExtraPadding(); > + > // C++17 demands that we evaluate the RHS of a (possibly-compound) > assignment > // operator before the LHS. > CallArgList RtlArgStorage; > CallArgList *RtlArgs = nullptr; > + LValue TrivialAssignmentRHS; > if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) { > if (OCE->isAssignmentOp()) { > - RtlArgs = &RtlArgStorage; > - EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(), > - drop_begin(CE->arguments(), 1), CE->getDirectCallee(), > - /*ParamsToSkip*/0, EvaluationOrder::ForceRightToLeft); > + if (TrivialAssignment) { > + TrivialAssignmentRHS = EmitLValue(CE->getArg(1)); > + } else { > + RtlArgs = &RtlArgStorage; > + EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(), > + drop_begin(CE->arguments(), 1), CE->getDirectCallee(), > + /*ParamsToSkip*/0, EvaluationOrder::ForceRightToLeft); > + } > } > } > > @@ -281,22 +293,25 @@ RValue > CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( > return RValue::get(nullptr); > } > > - if (MD->isTrivial() || (MD->isDefaulted() && MD->getParent()->isUnion())) { > - if (isa<CXXDestructorDecl>(MD)) return RValue::get(nullptr); > - if (!MD->getParent()->mayInsertExtraPadding()) { > - if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { > - // We don't like to generate the trivial copy/move assignment > operator > - // when it isn't necessary; just produce the proper effect here. > - LValue RHS = isa<CXXOperatorCallExpr>(CE) > - ? MakeNaturalAlignAddrLValue( > - (*RtlArgs)[0].getRValue(*this).getScalarVal(), > - (*(CE->arg_begin() + 1))->getType()) > - : EmitLValue(*CE->arg_begin()); > - EmitAggregateAssign(This, RHS, CE->getType()); > - return RValue::get(This.getPointer(*this)); > - } > - llvm_unreachable("unknown trivial member function"); > + if (TrivialForCodegen) { > + if (isa<CXXDestructorDecl>(MD)) > + return RValue::get(nullptr); > + > + if (TrivialAssignment) { > + // We don't like to generate the trivial copy/move assignment operator > + // when it isn't necessary; just produce the proper effect here. > + // It's important that we use the result of EmitLValue here rather than > + // emitting call arguments, in order to preserve TBAA information from > + // the RHS. > + LValue RHS = isa<CXXOperatorCallExpr>(CE) > + ? TrivialAssignmentRHS > + : EmitLValue(*CE->arg_begin()); > + EmitAggregateAssign(This, RHS, CE->getType()); > + return RValue::get(This.getPointer(*this)); > } > + > + assert(MD->getParent()->mayInsertExtraPadding() && > + "unknown trivial member function"); > } > > // Compute the function type we're calling. > > diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp > index d0b9fe122895..6216206690b0 100644 > --- a/clang/lib/Sema/SemaCast.cpp > +++ b/clang/lib/Sema/SemaCast.cpp > @@ -1306,10 +1306,6 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr > *SrcExpr, > // Because we try the reference downcast before this function, from now on > // this is the only cast possibility, so we issue an error if we fail now. > // FIXME: Should allow casting away constness if CStyle. > - bool DerivedToBase; > - bool ObjCConversion; > - bool ObjCLifetimeConversion; > - bool FunctionConversion; > QualType FromType = SrcExpr->getType(); > QualType ToType = R->getPointeeType(); > if (CStyle) { > @@ -1317,9 +1313,9 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr > *SrcExpr, > ToType = ToType.getUnqualifiedType(); > } > > + Sema::ReferenceConversions RefConv; > Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship( > - SrcExpr->getBeginLoc(), ToType, FromType, DerivedToBase, > ObjCConversion, > - ObjCLifetimeConversion, FunctionConversion); > + SrcExpr->getBeginLoc(), ToType, FromType, &RefConv); > if (RefResult != Sema::Ref_Compatible) { > if (CStyle || RefResult == Sema::Ref_Incompatible) > return TC_NotApplicable; > @@ -1331,7 +1327,7 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr > *SrcExpr, > return TC_Failed; > } > > - if (DerivedToBase) { > + if (RefConv & Sema::ReferenceConversions::DerivedToBase) { > Kind = CK_DerivedToBase; > CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, > /*DetectVirtual=*/true); > > diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp > index 47b58df0acd9..cfb3a05e9c14 100644 > --- a/clang/lib/Sema/SemaExprCXX.cpp > +++ b/clang/lib/Sema/SemaExprCXX.cpp > @@ -5862,29 +5862,29 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult > &Cond, ExprResult &LHS, > // FIXME: > // Resolving a defect in P0012R1: we extend this to cover all cases where > // one of the operands is reference-compatible with the other, in order > - // to support conditionals between functions > diff ering in noexcept. > + // to support conditionals between functions > diff ering in noexcept. This > + // will similarly cover > diff erence in array bounds after P0388R4. > ExprValueKind LVK = LHS.get()->getValueKind(); > ExprValueKind RVK = RHS.get()->getValueKind(); > if (!Context.hasSameType(LTy, RTy) && > LVK == RVK && LVK != VK_RValue) { > // DerivedToBase was already handled by the class-specific case above. > // FIXME: Should we allow ObjC conversions here? > - bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion, > - FunctionConversion; > - if (CompareReferenceRelationship(QuestionLoc, LTy, RTy, DerivedToBase, > - ObjCConversion, ObjCLifetimeConversion, > - FunctionConversion) == Ref_Compatible && > - !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion && > + const ReferenceConversions AllowedConversions = > + ReferenceConversions::Qualification | ReferenceConversions::Function; > + > + ReferenceConversions RefConv; > + if (CompareReferenceRelationship(QuestionLoc, LTy, RTy, &RefConv) == > + Ref_Compatible && > + !(RefConv & ~AllowedConversions) && > // [...] subject to the constraint that the reference must bind > // directly [...] > !RHS.get()->refersToBitField() && > !RHS.get()->refersToVectorElement()) { > RHS = ImpCastExprToType(RHS.get(), LTy, CK_NoOp, RVK); > RTy = RHS.get()->getType(); > - } else if (CompareReferenceRelationship( > - QuestionLoc, RTy, LTy, DerivedToBase, ObjCConversion, > - ObjCLifetimeConversion, > - FunctionConversion) == Ref_Compatible && > - !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion > && > + } else if (CompareReferenceRelationship(QuestionLoc, RTy, LTy, &RefConv) > == > + Ref_Compatible && > + !(RefConv & ~AllowedConversions) && > !LHS.get()->refersToBitField() && > !LHS.get()->refersToVectorElement()) { > LHS = ImpCastExprToType(LHS.get(), RTy, CK_NoOp, LVK); > > diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp > index cc9d1a4f6256..94d524a63f5a 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 > diff erent 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; > } > > > diff --git a/clang/lib/Sema/SemaOverload.cpp > b/clang/lib/Sema/SemaOverload.cpp > index 22f1a087ca22..74a0bc7c78ff 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(), > > diff --git a/clang/test/AST/ast-dump-expr-json.cpp > b/clang/test/AST/ast-dump-expr-json.cpp > index 0459c1842787..09e775e22ecf 100644 > --- a/clang/test/AST/ast-dump-expr-json.cpp > +++ b/clang/test/AST/ast-dump-expr-json.cpp > @@ -7991,7 +7991,6 @@ void TestNonADLCall3() { > // CHECK-NEXT: } > // CHECK-NEXT: }, > // CHECK-NEXT: "type": { > -// CHECK-NEXT: "desugaredQualType": "const NS::X", > // CHECK-NEXT: "qualType": "const NS::X" > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "lvalue", > @@ -8148,7 +8147,6 @@ void TestNonADLCall3() { > // CHECK-NEXT: } > // CHECK-NEXT: }, > // CHECK-NEXT: "type": { > -// CHECK-NEXT: "desugaredQualType": "const NS::X", > // CHECK-NEXT: "qualType": "const NS::X" > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "lvalue", > @@ -8430,7 +8428,6 @@ void TestNonADLCall3() { > // CHECK-NEXT: } > // CHECK-NEXT: }, > // CHECK-NEXT: "type": { > -// CHECK-NEXT: "desugaredQualType": "const NS::X", > // CHECK-NEXT: "qualType": "const NS::X" > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "lvalue", > @@ -8758,7 +8755,6 @@ void TestNonADLCall3() { > // CHECK-NEXT: } > // CHECK-NEXT: }, > // CHECK-NEXT: "type": { > -// CHECK-NEXT: "desugaredQualType": "const NS::X", > // CHECK-NEXT: "qualType": "const NS::X" > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "lvalue", > @@ -8915,7 +8911,6 @@ void TestNonADLCall3() { > // CHECK-NEXT: } > // CHECK-NEXT: }, > // CHECK-NEXT: "type": { > -// CHECK-NEXT: "desugaredQualType": "const NS::X", > // CHECK-NEXT: "qualType": "const NS::X" > // CHECK-NEXT: }, > // CHECK-NEXT: "valueCategory": "lvalue", > > diff --git a/clang/test/Index/print-type.cpp > b/clang/test/Index/print-type.cpp > index 32d1185eecb9..abe8d45c41db 100644 > --- a/clang/test/Index/print-type.cpp > +++ b/clang/test/Index/print-type.cpp > @@ -196,7 +196,7 @@ inline namespace InlineNS {} > // CHECK: TemplateRef=Specialization:66:8 [type=] [typekind=Invalid] > [isPOD=0] > // CHECK: CallExpr=Specialization:66:8 > [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] > [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] > [canonicaltype=Specialization<Specialization<bool> &>] > [canonicaltypekind=Record] [canonicaltemplateargs/1= > [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1] > // CHECK: VarDecl=autoTemplRefParam:72:6 (Definition) > [type=Specialization<Specialization<bool> &>] [typekind=Auto] > [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] > [canonicaltype=Specialization<Specialization<bool> &>] > [canonicaltypekind=Record] [canonicaltemplateargs/1= > [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1] > -// CHECK: UnexposedExpr=templRefParam:71:40 [type=const > Specialization<Specialization<bool> &>] [typekind=Unexposed] const > [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] > [canonicaltype=const Specialization<Specialization<bool> &>] > [canonicaltypekind=Record] [canonicaltemplateargs/1= > [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1] > +// CHECK: UnexposedExpr=templRefParam:71:40 [type=const > Specialization<Specialization<bool> &>] [typekind=Record] const > [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] > [isPOD=1] > // CHECK: DeclRefExpr=templRefParam:71:40 > [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] > [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] > [canonicaltype=Specialization<Specialization<bool> &>] > [canonicaltypekind=Record] [canonicaltemplateargs/1= > [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1] > // CHECK: TypeAliasDecl=baz:76:7 (Definition) [type=baz] [typekind=Typedef] > [templateargs/1= [type=A<void>] [typekind=Unexposed]] [canonicaltype=A<void>] > [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=void] > [typekind=Void]] [isPOD=0] > // CHECK: VarDecl=autoTemplPointer:78:6 (Definition) > [type=Specialization<Specialization<bool> &> *] [typekind=Auto] > [canonicaltype=Specialization<Specialization<bool> &> *] > [canonicaltypekind=Pointer] [isPOD=1] > [pointeetype=Specialization<Specialization<bool> &>] [pointeekind=Record] > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits