diff options
-rw-r--r-- | lib/Sema/Sema.h | 27 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 7 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-function-params.cpp | 11 |
4 files changed, 44 insertions, 13 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ba6d38f849..7e2e614396 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3487,15 +3487,27 @@ 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; + // This class is non-copyable LocalInstantiationScope(const LocalInstantiationScope &); LocalInstantiationScope &operator=(const LocalInstantiationScope &); public: - LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) + LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false, + bool Temporary = false) : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), - Exited(false) { - if (!CombineWithOuterScope) + Exited(false), Temporary(Temporary) { + if (!CombineWithOuterScope && !Temporary) SemaRef.CurrentInstantiationScope = this; else assert(SemaRef.CurrentInstantiationScope && @@ -3503,8 +3515,11 @@ public: } ~LocalInstantiationScope() { - if (!Exited) + if (!Exited) { SemaRef.CurrentInstantiationScope = Outer; + for (unsigned I = 0, N = AddedTemporaryDecls.size(); I != N; ++I) + LocalDecls.erase(AddedTemporaryDecls[I]); + } } /// \brief Exit this local instantiation scope early. @@ -3537,6 +3552,10 @@ public: 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; } }; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 326519d3a3..3a8ed50894 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -987,13 +987,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, Decl *Param = const_cast<NamedDecl *>( Partial->getTemplateParameters()->getParam(I)); - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) - Info.Param = TTP; - else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) - Info.Param = NTTP; - else - Info.Param = cast<TemplateTemplateParmDecl>(Param); + Info.Param = makeTemplateParameter(Param); return TDK_Incomplete; } @@ -1010,6 +1004,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // verify that the instantiated template arguments are both valid // and are equivalent to the template arguments originally provided // to the class template. + Sema::LocalInstantiationScope InstScope(*this); ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); const TemplateArgumentLoc *PartialTemplateArgs = Partial->getTemplateArgsAsWritten(); @@ -1458,6 +1453,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // The types of the parameters from which we will perform template argument // deduction. + Sema::LocalInstantiationScope InstScope(*this); TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); llvm::SmallVector<TemplateArgument, 4> Deduced; @@ -1612,6 +1608,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType FunctionType = Function->getType(); // Substitute any explicit template arguments. + Sema::LocalInstantiationScope InstScope(*this); llvm::SmallVector<TemplateArgument, 4> Deduced; llvm::SmallVector<QualType, 4> ParamTypes; if (ExplicitTemplateArgs) { @@ -1739,6 +1736,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // modulo the various allowed differences. // Finish template argument deduction. + Sema::LocalInstantiationScope InstScope(*this); FunctionDecl *Spec = 0; TemplateDeductionResult Result = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, Spec, Info); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index ac1bf7219c..89a660c79f 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -873,8 +873,11 @@ TemplateInstantiator::TransformFunctionTypeParams(FunctionProtoTypeLoc TL, llvm::SmallVectorImpl<QualType> &PTypes, llvm::SmallVectorImpl<ParmVarDecl*> &PVars) { // Create a local instantiation scope for the parameters. - Sema::LocalInstantiationScope - Scope(SemaRef, SemaRef.CurrentInstantiationScope != 0); + // 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)) diff --git a/test/SemaTemplate/instantiate-function-params.cpp b/test/SemaTemplate/instantiate-function-params.cpp index a574dbb787..dfba14a97c 100644 --- a/test/SemaTemplate/instantiate-function-params.cpp +++ b/test/SemaTemplate/instantiate-function-params.cpp @@ -31,3 +31,14 @@ template < typename TT > struct ForwardIterator : I }; typedef instantiate< &requirement_<void(*)(ForwardIterator<char*> x)>::failed> boost_concept_checkX; // expected-error{{no member named}} \ // expected-note 6{{in instantiation}} + +template<typename T> struct X0 { }; +template<typename R, typename A1> struct X0<R(A1 param)> { }; + +template<typename T, typename A1, typename A2> +void instF0(X0<T(A1)> x0a, X0<T(A2)> x0b) { + X0<T(A1)> x0c; + X0<T(A2)> x0d; +} + +template void instF0<int, int, float>(X0<int(int)>, X0<int(float)>); |