summaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp145
1 files changed, 97 insertions, 48 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index fb7fc109d2e9..65a5633bf0d5 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -21,6 +21,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
@@ -224,6 +225,10 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Inst.NumTemplateArgs = TemplateArgs.size();
Inst.DeductionInfo = DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
+ AlreadyInstantiating =
+ !SemaRef.InstantiatingSpecializations
+ .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
+ .second;
SemaRef.InNonInstantiationSFINAEContext = false;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
if (!Inst.isInstantiationRecord())
@@ -246,13 +251,14 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
PointOfInstantiation, InstantiationRange, Entity) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
+ Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param,
+ TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef,
ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation,
- PointOfInstantiation, InstantiationRange, Template, nullptr,
- TemplateArgs) {}
+ PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param),
+ Template, TemplateArgs) {}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -262,7 +268,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
InstantiationRange, FunctionTemplate, nullptr,
- TemplateArgs, &DeductionInfo) {}
+ TemplateArgs, &DeductionInfo) {
+ assert(
+ Kind == ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution ||
+ Kind == ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+}
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -326,7 +336,8 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
- if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+ auto &Active = SemaRef.ActiveTemplateInstantiations.back();
+ if (!Active.isInstantiationRecord()) {
assert(SemaRef.NonInstantiationEntries > 0);
--SemaRef.NonInstantiationEntries;
}
@@ -344,6 +355,10 @@ void Sema::InstantiatingTemplate::Clear() {
SemaRef.ActiveTemplateInstantiationLookupModules.pop_back();
}
+ if (!AlreadyInstantiating)
+ SemaRef.InstantiatingSpecializations.erase(
+ std::make_pair(Active.Entity, Active.Kind));
+
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
@@ -442,14 +457,12 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
- TemplateDecl *Template = cast<TemplateDecl>(Active->Entity);
+ TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
Template->printName(OS);
- TemplateSpecializationType::PrintTemplateArgumentList(OS,
- Active->TemplateArgs,
- Active->NumTemplateArgs,
- getPrintingPolicy());
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Active->template_arguments(), getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_arg_instantiation_here)
<< OS.str()
@@ -500,10 +513,8 @@ void Sema::PrintInstantiationStack() {
SmallVector<char, 128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
FD->printName(OS);
- TemplateSpecializationType::PrintTemplateArgumentList(OS,
- Active->TemplateArgs,
- Active->NumTemplateArgs,
- getPrintingPolicy());
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, Active->template_arguments(), getPrintingPolicy());
Diags.Report(Active->PointOfInstantiation,
diag::note_default_function_arg_instantiation_here)
<< OS.str()
@@ -729,6 +740,11 @@ namespace {
}
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+
+ // We recreated a local declaration, but not by instantiating it. There
+ // may be pending dependent diagnostics to produce.
+ if (auto *DC = dyn_cast<DeclContext>(Old))
+ SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
}
/// \brief Transform the definition of the given declaration by
@@ -1512,7 +1528,7 @@ QualType Sema::SubstType(QualType T,
}
static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
- if (T->getType()->isInstantiationDependentType() ||
+ if (T->getType()->isInstantiationDependentType() ||
T->getType()->isVariablyModifiedType())
return true;
@@ -1521,23 +1537,13 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
return false;
FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
- for (unsigned I = 0, E = FP.getNumParams(); I != E; ++I) {
- ParmVarDecl *P = FP.getParam(I);
-
+ for (ParmVarDecl *P : FP.getParams()) {
// This must be synthesized from a typedef.
if (!P) continue;
- // The parameter's type as written might be dependent even if the
- // decayed type was not dependent.
- if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo())
- if (TSInfo->getType()->isInstantiationDependentType())
- return true;
-
- // TODO: currently we always rebuild expressions. When we
- // properly get lazier about this, we should use the same
- // logic to avoid rebuilding prototypes here.
- if (P->hasDefaultArg())
- return true;
+ // If there are any parameters, a new TypeSourceInfo that refers to the
+ // instantiated parameters must be built.
+ return true;
}
return false;
@@ -1556,7 +1562,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
-
+
if (!NeedsInstantiationAsFunctionType(T))
return T;
@@ -1718,20 +1724,21 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
/// \brief Substitute the given template arguments into the given set of
/// parameters, producing the set of parameter types that would be generated
/// from such a substitution.
-bool Sema::SubstParmTypes(SourceLocation Loc,
- ParmVarDecl **Params, unsigned NumParams,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SmallVectorImpl<QualType> &ParamTypes,
- SmallVectorImpl<ParmVarDecl *> *OutParams) {
+bool Sema::SubstParmTypes(
+ SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
+ const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<QualType> &ParamTypes,
+ SmallVectorImpl<ParmVarDecl *> *OutParams,
+ ExtParameterInfoBuilder &ParamInfos) {
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
- return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams,
- nullptr, ParamTypes,
- OutParams);
+ return Instantiator.TransformFunctionTypeParams(
+ Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
}
/// \brief Perform substitution on the base class specifiers of the
@@ -1861,8 +1868,19 @@ static bool DiagnoseUninstantiableTemplate(Sema &S,
TagDecl *PatternDef,
TemplateSpecializationKind TSK,
bool Complain = true) {
- if (PatternDef && !PatternDef->isBeingDefined())
+ if (PatternDef && !PatternDef->isBeingDefined()) {
+ NamedDecl *SuggestedDef = nullptr;
+ if (!S.hasVisibleDefinition(PatternDef, &SuggestedDef,
+ /*OnlyNeedComplete*/false)) {
+ // If we're allowed to diagnose this and recover, do so.
+ bool Recover = Complain && !S.isSFINAEContext();
+ if (Complain)
+ S.diagnoseMissingImport(PointOfInstantiation, SuggestedDef,
+ Sema::MissingImportKind::Definition, Recover);
+ return !Recover;
+ }
return false;
+ }
if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
// Say nothing
@@ -1946,6 +1964,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
+ PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ "instantiating class definition");
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
@@ -1959,6 +1980,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
LocalInstantiationScope Scope(*this, MergeWithParentScope);
+ // All dllexported classes created during instantiation should be fully
+ // emitted after instantiation completes. We may not be ready to emit any
+ // delayed classes already on the stack, so save them away and put them back
+ // later.
+ decltype(DelayedDllExportClasses) ExportedClasses;
+ std::swap(ExportedClasses, DelayedDllExportClasses);
+
// Pull attributes from the pattern onto the instantiation.
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
@@ -2044,6 +2072,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// default arg exprs for default constructors if necessary now.
ActOnFinishCXXNonNestedClass(Instantiation);
+ // Put back the delayed exported classes that we moved out of the way.
+ std::swap(ExportedClasses, DelayedDllExportClasses);
+
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
@@ -2074,7 +2105,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (TSK == TSK_ImplicitInstantiation) {
Instantiation->setLocation(Pattern->getLocation());
Instantiation->setLocStart(Pattern->getInnerLocStart());
- Instantiation->setRBraceLoc(Pattern->getRBraceLoc());
+ Instantiation->setBraceRange(Pattern->getBraceRange());
}
if (!Instantiation->isInvalidDecl()) {
@@ -2159,6 +2190,10 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ if (Inst.isAlreadyInstantiating())
+ return false;
+ PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ "instantiating enum definition");
// The instantiation is visible here, even if it was first declared in an
// unimported module.
@@ -2231,6 +2266,14 @@ bool Sema::InstantiateInClassInitializer(
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
if (Inst.isInvalid())
return true;
+ if (Inst.isAlreadyInstantiating()) {
+ // Error out if we hit an instantiation cycle for this initializer.
+ Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle)
+ << Instantiation;
+ return true;
+ }
+ PrettyDeclStackTraceEntry CrashInfo(*this, Instantiation, SourceLocation(),
+ "instantiating default member init");
// Enter the scope of this instantiation. We don't use PushDeclContext because
// we don't have a scope.
@@ -2302,8 +2345,9 @@ bool Sema::InstantiateClassTemplateSpecialization(
Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
- FailedCandidates.addCandidate()
- .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
+ FailedCandidates.addCandidate().set(
+ DeclAccessPair::make(Template, AS_public), Partial,
+ MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
@@ -2495,8 +2539,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
// specialization and is only an explicit instantiation definition
// of members whose definition is visible at the point of
// instantiation.
- if (!Var->getInstantiatedFromStaticDataMember()
- ->getOutOfLineDefinition())
+ if (!Var->getInstantiatedFromStaticDataMember()->getDefinition())
continue;
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
@@ -2522,6 +2565,13 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
== TSK_ExplicitSpecialization)
continue;
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ TSK == TSK_ExplicitInstantiationDeclaration) {
+ // In MSVC mode, explicit instantiation decl of the outer class doesn't
+ // affect the inner class.
+ continue;
+ }
+
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
Record,
MSInfo->getTemplateSpecializationKind(),
@@ -2583,7 +2633,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Enum->getDefinition())
continue;
- EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum();
+ EnumDecl *Pattern = Enum->getTemplateInstantiationPattern();
assert(Pattern && "Missing instantiated-from-template information");
if (TSK == TSK_ExplicitInstantiationDefinition) {
@@ -2603,8 +2653,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
Instantiation->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
- assert(Lookup.size() == 1);
- FieldDecl *Pattern = cast<FieldDecl>(Lookup[0]);
+ FieldDecl *Pattern = cast<FieldDecl>(Lookup.front());
InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
TemplateArgs);
}