diff options
-rw-r--r-- | lib/Sema/Sema.h | 56 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 62 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 16 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-function-params.cpp | 23 |
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> + { + }; +} |