llvm::DenseMap<const Decl *, Decl *> LocalDecls;
/// \brief The outer scope, in which contains local variable
- /// definitions from some other instantiation (that is not
+ /// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
- LocalInstantiationScope(Sema &SemaRef)
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
- SemaRef.CurrentInstantiationScope = this;
+ if (!CombineWithOuterScope)
+ SemaRef.CurrentInstantiationScope = this;
+ else
+ assert(SemaRef.CurrentInstantiationScope &&
+ "No outer instantiation scope?");
}
~LocalInstantiationScope() {
return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
+ NonTypeTemplateParmDecl *getInstantiationOf(
+ const NonTypeTemplateParmDecl *Var) {
+ return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
void InstantiatedLocal(const Decl *D, Decl *Inst) {
Decl *&Stored = LocalDecls[D];
assert(!Stored && "Already instantiated this local");
// FIXME: Clean this up a bit
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
- if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) {
- assert(false && "Cannot reduce non-type template parameter depth yet");
- return getSema().ExprError();
- }
-
- // 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
- // arguments left unspecified.
- if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
- NTTP->getPosition()))
- return SemaRef.Owned(E->Retain());
-
- const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
- NTTP->getPosition());
-
- // The template argument itself might be an expression, in which
- // case we just return that expression.
- if (Arg.getKind() == TemplateArgument::Expression)
- return SemaRef.Owned(Arg.getAsExpr()->Retain());
-
- if (Arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
-
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(VD, TemplateArgs));
- if (!VD)
- return SemaRef.ExprError();
-
- return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
- /*FIXME:*/false, /*FIXME:*/false);
- }
+ 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
+ // arguments left unspecified.
+ if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+ NTTP->getPosition()))
+ return SemaRef.Owned(E->Retain());
+
+ const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
+ NTTP->getPosition());
+
+ // The template argument itself might be an expression, in which
+ // case we just return that expression.
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return SemaRef.Owned(Arg.getAsExpr()->Retain());
+
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(VD, TemplateArgs));
+ if (!VD)
+ return SemaRef.ExprError();
+
+ return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+ /*FIXME:*/false, /*FIXME:*/false);
+ }
- assert(Arg.getKind() == TemplateArgument::Integral);
- QualType T = Arg.getIntegralType();
- if (T->isCharType() || T->isWideCharType())
- return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
- Arg.getAsIntegral()->getZExtValue(),
- T->isWideCharType(),
- T,
- E->getSourceRange().getBegin()));
- if (T->isBooleanType())
- return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral()->getBoolValue(),
- T,
- E->getSourceRange().getBegin()));
-
- assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
- return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
- *Arg.getAsIntegral(),
+ assert(Arg.getKind() == TemplateArgument::Integral);
+ QualType T = Arg.getIntegralType();
+ if (T->isCharType() || T->isWideCharType())
+ return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
+ Arg.getAsIntegral()->getZExtValue(),
+ T->isWideCharType(),
T,
E->getSourceRange().getBegin()));
+ if (T->isBooleanType())
+ return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
+ Arg.getAsIntegral()->getBoolValue(),
+ T,
+ E->getSourceRange().getBegin()));
+
+ assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
+ return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
+ *Arg.getAsIntegral(),
+ T,
+ E->getSourceRange().getBegin()));
+ }
+
+ // We have a non-type template parameter that isn't fully substituted;
+ // FindInstantiatedDecl will find it in the local instantiation scope.
}
NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs);
}
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // Create a local instantiation scope for this class template, which
+ // will contain the instantiations of the template parameters.
+ Sema::LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
Decl *
TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
- // FIXME: Dig out the out-of-line definition of this function template?
-
+ // Create a local instantiation scope for this function template, which
+ // will contain the instantiations of the template parameters and then get
+ // 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)
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef);
+ Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
return Info->Function;
}
- Sema::LocalInstantiationScope Scope(SemaRef);
+ Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
llvm::SmallVector<ParmVarDecl *, 4> Params;
QualType T = SubstFunctionType(D, Params);
TemplateTypeParmDecl *Inst =
TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- TTPT->getDepth(), TTPT->getIndex(),
+ TTPT->getDepth() - 1, TTPT->getIndex(),
TTPT->getName(),
D->wasDeclaredWithTypename(),
D->isParameterPack());
D->defaultArgumentWasInherited() /* preserve? */);
}
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+
return Inst;
}
Param->setInvalidDecl();
Param->setDefaultArgument(D->getDefaultArgument());
+
+ // Introduce this template parameter's instantiation into the instantiation
+ // scope.
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
return Param;
}
TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
ClassTemplateDecl *ClassTemplate,
ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ // Create a local instantiation scope for this class template partial
+ // specialization, which will contain the instantiations of the template
+ // parameters.
+ Sema::LocalInstantiationScope Scope(SemaRef);
+
// Substitute into the template parameters of the class template partial
// specialization.
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
}
DeclContext *ParentDC = D->getDeclContext();
- if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) {
+ if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
+ isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
+ ParentDC->isFunctionOrMethod()) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
--- /dev/null
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5311
+template<typename T>
+class StringSwitch {
+public:
+ template<unsigned N>
+ void Case(const char (&S)[N], const int & Value) {
+ }
+};
+
+int main(int argc, char *argv[]) {
+ (void)StringSwitch<int>();
+}
float* (*fp7)(int) = X1::f2<>;
float* (*fp8)(float) = X1::f2<float>;
}
+
+template<int A> struct X2 {
+ int m;
+};
+
+template<typename T>
+struct X3 : T { };
+
+template<typename T>
+struct X4 {
+ template<typename U>
+ void f(X2<sizeof(X3<U>().U::m)>);
+};
+
+void f(X4<X3<int> > x4i) {
+ X2<sizeof(int)> x2;
+ x4i.f<X2<sizeof(int)> >(x2);
+}