summaryrefslogtreecommitdiffstats
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.cpp305
1 files changed, 246 insertions, 59 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 301bf6a..4740145 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -163,8 +163,8 @@ bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
case DefaultTemplateArgumentChecking:
return false;
}
-
- return true;
+
+ llvm_unreachable("Invalid InstantiationKind!");
}
Sema::InstantiatingTemplate::
@@ -404,15 +404,15 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
SemaRef.ActiveTemplateInstantiations.size());
if ((SemaRef.ActiveTemplateInstantiations.size() -
SemaRef.NonInstantiationEntries)
- <= SemaRef.getLangOptions().InstantiationDepth)
+ <= SemaRef.getLangOpts().InstantiationDepth)
return false;
SemaRef.Diag(PointOfInstantiation,
diag::err_template_recursion_depth_exceeded)
- << SemaRef.getLangOptions().InstantiationDepth
+ << SemaRef.getLangOpts().InstantiationDepth
<< InstantiationRange;
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
- << SemaRef.getLangOptions().InstantiationDepth;
+ << SemaRef.getLangOpts().InstantiationDepth;
return true;
}
@@ -469,6 +469,11 @@ void Sema::PrintInstantiationStack() {
diag::note_template_static_data_member_def_here)
<< VD
<< Active->InstantiationRange;
+ } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_enum_def_here)
+ << ED
+ << Active->InstantiationRange;
} else {
Diags.Report(Active->PointOfInstantiation,
diag::note_template_type_alias_instantiation_here)
@@ -732,6 +737,14 @@ namespace {
/// this declaration.
Decl *TransformDecl(SourceLocation Loc, Decl *D);
+ void transformAttrs(Decl *Old, Decl *New) {
+ SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+ }
+
+ void transformedLocalDecl(Decl *Old, Decl *New) {
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+ }
+
/// \brief Transform the definition of the given declaration by
/// instantiating it.
Decl *TransformDefinition(SourceLocation Loc, Decl *D);
@@ -778,7 +791,8 @@ namespace {
FunctionProtoTypeLoc TL);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions);
+ llvm::Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack);
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
@@ -1099,15 +1113,21 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
type = argExpr->getType();
} else if (arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(arg.getAsDecl());
-
- // Find the instantiation of the template argument. This is
- // required for nested templates.
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
- if (!VD)
- return ExprError();
-
+ ValueDecl *VD;
+ if (Decl *D = arg.getAsDecl()) {
+ VD = cast<ValueDecl>(D);
+
+ // Find the instantiation of the template argument. This is
+ // required for nested templates.
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
+ if (!VD)
+ return ExprError();
+ } else {
+ // Propagate NULL template argument.
+ VD = 0;
+ }
+
// Derive the type we want the substituted decl to have. This had
// better be non-dependent, or these checks will have serious problems.
if (parm->isExpandedParameterPack()) {
@@ -1194,9 +1214,10 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions) {
+ llvm::Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack) {
return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
- NumExpansions);
+ NumExpansions, ExpectParameterPack);
}
QualType
@@ -1450,7 +1471,8 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,
- llvm::Optional<unsigned> NumExpansions) {
+ llvm::Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack) {
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
TypeSourceInfo *NewDI = 0;
@@ -1471,7 +1493,16 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
// Therefore, make its type a pack expansion type.
NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
NumExpansions);
- }
+ } else if (ExpectParameterPack) {
+ // We expected to get a parameter pack but didn't (because the type
+ // itself is not a pack expansion type), so complain. This can occur when
+ // the substitution goes through an alias template that "loses" the
+ // pack expansion.
+ Diag(OldParm->getLocation(),
+ diag::err_function_parameter_pack_without_parameter_packs)
+ << NewDI->getType();
+ return 0;
+ }
} else {
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
OldParm->getDeclName());
@@ -1506,11 +1537,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewParm->setUninstantiatedDefaultArg(Arg);
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
-
- // FIXME: When OldParm is a parameter pack and NewParm is not a parameter
- // pack, we actually have a set of instantiated locations. Maintain this set!
+
if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
- // Add the new parameter to
+ // Add the new parameter to the instantiated parameter pack.
CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
} else {
// Introduce an Old -> New mapping
@@ -1654,6 +1683,59 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
return Invalid;
}
+// Defined via #include from SemaTemplateInstantiateDecl.cpp
+namespace clang {
+ namespace sema {
+ Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ }
+}
+
+/// Determine whether we would be unable to instantiate this template (because
+/// it either has no definition, or is in the process of being instantiated).
+static bool DiagnoseUninstantiableTemplate(Sema &S,
+ SourceLocation PointOfInstantiation,
+ TagDecl *Instantiation,
+ bool InstantiatedFromMember,
+ TagDecl *Pattern,
+ TagDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true) {
+ if (PatternDef && !PatternDef->isBeingDefined())
+ return false;
+
+ if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
+ // Say nothing
+ } else if (PatternDef) {
+ assert(PatternDef->isBeingDefined());
+ S.Diag(PointOfInstantiation,
+ diag::err_template_instantiate_within_definition)
+ << (TSK != TSK_ImplicitInstantiation)
+ << S.Context.getTypeDeclType(Instantiation);
+ // Not much point in noting the template declaration here, since
+ // we're lexically inside it.
+ Instantiation->setInvalidDecl();
+ } else if (InstantiatedFromMember) {
+ S.Diag(PointOfInstantiation,
+ diag::err_implicit_instantiate_member_undefined)
+ << S.Context.getTypeDeclType(Instantiation);
+ S.Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+ } else {
+ S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
+ << (TSK != TSK_ImplicitInstantiation)
+ << S.Context.getTypeDeclType(Instantiation);
+ S.Diag(Pattern->getLocation(), diag::note_template_decl_here);
+ }
+
+ // In general, Instantiation isn't marked invalid to get more than one
+ // error for multiple undefined instantiations. But the code that does
+ // explicit declaration -> explicit definition conversion can't handle
+ // invalid declarations, so mark as invalid in that case.
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ Instantiation->setInvalidDecl();
+ return true;
+}
+
/// \brief Instantiate the definition of a class from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
@@ -1686,31 +1768,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
- if (!PatternDef || PatternDef->isBeingDefined()) {
- if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
- // Say nothing
- } else if (PatternDef) {
- assert(PatternDef->isBeingDefined());
- Diag(PointOfInstantiation,
- diag::err_template_instantiate_within_definition)
- << (TSK != TSK_ImplicitInstantiation)
- << Context.getTypeDeclType(Instantiation);
- // Not much point in noting the template declaration here, since
- // we're lexically inside it.
- Instantiation->setInvalidDecl();
- } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
- Diag(PointOfInstantiation,
- diag::err_implicit_instantiate_member_undefined)
- << Context.getTypeDeclType(Instantiation);
- Diag(Pattern->getLocation(), diag::note_member_of_template_here);
- } else {
- Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
- << (TSK != TSK_ImplicitInstantiation)
- << Context.getTypeDeclType(Instantiation);
- Diag(Pattern->getLocation(), diag::note_template_decl_here);
- }
+ if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+ Instantiation->getInstantiatedFromMemberClass(),
+ Pattern, PatternDef, TSK, Complain))
return true;
- }
Pattern = PatternDef;
// \brief Record the point of instantiation.
@@ -1719,7 +1780,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
} else if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
+ = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
}
@@ -1756,6 +1817,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
SmallVector<Decl*, 4> Fields;
SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
FieldsWithMemberInitializers;
+ // Delay instantiation of late parsed attributes.
+ LateInstantiatedAttrVec LateAttrs;
+ Instantiator.enableLateAttributeInstantiation(&LateAttrs);
+
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
MemberEnd = Pattern->decls_end();
Member != MemberEnd; ++Member) {
@@ -1784,7 +1849,21 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (OldField->getInClassInitializer())
FieldsWithMemberInitializers.push_back(std::make_pair(OldField,
Field));
- } else if (NewMember->isInvalidDecl())
+ } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
+ // C++11 [temp.inst]p1: The implicit instantiation of a class template
+ // specialization causes the implicit instantiation of the definitions
+ // of unscoped member enumerations.
+ // Record a point of instantiation for this implicit instantiation.
+ if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
+ Enum->isCompleteDefinition()) {
+ MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
+ assert(MSInfo && "no spec info for member enum specialization");
+ MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+ }
+
+ if (NewMember->isInvalidDecl())
Invalid = true;
} else {
// FIXME: Eventually, a NULL return will mean that one of the
@@ -1804,22 +1883,42 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
Expr *OldInit = OldField->getInClassInitializer();
- SourceLocation LParenLoc, RParenLoc;
- ASTOwningVector<Expr*> NewArgs(*this);
- if (InstantiateInitializer(OldInit, TemplateArgs, LParenLoc, NewArgs,
- RParenLoc))
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ if (NewInit.isInvalid())
NewField->setInvalidDecl();
else {
- assert(NewArgs.size() == 1 && "wrong number of in-class initializers");
- ActOnCXXInClassMemberInitializer(NewField, LParenLoc, NewArgs[0]);
+ Expr *Init = NewInit.take();
+ assert(Init && "no-argument initializer in class");
+ assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+ ActOnCXXInClassMemberInitializer(NewField,
+ Init->getSourceRange().getBegin(), Init);
}
}
+ // Instantiate late parsed attributes, and attach them to their decls.
+ // See Sema::InstantiateAttrs
+ for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
+ E = LateAttrs.end(); I != E; ++I) {
+ assert(CurrentInstantiationScope == Instantiator.getStartingScope());
+ CurrentInstantiationScope = I->Scope;
+ Attr *NewAttr =
+ instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
+ I->NewDecl->addAttr(NewAttr);
+ LocalInstantiationScope::deleteScopes(I->Scope,
+ Instantiator.getStartingScope());
+ }
+ Instantiator.disableLateAttributeInstantiation();
+ LateAttrs.clear();
+
if (!FieldsWithMemberInitializers.empty())
ActOnFinishDelayedMemberInitializers(Instantiation);
- if (TSK == TSK_ImplicitInstantiation)
+ if (TSK == TSK_ImplicitInstantiation) {
+ Instantiation->setLocation(Pattern->getLocation());
+ Instantiation->setLocStart(Pattern->getInnerLocStart());
Instantiation->setRBraceLoc(Pattern->getRBraceLoc());
+ }
if (Instantiation->isInvalidDecl())
Invalid = true;
@@ -1854,6 +1953,63 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return Invalid;
}
+/// \brief Instantiate the definition of an enum from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be a member enumeration of a class
+/// temploid specialization, or a local enumeration within a
+/// function temploid specialization.
+/// \param Pattern The templated declaration from which the instantiation
+/// occurs.
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+/// \param TSK The kind of implicit or explicit instantiation to perform.
+///
+/// \return \c true if an error occurred, \c false otherwise.
+bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
+ EnumDecl *Instantiation, EnumDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK) {
+ EnumDecl *PatternDef = Pattern->getDefinition();
+ if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+ Instantiation->getInstantiatedFromMemberEnum(),
+ Pattern, PatternDef, TSK,/*Complain*/true))
+ return true;
+ Pattern = PatternDef;
+
+ // Record the point of instantiation.
+ if (MemberSpecializationInfo *MSInfo
+ = Instantiation->getMemberSpecializationInfo()) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
+ if (Inst)
+ return true;
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ ContextRAII SavedContext(*this, Instantiation);
+ EnterExpressionEvaluationContext EvalContext(*this,
+ Sema::PotentiallyEvaluated);
+
+ LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true);
+
+ // Pull attributes from the pattern onto the instantiation.
+ InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
+
+ TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
+ Instantiator.InstantiateEnumDefinition(Instantiation, Pattern);
+
+ // Exit the scope of this instantiation.
+ SavedContext.pop();
+
+ return Instantiation->isInvalidDecl();
+}
+
namespace {
/// \brief A partial specialization whose template arguments have matched
/// a given template-id.
@@ -1886,7 +2042,8 @@ Sema::InstantiateClassTemplateSpecialization(
// If this is an explicit instantiation definition, mark the
// vtable as used.
- if (TSK == TSK_ExplicitInstantiationDefinition)
+ if (TSK == TSK_ExplicitInstantiationDefinition &&
+ !ClassTemplateSpec->isInvalidDecl())
MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true);
return false;
@@ -2120,7 +2277,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
// Always skip the injected-class-name, along with any
// redeclarations of nested classes, since both would cause us
// to try to instantiate the members of a class twice.
- if (Record->isInjectedClassName() || Record->getPreviousDeclaration())
+ if (Record->isInjectedClassName() || Record->getPreviousDecl())
continue;
MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
@@ -2173,6 +2330,36 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
if (Pattern)
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
TSK);
+ } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*D)) {
+ MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+
+ if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ExplicitSpecialization)
+ continue;
+
+ if (CheckSpecializationInstantiationRedecl(
+ PointOfInstantiation, TSK, Enum,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(), SuppressNew) ||
+ SuppressNew)
+ continue;
+
+ if (Enum->getDefinition())
+ continue;
+
+ EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum();
+ assert(Pattern && "Missing instantiated-from-template information");
+
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ if (!Pattern->getDefinition())
+ continue;
+
+ InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK);
+ } else {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
}
}
}
@@ -2287,7 +2474,7 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
// If this is a tag declaration, it's possible that we need to look for
// a previous declaration.
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
- CheckD = Tag->getPreviousDeclaration();
+ CheckD = Tag->getPreviousDecl();
else
CheckD = 0;
} while (CheckD);
OpenPOWER on IntegriCloud