summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commit741c13ecc20fb35b836ad690aeecd402f002d654 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Sema/SemaTemplateInstantiate.cpp
parentb3a51061b1b9c4add078237850649f7c9efb13ab (diff)
downloadFreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.zip
FreeBSD-src-741c13ecc20fb35b836ad690aeecd402f002d654.tar.gz
Update clang to r89205.
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp294
1 files changed, 251 insertions, 43 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dfe37d8..58fe59e 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -28,11 +28,20 @@ using namespace clang;
/// \brief Retrieve the template argument list(s) that should be used to
/// instantiate the definition of the given declaration.
+///
+/// \param D the declaration for which we are computing template instantiation
+/// arguments.
+///
+/// \param Innermost if non-NULL, the innermost template argument list.
MultiLevelTemplateArgumentList
-Sema::getTemplateInstantiationArgs(NamedDecl *D) {
+Sema::getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost) {
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
+ if (Innermost)
+ Result.addOuterTemplateArguments(Innermost);
+
DeclContext *Ctx = dyn_cast<DeclContext>(D);
if (!Ctx)
Ctx = D->getDeclContext();
@@ -87,6 +96,23 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
return Result;
}
+bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
+ switch (Kind) {
+ case TemplateInstantiation:
+ case DefaultTemplateArgumentInstantiation:
+ case DefaultFunctionArgumentInstantiation:
+ return true;
+
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ return false;
+ }
+
+ return true;
+}
+
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
@@ -104,7 +130,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Inst.NumTemplateArgs = 0;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
@@ -128,7 +153,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
@@ -152,7 +176,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
+
+ if (!Inst.isInstantiationRecord())
+ ++SemaRef.NonInstantiationEntries;
}
}
@@ -164,48 +190,119 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
- Invalid = CheckInstantiationDepth(PointOfInstantiation,
- InstantiationRange);
- if (!Invalid) {
- ActiveTemplateInstantiation Inst;
- Inst.Kind
- = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
- Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
- Inst.TemplateArgs = TemplateArgs;
- Inst.NumTemplateArgs = NumTemplateArgs;
- Inst.InstantiationRange = InstantiationRange;
- SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
- }
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
}
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
- SourceLocation PointOfInstantation,
+ SourceLocation PointOfInstantiation,
ParmVarDecl *Param,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
- Invalid = CheckInstantiationDepth(PointOfInstantation, InstantiationRange);
+ Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
if (!Invalid) {
ActiveTemplateInstantiation Inst;
Inst.Kind
= ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation;
- Inst.PointOfInstantiation = PointOfInstantation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
Inst.Entity = reinterpret_cast<uintptr_t>(Param);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
- Invalid = false;
}
}
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ NamedDecl *Param,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange) : SemaRef(SemaRef) {
+ Invalid = false;
+
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Template = Template;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Param);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+
+ assert(!Inst.isInstantiationRecord());
+ ++SemaRef.NonInstantiationEntries;
+}
+
void Sema::InstantiatingTemplate::Clear() {
if (!Invalid) {
+ if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) {
+ assert(SemaRef.NonInstantiationEntries > 0);
+ --SemaRef.NonInstantiationEntries;
+ }
+
SemaRef.ActiveTemplateInstantiations.pop_back();
Invalid = true;
}
@@ -214,8 +311,11 @@ void Sema::InstantiatingTemplate::Clear() {
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
SourceLocation PointOfInstantiation,
SourceRange InstantiationRange) {
- if (SemaRef.ActiveTemplateInstantiations.size()
- <= SemaRef.getLangOptions().InstantiationDepth)
+ assert(SemaRef.NonInstantiationEntries <=
+ SemaRef.ActiveTemplateInstantiations.size());
+ if ((SemaRef.ActiveTemplateInstantiations.size() -
+ SemaRef.NonInstantiationEntries)
+ <= SemaRef.getLangOptions().InstantiationDepth)
return false;
SemaRef.Diag(PointOfInstantiation,
@@ -322,6 +422,34 @@ void Sema::PrintInstantiationStack() {
break;
}
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: {
+ NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity);
+ std::string Name;
+ if (!Parm->getName().empty())
+ Name = std::string(" '") + Parm->getName().str() + "'";
+
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_prior_template_arg_substitution)
+ << isa<TemplateTemplateParmDecl>(Parm)
+ << Name
+ << getTemplateArgumentBindingsText(
+ Active->Template->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_template_default_arg_checking)
+ << getTemplateArgumentBindingsText(
+ Active->Template->getTemplateParameters(),
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange;
+ break;
+ }
}
}
}
@@ -332,18 +460,20 @@ bool Sema::isSFINAEContext() const {
Active = ActiveTemplateInstantiations.rbegin(),
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
- ++Active) {
-
+ ++Active)
+ {
switch(Active->Kind) {
case ActiveTemplateInstantiation::TemplateInstantiation:
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
-
// 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.
+ case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking:
+ // A default template argument instantiation and substitution into
+ // template parameters with arguments for prior parameters may or may
+ // not be a SFINAE context; look further up the stack.
break;
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
@@ -427,6 +557,9 @@ namespace {
Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E,
bool isAddressOfOperand);
+ Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E,
+ bool isAddressOfOperand);
+
/// \brief Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
@@ -440,10 +573,11 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
- assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+ TemplateName Template
+ = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
+ assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
- return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
- TTP->getPosition()).getAsDecl());
+ return Template.getAsTemplateDecl();
}
// If the corresponding template argument is NULL or non-existent, it's
@@ -454,9 +588,8 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
TTP->getPosition()))
return D;
- // FIXME: Implement depth reduction of template template parameters
- assert(false &&
- "Reducing depth of template template parameters is not yet implemented");
+ // Fall through to find the instantiated declaration for this template
+ // template parameter.
}
return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
@@ -567,7 +700,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
if (NTTP->getDepth() < TemplateArgs.getNumLevels()) {
-
// If the corresponding template argument is NULL or non-existent, it's
// because we are performing instantiation from explicitly-specified
// template arguments in a function template, but there were some
@@ -592,7 +724,38 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
if (!VD)
return SemaRef.ExprError();
- return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+ if (VD->getDeclContext()->isRecord()) {
+ // If the value is a class member, we might have a pointer-to-member.
+ // Determine whether the non-type template template parameter is of
+ // pointer-to-member type. If so, we need to build an appropriate
+ // expression for a pointer-to-member, since a "normal" DeclRefExpr
+ // would refer to the member itself.
+ if (NTTP->getType()->isMemberPointerType()) {
+ QualType ClassType
+ = SemaRef.Context.getTypeDeclType(
+ cast<RecordDecl>(VD->getDeclContext()));
+ NestedNameSpecifier *Qualifier
+ = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+ ClassType.getTypePtr());
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ OwningExprResult RefExpr
+ = SemaRef.BuildDeclRefExpr(VD,
+ VD->getType().getNonReferenceType(),
+ E->getLocation(),
+ /*FIXME:*/false, /*FIXME:*/false,
+ &SS);
+ if (RefExpr.isInvalid())
+ return SemaRef.ExprError();
+
+ return SemaRef.CreateBuiltinUnaryOp(E->getLocation(),
+ UnaryOperator::AddrOf,
+ move(RefExpr));
+ }
+ }
+
+ return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+ E->getLocation(),
/*FIXME:*/false, /*FIXME:*/false);
}
@@ -625,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
if (!InstD)
return SemaRef.ExprError();
- // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl,
- // we need to get the underlying decl.
- // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
- InstD = InstD->getUnderlyingDecl();
+ // Flatten using declarations into their shadow declarations.
+ if (isa<UsingDecl>(InstD)) {
+ UsingDecl *UD = cast<UsingDecl>(InstD);
+
+ bool HasNonFunction = false;
+
+ llvm::SmallVector<NamedDecl*, 8> Decls;
+ for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+ E = UD->shadow_end(); I != E; ++I) {
+ NamedDecl *TD = (*I)->getTargetDecl();
+ if (!TD->isFunctionOrFunctionTemplate())
+ HasNonFunction = true;
+
+ Decls.push_back(TD);
+ }
+
+ if (Decls.empty())
+ return SemaRef.ExprError();
+
+ if (Decls.size() == 1)
+ InstD = Decls[0];
+ else if (!HasNonFunction) {
+ OverloadedFunctionDecl *OFD
+ = OverloadedFunctionDecl::Create(SemaRef.Context,
+ UD->getDeclContext(),
+ UD->getDeclName());
+ for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(),
+ E = Decls.end(); I != E; ++I)
+ if (isa<FunctionDecl>(*I))
+ OFD->addOverload(cast<FunctionDecl>(*I));
+ else
+ OFD->addOverload(cast<FunctionTemplateDecl>(*I));
+
+ InstD = OFD;
+ } else {
+ // FIXME
+ assert(false && "using declaration resolved to mixed set");
+ return SemaRef.ExprError();
+ }
+ }
CXXScopeSpec SS;
NestedNameSpecifier *Qualifier = 0;
@@ -648,6 +847,15 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E,
isAddressOfOperand);
}
+Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+ CXXDefaultArgExpr *E, bool isAddressOfOperand) {
+ assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
+ getDescribedFunctionTemplate() &&
+ "Default arg expressions are never formed in dependent cases.");
+ return SemaRef.Owned(E->Retain());
+}
+
+
QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL) {
@@ -889,9 +1097,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Member != MemberEnd; ++Member) {
Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
if (NewMember) {
- if (NewMember->isInvalidDecl())
+ if (NewMember->isInvalidDecl()) {
Invalid = true;
- else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+ } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
Fields.push_back(DeclPtrTy::make(Field));
else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
Instantiation->addDecl(UD);
OpenPOWER on IntegriCloud