[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