diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 275 |
1 files changed, 160 insertions, 115 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 3c3f3d7889f..09bfcf5c463 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1314,6 +1314,114 @@ static bool isSameTemplateArg(ASTContext &Context, return false; } +/// \brief Allocate a TemplateArgumentLoc where all locations have +/// been initialized to the given location. +/// +/// \param S The semantic analysis object. +/// +/// \param The template argument we are producing template argument +/// location information for. +/// +/// \param NTTPType For a declaration template argument, the type of +/// the non-type template parameter that corresponds to this template +/// argument. +/// +/// \param Loc The source location to use for the resulting template +/// argument. +static TemplateArgumentLoc +getTrivialTemplateArgumentLoc(Sema &S, + const TemplateArgument &Arg, + QualType NTTPType, + SourceLocation Loc) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Can't get a NULL template argument here"); + break; + + case TemplateArgument::Type: + return TemplateArgumentLoc(Arg, + S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc)); + + case TemplateArgument::Declaration: { + Expr *E + = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) + .takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Integral: { + Expr *E + = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Template: + return TemplateArgumentLoc(Arg, SourceRange(), Loc); + + case TemplateArgument::Expression: + return TemplateArgumentLoc(Arg, Arg.getAsExpr()); + + case TemplateArgument::Pack: + return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); + } + + return TemplateArgumentLoc(); +} + + +/// \brief Convert the given deduced template argument and add it to the set of +/// fully-converted template arguments. +static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, + DeducedTemplateArgument Arg, + NamedDecl *Template, + QualType NTTPType, + TemplateDeductionInfo &Info, + bool InFunctionTemplate, + llvm::SmallVectorImpl<TemplateArgument> &Output) { + if (Arg.getKind() == TemplateArgument::Pack) { + // This is a template argument pack, so check each of its arguments against + // the template parameter. + llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder; + for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), + PAEnd = Arg.pack_end(); + PA != PAEnd; ++PA) { + DeducedTemplateArgument InnerArg(*PA); + InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); + if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template, + NTTPType, Info, + InFunctionTemplate, PackedArgsBuilder)) + return true; + } + + // Create the resulting argument pack. + TemplateArgument *PackedArgs = 0; + if (!PackedArgsBuilder.empty()) { + PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()]; + std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs); + } + Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size())); + return false; + } + + // Convert the deduced template argument into a template + // argument that we can check, almost as if the user had written + // the template argument explicitly. + TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType, + Info.getLocation()); + + // Check the template argument, converting it as necessary. + return S.CheckTemplateArgument(Param, ArgLoc, + Template, + Template->getLocation(), + Template->getSourceRange().getEnd(), + Output, + InFunctionTemplate + ? (Arg.wasDeducedFromArrayBound() + ? Sema::CTAK_DeducedFromArrayBound + : Sema::CTAK_Deduced) + : Sema::CTAK_Specified); +} + /// Complete template argument deduction for a class template partial /// specialization. static Sema::TemplateDeductionResult @@ -1333,12 +1441,32 @@ FinishTemplateArgumentDeduction(Sema &S, llvm::SmallVector<TemplateArgument, 4> Builder; TemplateParameterList *PartialParams = Partial->getTemplateParameters(); for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) { + NamedDecl *Param = PartialParams->getParam(I); if (Deduced[I].isNull()) { - Info.Param = makeTemplateParameter(PartialParams->getParam(I)); + Info.Param = makeTemplateParameter(Param); return Sema::TDK_Incomplete; } - Builder.push_back(Deduced[I]); + // We have deduced this argument, so it still needs to be + // checked and converted. + + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) + NTTPType = NTTP->getType(); + + if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], + Partial, NTTPType, Info, false, + Builder)) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), + Builder.size())); + return Sema::TDK_SubstitutionFailure; + } } // Form the template argument list from the deduced template arguments. @@ -1380,23 +1508,39 @@ FinishTemplateArgumentDeduction(Sema &S, llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs; if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), - InstArgs, false, ConvertedInstArgs)) + InstArgs, false, ConvertedInstArgs)) return Sema::TDK_SubstitutionFailure; - for (unsigned I = 0, E = ConvertedInstArgs.size(); I != E; ++I) { + TemplateParameterList *TemplateParams + = ClassTemplate->getTemplateParameters(); + for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { TemplateArgument InstArg = ConvertedInstArgs.data()[I]; - Decl *Param = const_cast<NamedDecl *>( - ClassTemplate->getTemplateParameters()->getParam(I)); + Decl *Param = TemplateParams->getParam(I); - if (InstArg.getKind() == TemplateArgument::Expression) { + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { // When the argument is an expression, check the expression result // against the actual template parameter to get down to the canonical // template argument. - // FIXME: Variadic templates. - Expr *InstExpr = InstArg.getAsExpr(); - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + Expr *InstExpr = 0; + if (InstArg.getKind() == TemplateArgument::Expression) + InstExpr = InstArg.getAsExpr(); + else if (InstArg.getKind() == TemplateArgument::Integral) { + ExprResult InstExprFromArg + = S.BuildExpressionFromIntegralTemplateArgument(InstArg, + Info.getLocation()); + if (InstExprFromArg.isInvalid()) { + Info.Param = makeTemplateParameter(Param); + Info.FirstArg = InstArg; + return Sema::TDK_SubstitutionFailure; + } + + InstExpr = InstExprFromArg.get(); + } + + if (InstExpr) { + // FIXME: Variadic templates. if (S.CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = Partial->getTemplateArgs()[I]; @@ -1615,109 +1759,6 @@ Sema::SubstituteExplicitTemplateArguments( return TDK_Success; } -/// \brief Allocate a TemplateArgumentLoc where all locations have -/// been initialized to the given location. -/// -/// \param S The semantic analysis object. -/// -/// \param The template argument we are producing template argument -/// location information for. -/// -/// \param NTTPType For a declaration template argument, the type of -/// the non-type template parameter that corresponds to this template -/// argument. -/// -/// \param Loc The source location to use for the resulting template -/// argument. -static TemplateArgumentLoc -getTrivialTemplateArgumentLoc(Sema &S, - const TemplateArgument &Arg, - QualType NTTPType, - SourceLocation Loc) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - llvm_unreachable("Can't get a NULL template argument here"); - break; - - case TemplateArgument::Type: - return TemplateArgumentLoc(Arg, - S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc)); - - case TemplateArgument::Declaration: { - Expr *E - = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) - .takeAs<Expr>(); - return TemplateArgumentLoc(TemplateArgument(E), E); - } - - case TemplateArgument::Integral: { - Expr *E - = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>(); - return TemplateArgumentLoc(TemplateArgument(E), E); - } - - case TemplateArgument::Template: - return TemplateArgumentLoc(Arg, SourceRange(), Loc); - - case TemplateArgument::Expression: - return TemplateArgumentLoc(Arg, Arg.getAsExpr()); - - case TemplateArgument::Pack: - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); - } - - return TemplateArgumentLoc(); -} - -/// \brief Convert the given deduced template argument and add it to the set of -/// fully-converted template arguments. -static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, - DeducedTemplateArgument Arg, - FunctionTemplateDecl *FunctionTemplate, - QualType NTTPType, - TemplateDeductionInfo &Info, - llvm::SmallVectorImpl<TemplateArgument> &Output) { - if (Arg.getKind() == TemplateArgument::Pack) { - // This is a template argument pack, so check each of its arguments against - // the template parameter. - llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder; - for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), - PAEnd = Arg.pack_end(); - PA != PAEnd; ++PA) { - DeducedTemplateArgument InnerArg(*PA); - InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); - if (ConvertDeducedTemplateArgument(S, Param, InnerArg, FunctionTemplate, - NTTPType, Info, PackedArgsBuilder)) - return true; - } - - // Create the resulting argument pack. - TemplateArgument *PackedArgs = 0; - if (!PackedArgsBuilder.empty()) { - PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()]; - std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs); - } - Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size())); - return false; - } - - // Convert the deduced template argument into a template - // argument that we can check, almost as if the user had written - // the template argument explicitly. - TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType, - Info.getLocation()); - - // Check the template argument, converting it as necessary. - return S.CheckTemplateArgument(Param, ArgLoc, - FunctionTemplate, - FunctionTemplate->getLocation(), - FunctionTemplate->getSourceRange().getEnd(), - Output, - Arg.wasDeducedFromArrayBound() - ? Sema::CTAK_DeducedFromArrayBound - : Sema::CTAK_Deduced); -} - /// \brief Finish template argument deduction for a function template, /// checking the deduced template arguments for completeness and forming /// the function template specialization. @@ -1791,7 +1832,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I], FunctionTemplate, NTTPType, Info, - Builder)) { + true, Builder)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), @@ -2953,6 +2994,10 @@ MarkUsedTemplateParameters(Sema &SemaRef, if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E)) E = Expansion->getPattern(); + // Skip through any implicit casts we added while type-checking. + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + E = ICE->getSubExpr(); + // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to // find other occurrences of template parameters. const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); |