[llvm-branch-commits] [cfe-branch] r119250 - in /cfe/branches/Apple/whitney: include/clang/Sema/Template.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.decls/temp.class.spec/p6.cpp test/SemaTemplate/explicit-specialization-member.cpp
Daniel Dunbar
daniel at zuster.org
Mon Nov 15 13:46:08 PST 2010
Author: ddunbar
Date: Mon Nov 15 15:46:08 2010
New Revision: 119250
URL: http://llvm.org/viewvc/llvm-project?rev=119250&view=rev
Log:
Merge r118704:
--
Author: Douglas Gregor <dgregor at apple.com>
Date: Wed Nov 10 19:44:59 2010 +0000
Instantiate class member template partial specialization declarations
in the order they occur within the class template, delaying
out-of-line member template partial specializations until after the
class has been fully instantiated. This fixes a regression introduced
by r118454 (itself a fix for PR8001).
Modified:
cfe/branches/Apple/whitney/include/clang/Sema/Template.h
cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp
cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp
Modified: cfe/branches/Apple/whitney/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Sema/Template.h?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Sema/Template.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Sema/Template.h Mon Nov 15 15:46:08 2010
@@ -13,8 +13,10 @@
#define LLVM_CLANG_SEMA_TEMPLATE_H
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
+#include <utility>
namespace clang {
/// \brief Data structure that captures multiple levels of template argument
@@ -239,6 +241,113 @@
void InstantiatedLocal(const Decl *D, Decl *Inst);
};
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
+ Sema &SemaRef;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+
+ /// \brief A list of out-of-line class template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing class's instantiation is complete.
+ llvm::SmallVector<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>, 4>
+ OutOfLinePartialSpecs;
+
+ public:
+ TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs)
+ : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
+
+ // FIXME: Once we get closer to completion, replace these manually-written
+ // declarations with automatically-generated ones from
+ // clang/AST/DeclNodes.inc.
+ Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ Decl *VisitNamespaceDecl(NamespaceDecl *D);
+ Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ Decl *VisitTypedefDecl(TypedefDecl *D);
+ Decl *VisitVarDecl(VarDecl *D);
+ Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitFieldDecl(FieldDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
+ Decl *VisitEnumDecl(EnumDecl *D);
+ Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+ Decl *VisitFriendDecl(FriendDecl *D);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams = 0);
+ Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
+ Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
+ Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
+ ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
+ Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
+ Decl *VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
+ Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+ Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ Decl *VisitUsingDecl(UsingDecl *D);
+ Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
+ Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ // Base case. FIXME: Remove once we can instantiate everything.
+ Decl *VisitDecl(Decl *D) {
+ unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
+ Diagnostic::Error,
+ "cannot instantiate %0 yet");
+ SemaRef.Diag(D->getLocation(), DiagID)
+ << D->getDeclKindName();
+
+ return 0;
+ }
+
+ typedef
+ llvm::SmallVectorImpl<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> >
+ ::iterator
+ delayed_partial_spec_iterator;
+
+ /// \brief Return an iterator to the beginning of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_begin() {
+ return OutOfLinePartialSpecs.begin();
+ }
+
+ /// \brief Return an iterator to the end of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_end() {
+ return OutOfLinePartialSpecs.end();
+ }
+
+ // Helper functions for instantiating methods.
+ TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+ llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+ bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+ bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *List);
+
+ bool SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl);
+ bool SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl);
+
+ ClassTemplatePartialSpecializationDecl *
+ InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
+ };
}
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
Modified: cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiate.cpp Mon Nov 15 15:46:08 2010
@@ -1219,6 +1219,7 @@
if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
Invalid = true;
+ TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
llvm::SmallVector<Decl*, 4> Fields;
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
MemberEnd = Pattern->decls_end();
@@ -1235,7 +1236,12 @@
if ((*Member)->getDeclContext() != Pattern)
continue;
- Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
+ if ((*Member)->isInvalidDecl()) {
+ Invalid = true;
+ continue;
+ }
+
+ Decl *NewMember = Instantiator.Visit(*Member);
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
Fields.push_back(Field);
@@ -1255,7 +1261,22 @@
CheckCompletedCXXClass(Instantiation);
if (Instantiation->isInvalidDecl())
Invalid = true;
-
+ else {
+ // Instantiate any out-of-line class template partial
+ // specializations now.
+ for (TemplateDeclInstantiator::delayed_partial_spec_iterator
+ P = Instantiator.delayed_partial_spec_begin(),
+ PEnd = Instantiator.delayed_partial_spec_end();
+ P != PEnd; ++P) {
+ if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
+ P->first,
+ P->second)) {
+ Invalid = true;
+ break;
+ }
+ }
+ }
+
// Exit the scope of this instantiation.
SavedContext.pop();
Modified: cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Nov 15 15:46:08 2010
@@ -25,85 +25,6 @@
using namespace clang;
-namespace {
- class TemplateDeclInstantiator
- : public DeclVisitor<TemplateDeclInstantiator, Decl *> {
- Sema &SemaRef;
- DeclContext *Owner;
- const MultiLevelTemplateArgumentList &TemplateArgs;
-
- public:
- TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
- const MultiLevelTemplateArgumentList &TemplateArgs)
- : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
-
- // FIXME: Once we get closer to completion, replace these manually-written
- // declarations with automatically-generated ones from
- // clang/AST/DeclNodes.inc.
- Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
- Decl *VisitNamespaceDecl(NamespaceDecl *D);
- Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
- Decl *VisitTypedefDecl(TypedefDecl *D);
- Decl *VisitVarDecl(VarDecl *D);
- Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
- Decl *VisitFieldDecl(FieldDecl *D);
- Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
- Decl *VisitEnumDecl(EnumDecl *D);
- Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
- Decl *VisitFriendDecl(FriendDecl *D);
- Decl *VisitFunctionDecl(FunctionDecl *D,
- TemplateParameterList *TemplateParams = 0);
- Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
- Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
- TemplateParameterList *TemplateParams = 0);
- Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
- Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
- Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
- ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
- Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
- Decl *VisitClassTemplatePartialSpecializationDecl(
- ClassTemplatePartialSpecializationDecl *D);
- Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
- Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
- Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
- Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
- Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
- Decl *VisitUsingDecl(UsingDecl *D);
- Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
- Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
- Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
-
- // Base case. FIXME: Remove once we can instantiate everything.
- Decl *VisitDecl(Decl *D) {
- unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID(
- Diagnostic::Error,
- "cannot instantiate %0 yet");
- SemaRef.Diag(D->getLocation(), DiagID)
- << D->getDeclKindName();
-
- return 0;
- }
-
- // Helper functions for instantiating methods.
- TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
- llvm::SmallVectorImpl<ParmVarDecl *> &Params);
- bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
- bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
-
- TemplateParameterList *
- SubstTemplateParams(TemplateParameterList *List);
-
- bool SubstQualifier(const DeclaratorDecl *OldDecl,
- DeclaratorDecl *NewDecl);
- bool SubstQualifier(const TagDecl *OldDecl,
- TagDecl *NewDecl);
-
- bool InstantiateClassTemplatePartialSpecialization(
- ClassTemplateDecl *ClassTemplate,
- ClassTemplatePartialSpecializationDecl *PartialSpec);
- };
-}
-
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
DeclaratorDecl *NewDecl) {
NestedNameSpecifier *OldQual = OldDecl->getQualifier();
@@ -860,14 +781,18 @@
}
Owner->addDecl(Inst);
-
- // Instantiate all of the partial specializations of this member class
- // template.
- llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
- D->getPartialSpecializations(PartialSpecs);
- for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
- InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]);
-
+
+ if (!PrevClassTemplate) {
+ // Queue up any out-of-line partial specializations of this member
+ // class template; the client will force their instantiation once
+ // the enclosing class has been instantiated.
+ llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+ D->getPartialSpecializations(PartialSpecs);
+ for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
+ if (PartialSpecs[I]->isOutOfLine())
+ OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
+ }
+
return Inst;
}
@@ -888,7 +813,11 @@
if (!InstClassTemplate)
return 0;
- return InstClassTemplate->findPartialSpecInstantiatedFromMember(D);
+ if (ClassTemplatePartialSpecializationDecl *Result
+ = InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
+ return Result;
+
+ return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
}
Decl *
@@ -1818,8 +1747,9 @@
/// \param PartialSpec the (uninstantiated) class template partial
/// specialization that we are instantiating.
///
-/// \returns true if there was an error, false otherwise.
-bool
+/// \returns The instantiated partial specialization, if successful; otherwise,
+/// NULL to indicate an error.
+ClassTemplatePartialSpecializationDecl *
TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
ClassTemplateDecl *ClassTemplate,
ClassTemplatePartialSpecializationDecl *PartialSpec) {
@@ -1833,7 +1763,7 @@
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
- return true;
+ return 0;
// Substitute into the template arguments of the class template partial
// specialization.
@@ -1845,7 +1775,7 @@
for (unsigned I = 0; I != N; ++I) {
TemplateArgumentLoc Loc;
if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs))
- return true;
+ return 0;
InstTemplateArgs.addArgument(Loc);
}
@@ -1859,7 +1789,7 @@
InstTemplateArgs,
false,
Converted))
- return true;
+ return 0;
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
@@ -1906,10 +1836,10 @@
// Outer<int, int> outer; // error: the partial specializations of Inner
// // have the same signature.
SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
- << WrittenTy;
+ << WrittenTy->getType();
SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
<< SemaRef.Context.getTypeDeclType(PrevDecl);
- return true;
+ return 0;
}
@@ -1936,7 +1866,7 @@
// Add this partial specialization to the set of class template partial
// specializations.
ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
- return false;
+ return InstPartialSpec;
}
TypeSourceInfo*
Modified: cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp (original)
+++ cfe/branches/Apple/whitney/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp Mon Nov 15 15:46:08 2010
@@ -53,3 +53,24 @@
int array3[X0<float>::Inner0<int>::value == 0? 1 : -1];
int array4[X0<float>::Inner0<int*>::value == 3? 1 : -1];
int array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1];
+
+namespace rdar8651930 {
+ template<typename OuterT>
+ struct Outer {
+ template<typename T, typename U>
+ struct Inner;
+
+ template<typename T>
+ struct Inner<T, T> {
+ static const bool value = true;
+ };
+
+ template<typename T, typename U>
+ struct Inner {
+ static const bool value = false;
+ };
+ };
+
+ int array0[Outer<int>::Inner<int, int>::value? 1 : -1];
+ int array1[Outer<int>::Inner<int, float>::value? -1 : 1];
+}
Modified: cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp?rev=119250&r1=119249&r2=119250&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp (original)
+++ cfe/branches/Apple/whitney/test/SemaTemplate/explicit-specialization-member.cpp Mon Nov 15 15:46:08 2010
@@ -13,11 +13,9 @@
namespace PR6161 {
template<typename _CharT>
class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \
- // expected-error{{expected class name}} \
- // expected-note{{attempt to specialize declaration here}}
+ // expected-error{{expected class name}}
{
static locale::id id; // expected-error{{use of undeclared identifier}}
};
- numpunct<char>::~numpunct(); // expected-error{{template specialization requires 'template<>'}} \
- // expected-error{{specialization of member 'PR6161::numpunct<char>::~numpunct' does not specialize an instantiated member}}
+ numpunct<char>::~numpunct(); // expected-error{{expected the class name after '~' to name a destructor}}
}
More information about the llvm-branch-commits
mailing list