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