[cfe-commits] r77925 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/AST/DeclTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/partial-spec-instantiate.cpp
Douglas Gregor
dgregor at apple.com
Sun Aug 2 16:24:31 PDT 2009
Author: dgregor
Date: Sun Aug 2 18:24:31 2009
New Revision: 77925
URL: http://llvm.org/viewvc/llvm-project?rev=77925&view=rev
Log:
Keep track of the template arguments deduced when matching a class
template partial specialization. Then, use those template arguments
when instantiating members of that class template partial
specialization. Fixes PR4607.
Added:
cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=77925&r1=77924&r2=77925&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Sun Aug 2 18:24:31 2009
@@ -869,8 +869,23 @@
/// \endcode
class ClassTemplateSpecializationDecl
: public CXXRecordDecl, public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a class template
+ /// specialization that was instantiated from a class template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The class template partial specialization from which this
+ /// class template specialization was instantiated.
+ ClassTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the class template
+ /// partial specialization itself.
+ TemplateArgumentList *TemplateArgs;
+ };
+
/// \brief The template that this specialization specializes
- ClassTemplateDecl *SpecializedTemplate;
+ llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
+ SpecializedTemplate;
/// \brief The template arguments used to describe this specialization.
TemplateArgumentList TemplateArgs;
@@ -893,11 +908,13 @@
TemplateArgumentListBuilder &Builder,
ClassTemplateSpecializationDecl *PrevDecl);
+ virtual void Destroy(ASTContext& C);
+
/// \brief Retrieve the template that this specialization specializes.
- ClassTemplateDecl *getSpecializedTemplate() const {
- return SpecializedTemplate;
- }
+ ClassTemplateDecl *getSpecializedTemplate() const;
+ /// \brief Retrieve the template arguments of the class template
+ /// specialization.
const TemplateArgumentList &getTemplateArgs() const {
return TemplateArgs;
}
@@ -912,6 +929,56 @@
SpecializationKind = TSK;
}
+ /// \brief If this class template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// class template or class template partial specialization from which it
+ /// was instantiated.
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiation)
+ return (ClassTemplateDecl*)0;
+
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization;
+
+ return const_cast<ClassTemplateDecl*>(
+ SpecializedTemplate.get<ClassTemplateDecl*>());
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate members of the class template or class template partial
+ /// specialization from which this class template specialization was
+ /// instantiated.
+ ///
+ /// \returns For a class template specialization instantiated from the primary
+ /// template, this function will return the same template arguments as
+ /// getTemplateArgs(). For a class template specialization instantiated from
+ /// a class template partial specialization, this function will return the
+ /// deduced template arguments for the class template partial specialization
+ /// itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this class template specialization is actually an
+ /// instantiation of the given class template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
+ TemplateArgumentList *TemplateArgs) {
+ SpecializedPartialSpecialization *PS
+ = new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
/// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(QualType T) {
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=77925&r1=77924&r2=77925&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Sun Aug 2 18:24:31 2009
@@ -415,6 +415,22 @@
return Result;
}
+void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ C.Deallocate(PartialSpec);
+
+ CXXRecordDecl::Destroy(C);
+}
+
+ClassTemplateDecl *
+ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
+ if (SpecializedPartialSpecialization *PartialSpec
+ = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
+ return PartialSpec->PartialSpecialization->getSpecializedTemplate();
+ return SpecializedTemplate.get<ClassTemplateDecl*>();
+}
+
//===----------------------------------------------------------------------===//
// ClassTemplatePartialSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=77925&r1=77924&r2=77925&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sun Aug 2 18:24:31 2009
@@ -32,7 +32,7 @@
// Template arguments for a class template specialization.
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(D))
- return Spec->getTemplateArgs();
+ return Spec->getTemplateInstantiationArgs();
// Template arguments for a function template specialization.
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
@@ -50,7 +50,7 @@
ClassTemplateSpecializationDecl *EnclosingTemplate
= cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
- return EnclosingTemplate->getTemplateArgs();
+ return EnclosingTemplate->getTemplateInstantiationArgs();
}
Sema::InstantiatingTemplate::
@@ -1011,6 +1011,7 @@
// instantiation is generated from that specialization.
Pattern = Matched[0].first;
TemplateArgs = Matched[0].second;
+ ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
} else if (Matched.size() > 1) {
// -- If more than one matching specialization is found, the
// partial order rules (14.5.4.2) are used to determine
Added: cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp?rev=77925&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp (added)
+++ cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp Sun Aug 2 18:24:31 2009
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only %s
+
+// PR4607
+template <class T> struct X {};
+
+template <> struct X<char>
+{
+ static char* g();
+};
+
+template <class T> struct X2 {};
+
+template <class U>
+struct X2<U*> {
+ static void f() {
+ X<U>::g();
+ }
+};
+
+void a(char *a, char *b) {X2<char*>::f();}
Propchange: cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaTemplate/partial-spec-instantiate.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list