diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp | 286 |
1 files changed, 86 insertions, 200 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index dd2a4d2..6f676ad 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -91,30 +91,6 @@ DeduceTemplateArguments(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced); -/// \brief Whether template argument deduction for two reference parameters -/// resulted in the argument type, parameter type, or neither type being more -/// qualified than the other. -enum DeductionQualifierComparison { - NeitherMoreQualified = 0, - ParamMoreQualified, - ArgMoreQualified -}; - -/// \brief Stores the result of comparing two reference parameters while -/// performing template argument deduction for partial ordering of function -/// templates. -struct RefParamPartialOrderingComparison { - /// \brief Whether the parameter type is an rvalue reference type. - bool ParamIsRvalueRef; - /// \brief Whether the argument type is an rvalue reference type. - bool ArgIsRvalueRef; - - /// \brief Whether the parameter or argument (or neither) is more qualified. - DeductionQualifierComparison Qualifiers; -}; - - - static Sema::TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(Sema &S, TemplateParameterList *TemplateParams, @@ -124,9 +100,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, SmallVectorImpl<DeducedTemplateArgument> & Deduced, unsigned TDF, - bool PartialOrdering = false, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons = nullptr); + bool PartialOrdering = false); static Sema::TemplateDeductionResult DeduceTemplateArguments(Sema &S, @@ -602,6 +576,7 @@ struct clang::DeducedPack { DeducedPack *Outer; }; +namespace { /// A scope in which we're performing pack deduction. class PackDeductionScope { public: @@ -756,6 +731,7 @@ private: SmallVector<DeducedPack, 2> Packs; }; +} // namespace /// \brief Deduce the template arguments by comparing the list of parameter /// types to the list of argument types, as in the parameter-type-lists of @@ -784,9 +760,6 @@ private: /// deduction for during partial ordering for a call /// (C++0x [temp.deduct.partial]). /// -/// \param RefParamComparisons If we're performing template argument deduction -/// in the context of partial ordering, the set of qualifier comparisons. -/// /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. @@ -798,9 +771,7 @@ DeduceTemplateArguments(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, - bool PartialOrdering = false, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons = nullptr) { + bool PartialOrdering = false) { // Fast-path check to see if we have too many/too few arguments. if (NumParams != NumArgs && !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && @@ -836,8 +807,7 @@ DeduceTemplateArguments(Sema &S, = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Params[ParamIdx], Args[ArgIdx], Info, Deduced, TDF, - PartialOrdering, - RefParamComparisons)) + PartialOrdering)) return Result; ++ArgIdx; @@ -869,8 +839,7 @@ DeduceTemplateArguments(Sema &S, if (Sema::TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, Args[ArgIdx], Info, Deduced, - TDF, PartialOrdering, - RefParamComparisons)) + TDF, PartialOrdering)) return Result; PackScope.nextPackElement(); @@ -967,9 +936,6 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param, /// \param PartialOrdering Whether we're performing template argument deduction /// in the context of partial ordering (C++0x [temp.deduct.partial]). /// -/// \param RefParamComparisons If we're performing template argument deduction -/// in the context of partial ordering, the set of qualifier comparisons. -/// /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. @@ -980,9 +946,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, - bool PartialOrdering, - SmallVectorImpl<RefParamPartialOrderingComparison> * - RefParamComparisons) { + bool PartialOrdering) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. QualType Param = S.Context.getCanonicalType(ParamIn); @@ -995,7 +959,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, Arg = ArgExpansion->getPattern(); if (PartialOrdering) { - // C++0x [temp.deduct.partial]p5: + // C++11 [temp.deduct.partial]p5: // Before the partial ordering is done, certain transformations are // performed on the types used for partial ordering: // - If P is a reference type, P is replaced by the type referred to. @@ -1008,42 +972,42 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, if (ArgRef) Arg = ArgRef->getPointeeType(); - if (RefParamComparisons && ParamRef && ArgRef) { - // C++0x [temp.deduct.partial]p6: - // If both P and A were reference types (before being replaced with the - // type referred to above), determine which of the two types (if any) is - // more cv-qualified than the other; otherwise the types are considered - // to be equally cv-qualified for partial ordering purposes. The result - // of this determination will be used below. + if (ParamRef && ArgRef && S.Context.hasSameUnqualifiedType(Param, Arg)) { + // C++11 [temp.deduct.partial]p9: + // If, for a given type, deduction succeeds in both directions (i.e., + // the types are identical after the transformations above) and both + // P and A were reference types [...]: + // - if [one type] was an lvalue reference and [the other type] was + // not, [the other type] is not considered to be at least as + // specialized as [the first type] + // - if [one type] is more cv-qualified than [the other type], + // [the other type] is not considered to be at least as specialized + // as [the first type] + // Objective-C ARC adds: + // - [one type] has non-trivial lifetime, [the other type] has + // __unsafe_unretained lifetime, and the types are otherwise + // identical // - // We save this information for later, using it only when deduction - // succeeds in both directions. - RefParamPartialOrderingComparison Comparison; - Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>(); - Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>(); - Comparison.Qualifiers = NeitherMoreQualified; - + // A is "considered to be at least as specialized" as P iff deduction + // succeeds, so we model this as a deduction failure. Note that + // [the first type] is P and [the other type] is A here; the standard + // gets this backwards. Qualifiers ParamQuals = Param.getQualifiers(); Qualifiers ArgQuals = Arg.getQualifiers(); - if (ParamQuals.isStrictSupersetOf(ArgQuals)) - Comparison.Qualifiers = ParamMoreQualified; - else if (ArgQuals.isStrictSupersetOf(ParamQuals)) - Comparison.Qualifiers = ArgMoreQualified; - else if (ArgQuals.getObjCLifetime() != ParamQuals.getObjCLifetime() && - ArgQuals.withoutObjCLifetime() - == ParamQuals.withoutObjCLifetime()) { - // Prefer binding to non-__unsafe_autoretained parameters. - if (ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && - ParamQuals.getObjCLifetime()) - Comparison.Qualifiers = ParamMoreQualified; - else if (ParamQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && - ArgQuals.getObjCLifetime()) - Comparison.Qualifiers = ArgMoreQualified; + if ((ParamRef->isLValueReferenceType() && + !ArgRef->isLValueReferenceType()) || + ParamQuals.isStrictSupersetOf(ArgQuals) || + (ParamQuals.hasNonTrivialObjCLifetime() && + ArgQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone && + ParamQuals.withoutObjCLifetime() == + ArgQuals.withoutObjCLifetime())) { + Info.FirstArg = TemplateArgument(ParamIn); + Info.SecondArg = TemplateArgument(ArgIn); + return Sema::TDK_NonDeducedMismatch; } - RefParamComparisons->push_back(Comparison); } - // C++0x [temp.deduct.partial]p7: + // C++11 [temp.deduct.partial]p7: // Remove any top-level cv-qualifiers: // - If P is a cv-qualified type, P is replaced by the cv-unqualified // version of P. @@ -2784,7 +2748,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) { + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); @@ -2911,6 +2876,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, const_cast<NamedDecl *>(TemplateParams->getParam(I))); Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size())); + if (PartialOverloading) break; + return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete; } @@ -3136,34 +3103,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, // are ignored for type deduction. if (ParamType.hasQualifiers()) ParamType = ParamType.getUnqualifiedType(); - const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); - if (ParamRefType) { - QualType PointeeType = ParamRefType->getPointeeType(); - // If the argument has incomplete array type, try to complete its type. - if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) - ArgType = Arg->getType(); - - // [C++0x] If P is an rvalue reference to a cv-unqualified - // template parameter and the argument is an lvalue, the type - // "lvalue reference to A" is used in place of A for type - // deduction. - if (isa<RValueReferenceType>(ParamType)) { - if (!PointeeType.getQualifiers() && - isa<TemplateTypeParmType>(PointeeType) && - Arg->Classify(S.Context).isLValue() && - Arg->getType() != S.Context.OverloadTy && - Arg->getType() != S.Context.BoundMemberTy) - ArgType = S.Context.getLValueReferenceType(ArgType); - } - - // [...] If P is a reference type, the type referred to by P is used - // for type deduction. - ParamType = PointeeType; - } + // [...] If P is a reference type, the type referred to by P is + // used for type deduction. + const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); + if (ParamRefType) + ParamType = ParamRefType->getPointeeType(); - // Overload sets usually make this parameter an undeduced - // context, but there are sometimes special circumstances. + // Overload sets usually make this parameter an undeduced context, + // but there are sometimes special circumstances. Typically + // involving a template-id-expr. if (ArgType == S.Context.OverloadTy) { ArgType = ResolveOverloadForDeduction(S, TemplateParams, Arg, ParamType, @@ -3173,12 +3122,17 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, } if (ParamRefType) { + // If the argument has incomplete array type, try to complete its type. + if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) + ArgType = Arg->getType(); + // C++0x [temp.deduct.call]p3: - // [...] If P is of the form T&&, where T is a template parameter, and - // the argument is an lvalue, the type A& is used in place of A for - // type deduction. + // If P is an rvalue reference to a cv-unqualified template + // parameter and the argument is an lvalue, the type "lvalue + // reference to A" is used in place of A for type deduction. if (ParamRefType->isRValueReferenceType() && - ParamRefType->getAs<TemplateTypeParmType>() && + !ParamType.getQualifiers() && + isa<TemplateTypeParmType>(ParamType) && Arg->isLValue()) ArgType = S.Context.getLValueReferenceType(ArgType); } else { @@ -3298,26 +3252,28 @@ DeduceTemplateArgumentByListElement(Sema &S, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { + FunctionDecl *&Specialization, TemplateDeductionInfo &Info, + bool PartialOverloading) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + unsigned NumParams = Function->getNumParams(); // C++ [temp.deduct.call]p1: // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. unsigned CheckArgs = Args.size(); - if (Args.size() < Function->getMinRequiredArguments()) + if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) return TDK_TooFewArguments; - else if (Args.size() > Function->getNumParams()) { + else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { const FunctionProtoType *Proto = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) /* Do nothing */; else if (Proto->isVariadic()) - CheckArgs = Function->getNumParams(); + CheckArgs = NumParams; else return TDK_TooManyArguments; } @@ -3344,7 +3300,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified = Deduced.size(); } else { // Just fill in the parameter types from the function declaration. - for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + for (unsigned I = 0; I != NumParams; ++I) ParamTypes.push_back(Function->getParamDecl(I)->getType()); } @@ -3352,8 +3308,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( Deduced.resize(TemplateParams->size()); unsigned ArgIdx = 0; SmallVector<OriginalCallArg, 4> OriginalCallArgs; - for (unsigned ParamIdx = 0, NumParams = ParamTypes.size(); - ParamIdx != NumParams; ++ParamIdx) { + for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(); + ParamIdx != NumParamTypes; ++ParamIdx) { QualType OrigParamType = ParamTypes[ParamIdx]; QualType ParamType = OrigParamType; @@ -3422,7 +3378,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // the function parameter pack. For a function parameter pack that does // not occur at the end of the parameter-declaration-list, the type of // the parameter pack is a non-deduced context. - if (ParamIdx + 1 < NumParams) + if (ParamIdx + 1 < NumParamTypes) break; QualType ParamPattern = ParamExpansion->getPattern(); @@ -3492,7 +3448,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, - Info, &OriginalCallArgs); + Info, &OriginalCallArgs, + PartialOverloading); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, @@ -3699,8 +3656,10 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker( FunctionTemplateDecl *InvokerTemplate = LambdaClass-> getLambdaStaticInvoker()->getDescribedFunctionTemplate(); - Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result - = S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0, +#ifndef NDEBUG + Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result = +#endif + S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0, InvokerSpecialized, TDInfo); assert(Result == Sema::TDK_Success && "If the call operator succeeded so should the invoker!"); @@ -4153,8 +4112,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC, - unsigned NumCallArguments1, - SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { + unsigned NumCallArguments1) { FunctionDecl *FD1 = FT1->getTemplatedDecl(); FunctionDecl *FD2 = FT2->getTemplatedDecl(); const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>(); @@ -4219,8 +4177,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, Args2.resize(NumComparedArguments); if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), Args1.size(), Info, Deduced, - TDF_None, /*PartialOrdering=*/true, - RefParamComparisons)) + TDF_None, /*PartialOrdering=*/true)) return false; break; @@ -4232,7 +4189,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true, RefParamComparisons)) + /*PartialOrdering=*/true)) return false; break; @@ -4242,8 +4199,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, if (DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - RefParamComparisons)) + /*PartialOrdering=*/true)) return false; break; } @@ -4342,83 +4298,17 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, unsigned NumCallArguments2) { - SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons; bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, - NumCallArguments1, nullptr); + NumCallArguments1); bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, - NumCallArguments2, - &RefParamComparisons); + NumCallArguments2); if (Better1 != Better2) // We have a clear winner - return Better1? FT1 : FT2; + return Better1 ? FT1 : FT2; if (!Better1 && !Better2) // Neither is better than the other return nullptr; - // C++0x [temp.deduct.partial]p10: - // If for each type being considered a given template is at least as - // specialized for all types and more specialized for some set of types and - // the other template is not more specialized for any types or is not at - // least as specialized for any types, then the given template is more - // specialized than the other template. Otherwise, neither template is more - // specialized than the other. - Better1 = false; - Better2 = false; - for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) { - // C++0x [temp.deduct.partial]p9: - // If, for a given type, deduction succeeds in both directions (i.e., the - // types are identical after the transformations above) and both P and A - // were reference types (before being replaced with the type referred to - // above): - - // -- if the type from the argument template was an lvalue reference - // and the type from the parameter template was not, the argument - // type is considered to be more specialized than the other; - // otherwise, - if (!RefParamComparisons[I].ArgIsRvalueRef && - RefParamComparisons[I].ParamIsRvalueRef) { - Better2 = true; - if (Better1) - return nullptr; - continue; - } else if (!RefParamComparisons[I].ParamIsRvalueRef && - RefParamComparisons[I].ArgIsRvalueRef) { - Better1 = true; - if (Better2) - return nullptr; - continue; - } - - // -- if the type from the argument template is more cv-qualified than - // the type from the parameter template (as described above), the - // argument type is considered to be more specialized than the - // other; otherwise, - switch (RefParamComparisons[I].Qualifiers) { - case NeitherMoreQualified: - break; - - case ParamMoreQualified: - Better1 = true; - if (Better2) - return nullptr; - continue; - - case ArgMoreQualified: - Better2 = true; - if (Better1) - return nullptr; - continue; - } - - // -- neither type is more specialized than the other. - } - - assert(!(Better1 && Better2) && "Should have broken out in the loop above"); - if (Better1) - return FT1; - else if (Better2) - return FT2; - // FIXME: This mimics what GCC implements, but doesn't match up with the // proposed resolution for core issue 692. This area needs to be sorted out, // but for now we attempt to maintain compatibility. @@ -4591,8 +4481,7 @@ Sema::getMoreSpecializedPartialSpecialization( bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better1) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end()); InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info); @@ -4605,8 +4494,7 @@ Sema::getMoreSpecializedPartialSpecialization( Deduced.resize(PS1->getTemplateParameters()->size()); bool Better2 = !DeduceTemplateArgumentsByTypeMatch( *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better2) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); @@ -4649,8 +4537,7 @@ Sema::getMoreSpecializedPartialSpecialization( Deduced.resize(PS2->getTemplateParameters()->size()); bool Better1 = !DeduceTemplateArgumentsByTypeMatch( *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better1) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); @@ -4666,8 +4553,7 @@ Sema::getMoreSpecializedPartialSpecialization( bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None, - /*PartialOrdering=*/true, - /*RefParamComparisons=*/nullptr); + /*PartialOrdering=*/true); if (Better2) { SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end()); InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info); |