summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateDeduction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp160
1 files changed, 103 insertions, 57 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index d61a767..2bb97eb 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -638,7 +638,8 @@ DeduceTemplateArguments(Sema &S,
case Type::InjectedClassName: {
// Treat a template's injected-class-name as if the template
// specialization type had been used.
- Param = cast<InjectedClassNameType>(Param)->getUnderlyingType();
+ Param = cast<InjectedClassNameType>(Param)
+ ->getInjectedSpecializationType();
assert(isa<TemplateSpecializationType>(Param) &&
"injected class name is not a template specialization type");
// fall through
@@ -960,32 +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;
+/// 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
@@ -995,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
@@ -1016,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();
@@ -1029,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);
}
@@ -1041,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) {
@@ -1060,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.
@@ -1162,6 +1184,8 @@ Sema::SubstituteExplicitTemplateArguments(
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
if (CheckTemplateArgumentList(FunctionTemplate,
SourceLocation(),
ExplicitTemplateArgs,
@@ -1310,6 +1334,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
@@ -1416,9 +1442,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// Substitute the deduced template arguments into the function template
// declaration to produce the function template specialization.
+ DeclContext *Owner = FunctionTemplate->getDeclContext();
+ if (FunctionTemplate->getFriendObjectKind())
+ Owner = FunctionTemplate->getLexicalDeclContext();
Specialization = cast_or_null<FunctionDecl>(
- SubstDecl(FunctionTemplate->getTemplatedDecl(),
- FunctionTemplate->getDeclContext(),
+ SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
MultiLevelTemplateArgumentList(*DeducedArgumentList)));
if (!Specialization)
return TDK_SubstitutionFailure;
@@ -2332,35 +2360,49 @@ 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);
+
+ QualType PT1 = PS1->getInjectedSpecializationType();
+ QualType PT2 = PS2->getInjectedSpecializationType();
// Determine whether PS1 is at least as specialized as PS2
Deduced.resize(PS2->getTemplateParameters()->size());
bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS2->getTemplateParameters(),
- Context.getTypeDeclType(PS2),
- Context.getTypeDeclType(PS1),
+ PT2,
+ PT1,
Info,
Deduced,
0);
-
+ if (Better1)
+ Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
+ PS1->getTemplateArgs(),
+ Deduced, Info);
+
// Determine whether PS2 is at least as specialized as PS1
Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS1->getTemplateParameters(),
- Context.getTypeDeclType(PS1),
- Context.getTypeDeclType(PS2),
+ PT1,
+ PT2,
Info,
Deduced,
0);
+ if (Better2)
+ Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
+ PS2->getTemplateArgs(),
+ Deduced, Info);
if (Better1 == Better2)
return 0;
@@ -2537,6 +2579,10 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
break;
}
+ case Type::InjectedClassName:
+ T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
+ // fall through
+
case Type::TemplateSpecialization: {
const TemplateSpecializationType *Spec
= cast<TemplateSpecializationType>(T);
OpenPOWER on IntegriCloud