diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-29 06:21:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-29 06:21:43 +0000 |
commit | 31dce8f606c5ff4a51db67caa24ac3312ccea3f3 (patch) | |
tree | 5fa54daff13d6982e3d52b10a00f01a35f0804b2 /lib/Sema/SemaTemplateDeduction.cpp | |
parent | fc39dc4c7886723310419b1869cf651ca55b7af4 (diff) |
For template argument deduction from class template partial
specializations, separate out the deduction part from the checking and
substitution of the deduced arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102600 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 124 |
1 files changed, 73 insertions, 51 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index e7a12d6b70..031209235c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -961,34 +961,18 @@ static TemplateParameter makeTemplateParameter(Decl *D) { return TemplateParameter(cast<TemplateTemplateParmDecl>(D)); } -/// \brief Perform template argument deduction to determine whether -/// the given template arguments match the given class template -/// partial specialization per C++ [temp.class.spec.match]. -Sema::TemplateDeductionResult -Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, - TemplateDeductionInfo &Info) { - // C++ [temp.class.spec.match]p2: - // A partial specialization matches a given actual template - // argument list if the template arguments of the partial - // specialization can be deduced from the actual template argument - // list (14.8.2). - SFINAETrap Trap(*this); - llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; - Deduced.resize(Partial->getTemplateParameters()->size()); - if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, - Partial->getTemplateParameters(), - Partial->getTemplateArgs(), - TemplateArgs, Info, Deduced)) - return Result; - - InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, - Deduced.data(), Deduced.size()); - if (Inst) - return TDK_InstantiationDepth; - - ContextRAII SavedContext(*this, Partial); +/// Complete template argument deduction for a class template partial +/// specialization. +static Sema::TemplateDeductionResult +FinishTemplateArgumentDeduction(Sema &S, + ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + Sema::TemplateDeductionInfo &Info) { + // Trap errors. + Sema::SFINAETrap Trap(S); + + Sema::ContextRAII SavedContext(S, Partial); // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor @@ -998,18 +982,19 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { if (Deduced[I].isNull()) { Decl *Param - = const_cast<NamedDecl *>( + = const_cast<NamedDecl *>( Partial->getTemplateParameters()->getParam(I)); Info.Param = makeTemplateParameter(Param); - return TDK_Incomplete; + return Sema::TDK_Incomplete; } - + Builder.Append(Deduced[I]); } - + // Form the template argument list from the deduced template arguments. TemplateArgumentList *DeducedArgumentList - = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); + = new (S.Context) TemplateArgumentList(S.Context, Builder, + /*TakeArgs=*/true); Info.reset(DeducedArgumentList); // Substitute the deduced template arguments into the template @@ -1019,7 +1004,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // to the class template. // FIXME: Do we have to correct the types of deduced non-type template // arguments (in particular, integral non-type template arguments?). - Sema::LocalInstantiationScope InstScope(*this); + Sema::LocalInstantiationScope InstScope(S); ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); const TemplateArgumentLoc *PartialTemplateArgs = Partial->getTemplateArgsAsWritten(); @@ -1032,11 +1017,11 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, Decl *Param = const_cast<NamedDecl *>( ClassTemplate->getTemplateParameters()->getParam(I)); TemplateArgumentLoc InstArg; - if (Subst(PartialTemplateArgs[I], InstArg, - MultiLevelTemplateArgumentList(*DeducedArgumentList))) { + if (S.Subst(PartialTemplateArgs[I], InstArg, + MultiLevelTemplateArgumentList(*DeducedArgumentList))) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = PartialTemplateArgs[I].getArgument(); - return TDK_SubstitutionFailure; + return Sema::TDK_SubstitutionFailure; } InstArgs.addArgument(InstArg); } @@ -1044,10 +1029,10 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, TemplateArgumentListBuilder ConvertedInstArgs( ClassTemplate->getTemplateParameters(), N); - if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), + if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), InstArgs, false, ConvertedInstArgs)) { // FIXME: fail with more useful information? - return TDK_SubstitutionFailure; + return Sema::TDK_SubstitutionFailure; } for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) { @@ -1063,26 +1048,60 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, Expr *InstExpr = InstArg.getAsExpr(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) { + if (S.CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = Partial->getTemplateArgs()[I]; - return TDK_SubstitutionFailure; + return Sema::TDK_SubstitutionFailure; } } } - if (!isSameTemplateArg(Context, TemplateArgs[I], InstArg)) { + if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) { Info.Param = makeTemplateParameter(Param); Info.FirstArg = TemplateArgs[I]; Info.SecondArg = InstArg; - return TDK_NonDeducedMismatch; + return Sema::TDK_NonDeducedMismatch; } } if (Trap.hasErrorOccurred()) - return TDK_SubstitutionFailure; + return Sema::TDK_SubstitutionFailure; - return TDK_Success; + return Sema::TDK_Success; +} + +/// \brief Perform template argument deduction to determine whether +/// the given template arguments match the given class template +/// partial specialization per C++ [temp.class.spec.match]. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + TemplateDeductionInfo &Info) { + // C++ [temp.class.spec.match]p2: + // A partial specialization matches a given actual template + // argument list if the template arguments of the partial + // specialization can be deduced from the actual template argument + // list (14.8.2). + SFINAETrap Trap(*this); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + Deduced.resize(Partial->getTemplateParameters()->size()); + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, + Partial->getTemplateParameters(), + Partial->getTemplateArgs(), + TemplateArgs, Info, Deduced)) + return Result; + + InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, + Deduced.data(), Deduced.size()); + if (Inst) + return TDK_InstantiationDepth; + + if (Trap.hasErrorOccurred()) + return Sema::TDK_SubstitutionFailure; + + return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs, + Deduced, Info); } /// \brief Determine whether the given type T is a simple-template-id type. @@ -2341,12 +2360,15 @@ Sema::getMoreSpecializedPartialSpecialization( // whose type is a class template specialization with the template // arguments of the second partial specialization. // - // Rather than synthesize function templates, we merely perform the - // equivalent partial ordering by performing deduction directly on the - // template arguments of the class template partial specializations. This - // computation is slightly simpler than the general problem of function - // template partial ordering, because class template partial specializations - // are more constrained. We know that every template parameter is deduc + // Rather than synthesize function templates, we merely perform the + // equivalent partial ordering by performing deduction directly on + // the template arguments of the class template partial + // specializations. This computation is slightly simpler than the + // general problem of function template partial ordering, because + // class template partial specializations are more constrained. We + // know that every template parameter is deducible from the class + // template partial specialization's template arguments, for + // example. llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; Sema::TemplateDeductionInfo Info(Context, Loc); |