aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/Sema.h31
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp6
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp79
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp22
4 files changed, 107 insertions, 31 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 338221e4d4..a6c34e8885 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2359,7 +2359,7 @@ public:
/// \brief A template instantiation that is currently in progress.
struct ActiveTemplateInstantiation {
/// \brief The kind of template instantiation we are performing
- enum {
+ enum InstantiationKind {
/// We are instantiating a template declaration. The entity is
/// the declaration we're instantiating (e.g., a CXXRecordDecl).
TemplateInstantiation,
@@ -2371,13 +2371,16 @@ public:
/// FIXME: Use a TemplateArgumentList
DefaultTemplateArgumentInstantiation,
- /// We are performing template argument deduction for a class
- /// template partial specialization. The Entity is the class
- /// template partial specialization, and
- /// TemplateArgs/NumTemplateArgs provides the deduced template
- /// arguments.
- /// FIXME: Use a TemplateArgumentList
- PartialSpecDeductionInstantiation
+ /// We are substituting explicit template arguments provided for
+ /// a function template. The entity is a FunctionTemplateDecl.
+ ExplicitTemplateArgumentSubstitution,
+
+ /// We are substituting template argument determined as part of
+ /// template argument deduction for either a class template
+ /// partial specialization or a function template. The
+ /// Entity is either a ClassTemplatePartialSpecializationDecl or
+ /// a FunctionTemplateDecl.
+ DeducedTemplateArgumentSubstitution
} Kind;
/// \brief The point of instantiation within the source code.
@@ -2411,7 +2414,8 @@ public:
return true;
case DefaultTemplateArgumentInstantiation:
- case PartialSpecDeductionInstantiation:
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
return X.TemplateArgs == Y.TemplateArgs;
}
@@ -2468,6 +2472,15 @@ public:
unsigned NumTemplateArgs,
SourceRange InstantiationRange = SourceRange());
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceRange InstantiationRange = SourceRange());
+
/// \brief Note that we are instantiating as part of template
/// argument deduction for a class template partial
/// specialization.
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index ae0e704065..5a0578f6bc 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -939,7 +939,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// explicitly-specified template arguments against this function template,
// and then substitute them into the function parameter types.
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, Deduced.data(), Deduced.size());
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
if (Inst)
return TDK_InstantiationDepth;
@@ -1106,7 +1107,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// Enter a new template instantiation context while we instantiate the
// actual function declaration.
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
- FunctionTemplate, Deduced.data(), Deduced.size());
+ FunctionTemplate, Deduced.data(), Deduced.size(),
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
if (Inst)
return TDK_InstantiationDepth;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 3bc1cf9504..6c2dc77b4c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -100,6 +100,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceRange InstantiationRange)
+: SemaRef(SemaRef) {
+
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = Kind;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ Invalid = false;
+ }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
@@ -111,7 +135,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
if (!Invalid) {
ActiveTemplateInstantiation Inst;
Inst.Kind
- = ActiveTemplateInstantiation::PartialSpecDeductionInstantiation;
+ = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
Inst.TemplateArgs = TemplateArgs;
@@ -148,6 +172,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
/// \brief Prints the current instantiation stack through a series of
/// notes.
void Sema::PrintInstantiationStack() {
+ // FIXME: In all of these cases, we need to show the template arguments
for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
@@ -183,7 +208,7 @@ void Sema::PrintInstantiationStack() {
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
std::string TemplateArgsStr
= TemplateSpecializationType::PrintTemplateArgumentList(
- Active->TemplateArgs,
+ Active->TemplateArgs,
Active->NumTemplateArgs,
Context.PrintingPolicy);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
@@ -193,18 +218,31 @@ void Sema::PrintInstantiationStack() {
break;
}
- case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: {
- ClassTemplatePartialSpecializationDecl *PartialSpec
- = cast<ClassTemplatePartialSpecializationDecl>((Decl *)Active->Entity);
- // FIXME: The active template instantiation's template arguments
- // are interesting, too. We should add something like [with T =
- // foo, U = bar, etc.] to the string.
+ case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
+ FunctionTemplateDecl *FnTmpl
+ = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
- diag::note_partial_spec_deduct_instantiation_here)
- << Context.getTypeDeclType(PartialSpec)
- << Active->InstantiationRange;
+ diag::note_explicit_template_arg_substitution_here)
+ << FnTmpl << Active->InstantiationRange;
break;
}
+
+ case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+ (Decl *)Active->Entity)) {
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_partial_spec_deduct_instantiation_here)
+ << Context.getTypeDeclType(PartialSpec)
+ << Active->InstantiationRange;
+ } else {
+ FunctionTemplateDecl *FnTmpl
+ = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_function_template_deduction_instantiation_here)
+ << FnTmpl << Active->InstantiationRange;
+ }
+ break;
}
}
@@ -219,19 +257,20 @@ bool Sema::isSFINAEContext() const {
++Active) {
switch(Active->Kind) {
- case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation:
- // We're in a template argument deduction context, so SFINAE
- // applies.
- return true;
-
+ case ActiveTemplateInstantiation::TemplateInstantiation:
+ // This is a template instantiation, so there is no SFINAE.
+ return false;
+
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
// A default template argument instantiation may or may not be a
// SFINAE context; look further up the stack.
break;
-
- case ActiveTemplateInstantiation::TemplateInstantiation:
- // This is a template instantiation, so there is no SFINAE.
- return false;
+
+ case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
+ case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+ // We're either substitution explicitly-specified template arguments
+ // or deduced template arguments, so SFINAE applies.
+ return true;
}
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 769e0d222a..f597199920 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -628,6 +628,28 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
FunctionDecl *Tmpl) {
if (Tmpl->isDeleted())
New->setDeleted();
+
+ // If we are performing substituting explicitly-specified template arguments
+ // or deduced template arguments into a function template and we reach this
+ // point, we are now past the point where SFINAE applies and have committed
+ // to keeping the new function template specialization. We therefore
+ // convert the active template instantiation for the function template
+ // into a template instantiation for this specific function template
+ // specialization, which is not a SFINAE context, so that we diagnose any
+ // further errors in the declaration itself.
+ typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+ ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+ if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+ ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+ if (FunctionTemplateDecl *FunTmpl
+ = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+ assert(FunTmpl->getTemplatedDecl() == Tmpl &&
+ "Deduction from the wrong function template?");
+ ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+ ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+ }
+ }
+
return false;
}