summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-27 17:54:46 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-27 17:54:46 +0000
commitcd3a09792597ebcb0910c0f8cefa0d713e7f1fc3 (patch)
tree0577be3cda177bc6a9ba64d32cb822475184d61e /clang
parent0a9ea80013b78c49ecb4fa4f45e6a66089f2f9e3 (diff)
downloadbcm5719-llvm-cd3a09792597ebcb0910c0f8cefa0d713e7f1fc3.tar.gz
bcm5719-llvm-cd3a09792597ebcb0910c0f8cefa0d713e7f1fc3.zip
Simplify, and improve the performance of, template instantiation for
declaration references. The key realization is that dependent Decls, which actually require instantiation, can only refer to the current instantiation or members thereof. And, since the current context during instantiation contains all of those members of the current instantiation, we can simply find the real instantiate that matches up with the "current instantiation" template. llvm-svn: 72486
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp10
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp46
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateExpr.cpp3
-rw-r--r--clang/test/SemaTemplate/instantiate-declref.cpp3
5 files changed, 35 insertions, 30 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 5b3ea40b064..3825b7cc06a 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 1cc999201bb..1546e39ee24 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 41c1944b541..33eedcec38a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiateExpr.cpp b/clang/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 726ac2b425e..31bb91def2c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/clang/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/clang/test/SemaTemplate/instantiate-declref.cpp b/clang/test/SemaTemplate/instantiate-declref.cpp
index 3b6db38617b..0e1e562056e 100644
--- a/clang/test/SemaTemplate/instantiate-declref.cpp
+++ b/clang/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;
}
};
};
OpenPOWER on IntegriCloud