aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h27
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp7
-rw-r--r--test/SemaTemplate/instantiate-function-params.cpp11
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)>);