aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h56
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp62
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp11
-rw-r--r--lib/Sema/TreeTransform.h16
-rw-r--r--test/SemaTemplate/instantiate-function-params.cpp23
6 files changed, 95 insertions, 77 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 4d107b5df2..a5b43e8a04 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3589,7 +3589,7 @@ public:
/// instantiated ParmVarDecl for 'x'.
llvm::DenseMap<const Decl *, Decl *> LocalDecls;
- /// \brief The outer scope, in which contains local variable
+ /// \brief The outer scope, which contains local variable
/// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
@@ -3597,54 +3597,36 @@ public:
/// \brief Whether we have already exited this scope.
bool Exited;
- /// \brief Whether this scope is temporary, meaning that we should
- /// remove any additions we make once we exit this
- /// scope. Temporary scopes are always combined with their outer
- /// scopes.
- bool Temporary;
-
- /// \brief List of the declarations that we have added into this
- /// temporary scope. They will be removed when we exit the
- /// temporary scope.
- llvm::SmallVector<const Decl *, 4> AddedTemporaryDecls;
-
+ /// \brief Whether to combine this scope with the outer scope, such that
+ /// lookup will search our outer scope.
+ bool CombineWithOuterScope;
+
// This class is non-copyable
LocalInstantiationScope(const LocalInstantiationScope &);
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
- LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false,
- bool Temporary = false)
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
- Exited(false), Temporary(Temporary) {
- if (!CombineWithOuterScope && !Temporary)
- SemaRef.CurrentInstantiationScope = this;
- else
- assert(SemaRef.CurrentInstantiationScope &&
- "No outer instantiation scope?");
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+ {
+ SemaRef.CurrentInstantiationScope = this;
}
~LocalInstantiationScope() {
- if (!Exited) {
- SemaRef.CurrentInstantiationScope = Outer;
- for (unsigned I = 0, N = AddedTemporaryDecls.size(); I != N; ++I)
- LocalDecls.erase(AddedTemporaryDecls[I]);
- }
+ Exit();
}
/// \brief Exit this local instantiation scope early.
void Exit() {
+ if (Exited)
+ return;
+
SemaRef.CurrentInstantiationScope = Outer;
- LocalDecls.clear();
Exited = true;
}
- Decl *getInstantiationOf(const Decl *D) {
- Decl *Result = LocalDecls[D];
- assert((Result || D->isInvalidDecl()) &&
- "declaration was not instantiated in this scope!");
- return Result;
- }
+ Decl *getInstantiationOf(const Decl *D);
VarDecl *getInstantiationOf(const VarDecl *Var) {
return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
@@ -3659,15 +3641,7 @@ public:
return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
}
- void InstantiatedLocal(const Decl *D, Decl *Inst) {
- Decl *&Stored = LocalDecls[D];
- assert((!Stored || Stored == Inst) && "Already instantiated this local");
-
- if (Temporary && !Stored)
- AddedTemporaryDecls.push_back(D);
-
- Stored = Inst;
- }
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
};
/// \brief The current instantiation scope used to store local
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index a84ceab2eb..db9ed7e1ef 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -5335,6 +5335,8 @@ namespace {
DeclarationName Entity;
public:
+ typedef TreeTransform<CurrentInstantiationRebuilder> inherited;
+
CurrentInstantiationRebuilder(Sema &SemaRef,
SourceLocation Loc,
DeclarationName Entity)
@@ -5370,7 +5372,7 @@ namespace {
/// FIXME: This is completely unsafe; we will need to actually clone the
/// expressions.
Sema::OwningExprResult TransformExpr(Expr *E) {
- return getSema().Owned(E);
+ return getSema().Owned(E->Retain());
}
/// \brief Transforms a typename type by determining whether the type now
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index a75a80b83d..e727cdbc9e 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -532,8 +532,7 @@ bool Sema::isSFINAEContext() const {
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
namespace {
- class TemplateInstantiator
- : public TreeTransform<TemplateInstantiator> {
+ class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
const MultiLevelTemplateArgumentList &TemplateArgs;
SourceLocation Loc;
DeclarationName Entity;
@@ -604,13 +603,9 @@ namespace {
Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
- /// \brief Transforms a function proto type by performing
- /// substitution in the function parameters, possibly adjusting
- /// their types and marking default arguments as uninstantiated.
- bool TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
- llvm::SmallVectorImpl<QualType> &PTypes,
- llvm::SmallVectorImpl<ParmVarDecl*> &PVars);
-
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ QualType ObjectType);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm);
/// \brief Transforms a template type parameter type by performing
@@ -825,23 +820,12 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
E->getParam());
}
-
-bool
-TemplateInstantiator::TransformFunctionTypeParams(FunctionProtoTypeLoc TL,
- llvm::SmallVectorImpl<QualType> &PTypes,
- llvm::SmallVectorImpl<ParmVarDecl*> &PVars) {
- // Create a local instantiation scope for the parameters.
- // FIXME: When we implement the C++0x late-specified return type,
- // we will need to move this scope out to the function type itself.
- bool IsTemporaryScope = (SemaRef.CurrentInstantiationScope != 0);
- Sema::LocalInstantiationScope Scope(SemaRef, IsTemporaryScope,
- IsTemporaryScope);
-
- if (TreeTransform<TemplateInstantiator>::
- TransformFunctionTypeParams(TL, PTypes, PVars))
- return true;
-
- return false;
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ QualType ObjectType) {
+ // We need a local instantiation scope for this function prototype.
+ Sema::LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return inherited::TransformFunctionProtoType(TLB, TL, ObjectType);
}
ParmVarDecl *
@@ -1600,3 +1584,29 @@ bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
return Instantiator.TransformTemplateArgument(Input, Output);
}
+
+Decl *Sema::LocalInstantiationScope::getInstantiationOf(const Decl *D) {
+ for (LocalInstantiationScope *Current = this; Current;
+ Current = Current->Outer) {
+ // Check if we found something within this scope.
+ llvm::DenseMap<const Decl *, Decl *>::iterator Found
+ = Current->LocalDecls.find(D);
+ if (Found != Current->LocalDecls.end())
+ return Found->second;
+
+ // If we aren't combined with our outer scope, we're done.
+ if (!Current->CombineWithOuterScope)
+ break;
+ }
+
+ assert(D->isInvalidDecl() &&
+ "declaration was not instantiated in this scope!");
+ return 0;
+}
+
+void Sema::LocalInstantiationScope::InstantiatedLocal(const Decl *D,
+ Decl *Inst) {
+ Decl *&Stored = LocalDecls[D];
+ assert((!Stored || Stored == Inst)&& "Already instantiated this local");
+ Stored = Inst;
+}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 25ba2829ce..48b517ef22 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -822,7 +822,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// merged with the local instantiation scope for the function template
// itself.
Sema::LocalInstantiationScope Scope(SemaRef);
-
+
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
@@ -1775,11 +1775,18 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
if (NewTInfo != OldTInfo) {
// Get parameters from the new type info.
+ TypeLoc OldTL = OldTInfo->getTypeLoc();
+ FunctionProtoTypeLoc *OldProtoLoc = cast<FunctionProtoTypeLoc>(&OldTL);
TypeLoc NewTL = NewTInfo->getTypeLoc();
FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
assert(NewProtoLoc && "Missing prototype?");
- for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i)
+ for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i) {
+ // FIXME: Variadic templates will break this.
Params.push_back(NewProtoLoc->getArg(i));
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(
+ OldProtoLoc->getArg(i),
+ NewProtoLoc->getArg(i));
+ }
} else {
// The function type itself was not dependent and therefore no
// substitution occurred. However, we still need to instantiate
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 5143b77f59..445cf17aad 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2907,17 +2907,19 @@ QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
QualType ObjectType) {
- FunctionProtoType *T = TL.getTypePtr();
- QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
- if (ResultType.isNull())
- return QualType();
-
- // Transform the parameters.
+ // Transform the parameters. We do this first for the benefit of template
+ // instantiations, so that the ParmVarDecls get/ placed into the template
+ // instantiation scope before we transform the function type.
llvm::SmallVector<QualType, 4> ParamTypes;
llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
return QualType();
-
+
+ FunctionProtoType *T = TL.getTypePtr();
+ QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ResultType != T->getResultType() ||
diff --git a/test/SemaTemplate/instantiate-function-params.cpp b/test/SemaTemplate/instantiate-function-params.cpp
index eb16cf7651..45de3425d2 100644
--- a/test/SemaTemplate/instantiate-function-params.cpp
+++ b/test/SemaTemplate/instantiate-function-params.cpp
@@ -53,3 +53,26 @@ void use_func_ptr() {
};
template void use_func_ptr<int, float, double>();
+
+namespace PR6990 {
+ template < typename , typename = int, typename = int > struct X1;
+ template <typename >
+ struct X2;
+
+ template <typename = int *, typename TokenT = int,
+ typename = int( X2<TokenT> &)>
+ struct X3
+ {
+ };
+
+ template <typename , typename P>
+ struct X3_base : X3< X1<int, P> >
+ {
+ protected: typedef X1< P> type;
+ X3<type> e;
+ };
+
+ struct r : X3_base<int, int>
+ {
+ };
+}