aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp10
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp46
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp3
-rw-r--r--test/SemaTemplate/instantiate-declref.cpp3
5 files changed, 35 insertions, 30 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 5b3ea40b06..3825b7cc06 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2250,8 +2250,7 @@ public:
FunctionDecl *Function);
void InstantiateVariableDefinition(VarDecl *Var);
- NamedDecl *
- InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs);
+ NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
// Simple function for cloning expressions.
template<typename T>
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1cc999201b..1546e39ee2 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -407,8 +407,8 @@ QualType
TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
unsigned Quals) const {
TypedefDecl *Typedef
- = cast_or_null<TypedefDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
- TemplateArgs));
+ = cast_or_null<TypedefDecl>(
+ SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
if (!Typedef)
return QualType();
@@ -440,8 +440,7 @@ QualType
TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
unsigned Quals) const {
RecordDecl *Record
- = cast_or_null<RecordDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
- TemplateArgs));
+ = cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
if (!Record)
return QualType();
@@ -452,8 +451,7 @@ QualType
TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
unsigned Quals) const {
EnumDecl *Enum
- = cast_or_null<EnumDecl>(SemaRef.InstantiateDeclRef(T->getDecl(),
- TemplateArgs));
+ = cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
if (!Enum)
return QualType();
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 41c1944b54..33eedcec38 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -671,8 +671,8 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
return 0;
}
-/// \brief Find the instantiation of the given declaration with the
-/// given template arguments.
+/// \brief Find the instantiation of the given declaration within the
+/// current instantiation.
///
/// This routine is intended to be used when \p D is a declaration
/// referenced from within a template, that needs to mapped into the
@@ -695,10 +695,9 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx,
/// In the instantiation of X<int>::getKind(), we need to map the
/// EnumConstantDecl for KnownValue (which refers to
/// X<T>::<Kind>::KnownValue) to its instantiation
-/// (X<int>::<Kind>::KnownValue). InstantiateDeclRef() performs this
-/// mapping, given the template arguments 'int'.
-NamedDecl *
-Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs) {
+/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
+/// this mapping from within the instantiation of X<int>.
+NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
DeclContext *ParentDC = D->getDeclContext();
if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) {
// D is a local of some kind. Look into the map of local
@@ -707,7 +706,7 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs)
}
if (NamedDecl *ParentDecl = dyn_cast<NamedDecl>(ParentDC)) {
- ParentDecl = InstantiateDeclRef(ParentDecl, TemplateArgs);
+ ParentDecl = InstantiateCurrentDeclRef(ParentDecl);
if (!ParentDecl)
return 0;
@@ -740,20 +739,27 @@ Sema::InstantiateDeclRef(NamedDecl *D, const TemplateArgumentList &TemplateArgs)
D = Result;
}
- // D itself might be a class template that we need to instantiate
- // with the given template arguments.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
- if (ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate()) {
- QualType InjectedClassName
- = ClassTemplate->getInjectedClassNameType(Context);
- QualType InstantiatedType = InstantiateType(InjectedClassName,
- TemplateArgs,
- Record->getLocation(),
- Record->getDeclName());
- if (InstantiatedType.isNull())
- return 0;
- if (const RecordType *RT = InstantiatedType->getAsRecordType())
- D = RT->getDecl();
+ if (ClassTemplateDecl *ClassTemplate
+ = Record->getDescribedClassTemplate()) {
+ // When the declaration D was parsed, it referred to the current
+ // instantiation. Therefore, look through the current context,
+ // which contains actual instantiations, to find the
+ // instantiation of the "current instantiation" that D refers
+ // to. Alternatively, we could just instantiate the
+ // injected-class-name with the current template arguments, but
+ // such an instantiation is far more expensive.
+ for (DeclContext *DC = CurContext; !DC->isFileContext();
+ DC = DC->getParent()) {
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+ if (Context.getCanonicalDecl(Spec->getSpecializedTemplate())
+ == Context.getCanonicalDecl(ClassTemplate))
+ return Spec;
+ }
+
+ assert(false &&
+ "Unable to find declaration for the current instantiation");
}
return D;
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 726ac2b425..31bb91def2 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -108,7 +108,6 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr(
Sema::OwningExprResult
TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
- // FIXME: Recast this in terms of Sema::InstantiateDeclRef.
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
assert(NTTP->getDepth() == 0 && "No nested templates yet");
@@ -141,7 +140,7 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
}
ValueDecl *NewD
- = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateDeclRef(D, TemplateArgs));
+ = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D));
if (!NewD)
return SemaRef.ExprError();
diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp
index 3b6db38617..0e1e562056 100644
--- a/test/SemaTemplate/instantiate-declref.cpp
+++ b/test/SemaTemplate/instantiate-declref.cpp
@@ -24,6 +24,9 @@ namespace N {
K1 k1 = K1Val;
Kind1 = K1Val;
Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
+
+ InnerTemplate t;
+ InnerTemplate<type> t2;
}
};
};