Yes, it is this change that broke us. I still don't fully understand what the change was, but it appears to mess things up for IWYU for operator== with templates and const, somehow.
Could you expand on what changed here and how the AST might be affected? Thanks, - Kim On Sat, Dec 28, 2019 at 4:35 PM Kim Gräsman <kim.gras...@gmail.com> wrote: > > 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