[cfe-commits] r82069 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/default-expr-arguments.cpp
Douglas Gregor
dgregor at apple.com
Wed Sep 16 11:34:49 PDT 2009
Author: dgregor
Date: Wed Sep 16 13:34:49 2009
New Revision: 82069
URL: http://llvm.org/viewvc/llvm-project?rev=82069&view=rev
Log:
Teach Sema::FindInstantiatedDecl to find instantiated RecordDecls even
when we are not instantiating the corresponding "current
instantiation." This happens, e.g., when we are instantiating a
declaration reference that refers into the "current instantiation" but
occurs in a default function argument. The libstdc++ vector default
constructor now instantiates properly.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=82069&r1=82068&r2=82069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Sep 16 13:34:49 2009
@@ -3103,8 +3103,10 @@
const CXXConstructorDecl *Tmpl,
const MultiLevelTemplateArgumentList &TemplateArgs);
- NamedDecl *FindInstantiatedDecl(NamedDecl *D);
- DeclContext *FindInstantiatedContext(DeclContext *DC);
+ NamedDecl *FindInstantiatedDecl(NamedDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ DeclContext *FindInstantiatedContext(DeclContext *DC,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
// Objective-C declarations.
virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=82069&r1=82068&r2=82069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Sep 16 13:34:49 2009
@@ -429,7 +429,7 @@
"Reducing depth of template template parameters is not yet implemented");
}
- return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D));
+ return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
}
Decl *TemplateInstantiator::TransformDefinition(Decl *D) {
@@ -533,7 +533,8 @@
if (Arg.getKind() == TemplateArgument::Declaration) {
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
- VD = cast_or_null<ValueDecl>(getSema().FindInstantiatedDecl(VD));
+ VD = cast_or_null<ValueDecl>(
+ getSema().FindInstantiatedDecl(VD, TemplateArgs));
if (!VD)
return SemaRef.ExprError();
@@ -562,7 +563,7 @@
E->getSourceRange().getBegin()));
}
- NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D);
+ NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs);
if (!InstD)
return SemaRef.ExprError();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=82069&r1=82068&r2=82069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Sep 16 13:34:49 2009
@@ -491,7 +491,8 @@
return 0;
// Build the instantiated method declaration.
- DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext());
+ DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext(),
+ TemplateArgs);
FunctionDecl *Function =
FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(),
D->getDeclName(), T, D->getDeclaratorInfo(),
@@ -1176,9 +1177,10 @@
// Is this an anonymous union?
if (FieldDecl *UnionInit = Init->getAnonUnionMember())
- Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit));
+ Member = cast<FieldDecl>(FindInstantiatedDecl(UnionInit, TemplateArgs));
else
- Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember()));
+ Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMember(),
+ TemplateArgs));
NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
NewArgs.size(),
@@ -1333,9 +1335,10 @@
/// within the current instantiation.
///
/// \returns NULL if there was an error
-DeclContext *Sema::FindInstantiatedContext(DeclContext* DC) {
+DeclContext *Sema::FindInstantiatedContext(DeclContext* DC,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
- Decl* ID = FindInstantiatedDecl(D);
+ Decl* ID = FindInstantiatedDecl(D, TemplateArgs);
return cast_or_null<DeclContext>(ID);
} else return DC;
}
@@ -1366,7 +1369,8 @@
/// X<T>::<Kind>::KnownValue) to its instantiation
/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs
/// this mapping from within the instantiation of X<int>.
-NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D) {
+NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
// Transform all of the elements of the overloaded function set.
OverloadedFunctionDecl *Result
@@ -1376,7 +1380,8 @@
FEnd = Ovl->function_end();
F != FEnd; ++F) {
Result->addOverload(
- AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F)));
+ AnyFunctionDecl::getFromNamedDecl(FindInstantiatedDecl(*F,
+ TemplateArgs)));
}
return Result;
@@ -1389,29 +1394,68 @@
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
}
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
- 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.
+ if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+ if (!Record->isDependentContext())
+ return D;
+
+ // If the RecordDecl is actually the injected-class-name or a "templated"
+ // declaration for a class template or class template partial
+ // specialization, substitute into the injected-class-name of the
+ // class template or partial specialization to find the new DeclContext.
+ QualType T;
+ ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
+
+ if (ClassTemplate) {
+ T = ClassTemplate->getInjectedClassNameType(Context);
+ } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
+ T = Context.getTypeDeclType(Record);
+ ClassTemplate = PartialSpec->getSpecializedTemplate();
+ }
+
+ if (!T.isNull()) {
+ // Substitute into the injected-class-name to get the type corresponding
+ // to the instantiation we want. This substitution should never fail,
+ // since we know we can instantiate the injected-class-name or we wouldn't
+ // have gotten to the injected-class-name!
+ // FIXME: Can we use the CurrentInstantiationScope to avoid this extra
+ // instantiation in the common case?
+ T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
+ assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
+
+ if (!T->isDependentType()) {
+ assert(T->isRecordType() && "Instantiation must produce a record type");
+ return T->getAs<RecordType>()->getDecl();
+ }
+
+ // We are performing "partial" template instantiation to create the
+ // member declarations for the members of a class template
+ // specialization. Therefore, D is actually referring to something in
+ // the current instantiation. Look through the current context,
+ // which contains actual instantiations, to find the instantiation of
+ // the "current instantiation" that D refers to.
for (DeclContext *DC = CurContext; !DC->isFileContext();
DC = DC->getParent()) {
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(DC))
- if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate()))
+ if (isInstantiationOf(ClassTemplate,
+ Spec->getSpecializedTemplate()))
return Spec;
}
assert(false &&
"Unable to find declaration for the current instantiation");
+ return Record;
}
+
+ // Fall through to deal with other dependent record types (e.g.,
+ // anonymous unions in class templates).
+ }
- ParentDC = FindInstantiatedContext(ParentDC);
+ if (!ParentDC->isDependentContext())
+ return D;
+
+ ParentDC = FindInstantiatedContext(ParentDC, TemplateArgs);
if (!ParentDC)
return 0;
Modified: cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp?rev=82069&r1=82068&r2=82069&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp (original)
+++ cfe/trunk/test/SemaTemplate/default-expr-arguments.cpp Wed Sep 16 13:34:49 2009
@@ -68,3 +68,13 @@
xn.f(42);
xn.f(); // expected-note{{in instantiation of default function argument}}
}
+
+template<typename T>
+struct X1 {
+ typedef T value_type;
+ X1(const value_type& value = value_type());
+};
+
+void test_X1() {
+ X1<int> x1;
+}
More information about the cfe-commits
mailing list