diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-05 23:02:44 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-05 23:02:44 +0000 |
commit | c92d206ce441934a28e5886b5d635748f865a808 (patch) | |
tree | cc70df83508f88b410b563f53fa0f68b90e797ad /clang/lib/Sema/SemaTemplateDeduction.cpp | |
parent | 1594e0629d02a4a5c7598da6b5bb2a2bfef4207e (diff) | |
download | bcm5719-llvm-c92d206ce441934a28e5886b5d635748f865a808.tar.gz bcm5719-llvm-c92d206ce441934a28e5886b5d635748f865a808.zip |
Add missing "original call argument has same type as deduced parameter type"
check for deductions from elements of a braced-init-list.
llvm-svn: 291190
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 101 |
1 files changed, 80 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 7750b9c0eae..043e5c37160 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeOrdering.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Sema.h" #include "clang/Sema/Template.h" @@ -2856,6 +2857,36 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, return true; } +/// Find the pack index for a particular parameter index in an instantiation of +/// a function template with specific arguments. +/// +/// \return The pack index for whichever pack produced this parameter, or -1 +/// if this was not produced by a parameter. Intended to be used as the +/// ArgumentPackSubstitutionIndex for further substitutions. +// FIXME: We should track this in OriginalCallArgs so we don't need to +// reconstruct it here. +static unsigned getPackIndexForParam(Sema &S, + FunctionTemplateDecl *FunctionTemplate, + const MultiLevelTemplateArgumentList &Args, + unsigned ParamIdx) { + unsigned Idx = 0; + for (auto *PD : FunctionTemplate->getTemplatedDecl()->parameters()) { + if (PD->isParameterPack()) { + unsigned NumExpansions = + S.getNumArgumentsInExpansion(PD->getType(), Args).getValueOr(1); + if (Idx + NumExpansions > ParamIdx) + return ParamIdx - Idx; + Idx += NumExpansions; + } else { + if (Idx == ParamIdx) + return -1; // Not a pack expansion + ++Idx; + } + } + + llvm_unreachable("parameter index would not be produced from template"); +} + /// \brief Finish template argument deduction for a function template, /// checking the deduced template arguments for completeness and forming /// the function template specialization. @@ -2906,9 +2937,9 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); + MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList); Specialization = cast_or_null<FunctionDecl>( - SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, - MultiLevelTemplateArgumentList(*DeducedArgumentList))); + SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) return TDK_SubstitutionFailure; @@ -2934,19 +2965,46 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // In general, the deduction process attempts to find template argument // values that will make the deduced A identical to A (after the type A // is transformed as described above). [...] + llvm::SmallDenseMap<std::pair<unsigned, QualType>, QualType> DeducedATypes; for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) { OriginalCallArg OriginalArg = (*OriginalCallArgs)[I]; - unsigned ParamIdx = OriginalArg.ArgIdx; + auto ParamIdx = OriginalArg.ArgIdx; if (ParamIdx >= Specialization->getNumParams()) + // FIXME: This presumably means a pack ended up smaller than we + // expected while deducing. Should this not result in deduction + // failure? Can it even happen? continue; - QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType(); + QualType DeducedA; + if (!OriginalArg.DecomposedParam) { + // P is one of the function parameters, just look up its substituted + // type. + DeducedA = Specialization->getParamDecl(ParamIdx)->getType(); + } else { + // P is a decomposed element of a parameter corresponding to a + // braced-init-list argument. Substitute back into P to find the + // deduced A. + QualType &CacheEntry = + DeducedATypes[{ParamIdx, OriginalArg.OriginalParamType}]; + if (CacheEntry.isNull()) { + ArgumentPackSubstitutionIndexRAII PackIndex( + *this, getPackIndexForParam(*this, FunctionTemplate, SubstArgs, + ParamIdx)); + CacheEntry = + SubstType(OriginalArg.OriginalParamType, SubstArgs, + Specialization->getTypeSpecStartLoc(), + Specialization->getDeclName()); + } + DeducedA = CacheEntry; + } + if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) { Info.FirstArg = TemplateArgument(DeducedA); Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType); Info.CallArgIndex = OriginalArg.ArgIdx; - return TDK_DeducedMismatch; + return OriginalArg.DecomposedParam ? TDK_DeducedMismatchNested + : TDK_DeducedMismatch; } } } @@ -3203,7 +3261,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, - Optional<unsigned> ArgIdx, unsigned TDF); + bool DecomposedParam, unsigned ArgIdx, unsigned TDF); /// \brief Attempt template argument deduction from an initializer list /// deemed to be an argument in a function call. @@ -3211,7 +3269,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( Sema &S, TemplateParameterList *TemplateParams, QualType AdjustedParamType, InitListExpr *ILE, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, - SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned TDF) { + SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, unsigned ArgIdx, + unsigned TDF) { // C++ [temp.deduct.call]p1: (CWG 1591) // If removing references and cv-qualifiers from P gives // std::initializer_list<P0> or P0[N] for some P0 and N and the argument is @@ -3237,8 +3296,8 @@ static Sema::TemplateDeductionResult DeduceFromInitializerList( if (ElTy->isDependentType()) { for (Expr *E : ILE->inits()) { if (auto Result = DeduceTemplateArgumentsFromCallArgument( - S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, None, - TDF)) + S, TemplateParams, ElTy, E, Info, Deduced, OriginalCallArgs, true, + ArgIdx, TDF)) return Result; } } @@ -3270,7 +3329,7 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( Expr *Arg, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced, SmallVectorImpl<Sema::OriginalCallArg> &OriginalCallArgs, - Optional<unsigned> ArgIdx, unsigned TDF) { + bool DecomposedParam, unsigned ArgIdx, unsigned TDF) { QualType ArgType = Arg->getType(); QualType OrigParamType = ParamType; @@ -3283,19 +3342,15 @@ static Sema::TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( // If [...] the argument is a non-empty initializer list [...] if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) return DeduceFromInitializerList(S, TemplateParams, ParamType, ILE, Info, - Deduced, OriginalCallArgs, TDF); + Deduced, OriginalCallArgs, ArgIdx, TDF); // [...] the deduction process attempts to find template argument values // that will make the deduced A identical to A // // Keep track of the argument type and corresponding parameter index, // so we can check for compatibility between the deduced A and A. - // - // FIXME: We are supposed to perform this check for the P/A pairs we extract - // from the initializer list case too. - if (ArgIdx) - OriginalCallArgs.push_back( - Sema::OriginalCallArg(OrigParamType, *ArgIdx, ArgType)); + OriginalCallArgs.push_back( + Sema::OriginalCallArg(OrigParamType, DecomposedParam, ArgIdx, ArgType)); return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); } @@ -3388,7 +3443,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // ... with the type of the corresponding argument return DeduceTemplateArgumentsFromCallArgument( *this, TemplateParams, ParamType, Args[ArgIdx], Info, Deduced, - OriginalCallArgs, ArgIdx, /*TDF*/ 0); + OriginalCallArgs, /*Decomposed*/false, ArgIdx, /*TDF*/ 0); }; // Deduce template arguments from the function parameters. @@ -4075,7 +4130,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) { if (DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), TemplArg, InitList->getInit(i), - Info, Deduced, OriginalCallArgs, None, /*TDF*/0)) + Info, Deduced, OriginalCallArgs, /*Decomposed*/ true, + /*ArgIdx*/ 0, /*TDF*/ 0)) return DeductionFailed(); } } else { @@ -4086,7 +4142,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, if (DeduceTemplateArgumentsFromCallArgument( *this, TemplateParamsSt.get(), FuncParam, Init, Info, Deduced, - OriginalCallArgs, /*ArgIdx*/0, /*TDF*/0)) + OriginalCallArgs, /*Decomposed*/ false, /*ArgIdx*/ 0, /*TDF*/ 0)) return DeductionFailed(); } @@ -4108,8 +4164,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, // Check that the deduced argument type is compatible with the original // argument type per C++ [temp.deduct.call]p4. + QualType DeducedA = InitList ? Deduced[0].getAsType() : Result; for (const OriginalCallArg &OriginalArg : OriginalCallArgs) { - if (CheckOriginalCallArgDeduction(*this, OriginalArg, Result)) { + assert((bool)InitList == OriginalArg.DecomposedParam && + "decomposed non-init-list in auto deduction?"); + if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) { Result = QualType(); return DeductionFailed(); } |