[cfe-commits] r63750 - in /cfe/trunk: Driver/ include/clang/AST/ include/clang/Parse/ lib/AST/ lib/Parse/ lib/Sema/ test/Parser/

Douglas Gregor dgregor at apple.com
Wed Feb 4 11:02:07 PST 2009


Author: dgregor
Date: Wed Feb  4 13:02:06 2009
New Revision: 63750

URL: http://llvm.org/viewvc/llvm-project?rev=63750&view=rev
Log:
Basic representation of C++ class templates, from Andrew Sutton.

Added:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/DeclTemplate.cpp
Modified:
    cfe/trunk/Driver/ASTConsumers.cpp
    cfe/trunk/include/clang/AST/AST.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/DeclNodes.def
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/CMakeLists.txt
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclSerialization.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/Parser/cxx-template-decl.cpp

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Wed Feb  4 13:02:06 2009
@@ -52,6 +52,8 @@
     void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
     void PrintObjCPropertyDecl(ObjCPropertyDecl *PD);
     void PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID);
+
+    void PrintTemplateDecl(TemplateDecl *TD);
   };
 } // end anonymous namespace
 
@@ -116,6 +118,8 @@
     Out << "};\n";
   } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
     Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\n";
+  } else if (TemplateDecl *TempD = dyn_cast<TemplateDecl>(D)) {
+    PrintTemplateDecl(TempD);
   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
     PrintLinkageSpec(LSD);
   } else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
@@ -437,6 +441,17 @@
     Out << "=" << PID->getPropertyIvarDecl()->getNameAsString();
   Out << ";\n";
 }
+
+/// PrintTemplateParams - Print a template parameter list and recursively print
+/// it's underlying top-level definition.
+void DeclPrinter::PrintTemplateDecl(TemplateDecl *TD) {
+  // TODO: Write template parameters.
+  Out << "template <...> ";
+  PrintDecl(TD->getTemplatedDecl());
+}
+
+
+
 //===----------------------------------------------------------------------===//
 /// ASTPrinter - Pretty-printer of ASTs
 

Modified: cfe/trunk/include/clang/AST/AST.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/AST.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/AST.h (original)
+++ cfe/trunk/include/clang/AST/AST.h Wed Feb  4 13:02:06 2009
@@ -19,6 +19,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/Type.h"

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Wed Feb  4 13:02:06 2009
@@ -237,6 +237,10 @@
       return IDNS_Tag;
 
     case Namespace:
+    case Template:
+    case FunctionTemplate:
+    case ClassTemplate:
+    case TemplateTemplateParm:
       return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
     }
   }

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Feb  4 13:02:06 2009
@@ -24,70 +24,6 @@
 class CXXConversionDecl;
 class CXXMethodDecl;
 
-/// TemplateTypeParmDecl - Declaration of a template type parameter,
-/// e.g., "T" in
-/// @code
-/// template<typename T> class vector;
-/// @endcode
-class TemplateTypeParmDecl : public TypeDecl {
-  /// Typename - Whether this template type parameter was declaration
-  /// with the 'typename' keyword. If false, it was declared with the
-  /// 'class' keyword.
-  bool Typename : 1;
-
-  TemplateTypeParmDecl(DeclContext *DC, SourceLocation L,
-                       IdentifierInfo *Id, bool Typename)
-    : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename) { }
-
-public:
-  static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
-                                      SourceLocation L, IdentifierInfo *Id,
-                                      bool Typename);
-
-  /// wasDeclarationWithTypename - Whether this template type
-  /// parameter was declared with the 'typename' keyword. If not, it
-  /// was declared with the 'class' keyword.
-  bool wasDeclaredWithTypename() const { return Typename; }
-
-  // Implement isa/cast/dyncast/etc.
-  static bool classof(const Decl *D) { 
-    return D->getKind() == TemplateTypeParm; 
-  }
-  static bool classof(const TemplateTypeParmDecl *D) { return true; }
-
-protected:
-  /// EmitImpl - Serialize this TemplateTypeParmDecl.  Called by Decl::Emit.
-  virtual void EmitImpl(llvm::Serializer& S) const;
-  
-  /// CreateImpl - Deserialize a TemplateTypeParmDecl.  Called by Decl::Create.
-  static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
-  
-  friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);  
-};
-
-/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
-/// e.g., "Size" in 
-/// @code
-/// template<int Size> class array { };
-/// @endcode
-class NonTypeTemplateParmDecl : public VarDecl {
-  NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, 
-                          IdentifierInfo *Id, QualType T,
-                          SourceLocation TSSL = SourceLocation())
-    : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL) { }
-
-public:
-  static NonTypeTemplateParmDecl *
-  Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
-         QualType T, SourceLocation TypeSpecStartLoc = SourceLocation());
-
-  // Implement isa/cast/dyncast/etc.
-  static bool classof(const Decl *D) {
-    return D->getKind() == NonTypeTemplateParm;
-  }
-  static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
-};
-
 /// OverloadedFunctionDecl - An instance of this class represents a
 /// set of overloaded functions. All of the functions have the same
 /// name and occur within the same scope.
@@ -1024,34 +960,6 @@
   friend class DeclContext;
 };
 
-/// TemplateParameterList - Stores a list of template parameters. 
-class TemplateParameterList {
-  /// NumParams - The number of template parameters in this template
-  /// parameter list. 
-  unsigned NumParams;
-
-  TemplateParameterList(Decl **Params, unsigned NumParams);
-
-public:
-  static TemplateParameterList *Create(ASTContext &C, Decl **Params, 
-                                       unsigned NumParams);
-
-  /// iterator - Iterates through the template parameters in this list.
-  typedef Decl** iterator;
-
-  /// const_iterator - Iterates through the template parameters in this list.
-  typedef Decl* const* const_iterator;
-
-  iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
-  const_iterator begin() const { 
-    return reinterpret_cast<Decl * const *>(this + 1); 
-  }
-  iterator end() { return begin() + NumParams; }
-  const_iterator end() const { return begin() + NumParams; }
-
-  unsigned size() const { return NumParams; }
-};
-
 } // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/AST/DeclNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclNodes.def?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclNodes.def (original)
+++ cfe/trunk/include/clang/AST/DeclNodes.def Wed Feb  4 13:02:06 2009
@@ -97,6 +97,10 @@
       DECL(ParmVar, VarDecl)
         DECL(OriginalParmVar, ParmVarDecl)
       DECL(NonTypeTemplateParm, VarDecl)
+  DECL(Template, NamedDecl)
+    DECL(FunctionTemplate, TemplateDecl)
+    DECL(ClassTemplate, TemplateDecl)
+    DECL(TemplateTemplateParm, TemplateDecl)
   DECL(ObjCMethod, NamedDecl)
   DECL(ObjCContainer, NamedDecl)
     DECL(ObjCCategory, ObjCContainerDecl)
@@ -139,6 +143,7 @@
 DECL_RANGE(Record, Record, CXXRecord)
 DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm)
 DECL_RANGE(Function, Function, CXXConversion)
+DECL_RANGE(Template, Template, TemplateTemplateParm)
 LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm)
 
 #undef LAST_DECL_RANGE

Added: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=63750&view=auto

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (added)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Wed Feb  4 13:02:06 2009
@@ -0,0 +1,325 @@
+//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the C++ template declaration subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
+#define LLVM_CLANG_AST_DECLTEMPLATE_H
+
+namespace clang {
+
+class TemplateParameterList;
+class TemplateDecl;
+class FunctionTemplateDecl;
+class ClassTemplateDecl;
+class TemplateTypeParmDecl;
+class NonTypeTemplateParmDecl;
+class TemplateTemplateParmDecl;
+
+/// TemplateParameterList - Stores a list of template parameters for a
+/// TemplateDecl and its derived classes.
+class TemplateParameterList {
+  /// NumParams - The number of template parameters in this template
+  /// parameter list.
+  unsigned NumParams;
+
+  TemplateParameterList(Decl **Params, unsigned NumParams);
+
+public:
+  static TemplateParameterList *Create(ASTContext &C, Decl **Params,
+                                       unsigned NumParams);
+
+  /// iterator - Iterates through the template parameters in this list.
+  typedef Decl** iterator;
+
+  /// const_iterator - Iterates through the template parameters in this list.
+  typedef Decl* const* const_iterator;
+
+  iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
+  const_iterator begin() const {
+    return reinterpret_cast<Decl * const *>(this + 1);
+  }
+  iterator end() { return begin() + NumParams; }
+  const_iterator end() const { return begin() + NumParams; }
+
+  unsigned size() const { return NumParams; }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Templates
+//===----------------------------------------------------------------------===//
+
+/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
+/// class, function, etc.). The TemplateDecl class stores the list of template
+/// parameters and a reference to the templated scoped declaration: the
+/// underlying AST node.
+class TemplateDecl : public NamedDecl {
+protected:
+  // This is probably never used.
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+               DeclarationName Name)
+    : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0)
+  { }
+
+  // Construct a template decl with the given name and parameters.
+  // Used when there is not templated element (tt-params, alias?).
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+               DeclarationName Name, TemplateParameterList *Params)
+    : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params)
+  { }
+
+  // Construct a template decl with name, parameters, and templated element.
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+               DeclarationName Name, TemplateParameterList *Params,
+               NamedDecl *Decl)
+    : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
+      TemplateParams(Params) { }
+public:
+  ~TemplateDecl();
+
+  /// Get the list of template parameters
+  TemplateParameterList *GetTemplateParameters() const {
+    return TemplateParams;
+  }
+
+  /// Get the underlying, templated declaration.
+  NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) {
+      return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast;
+  }
+  static bool classof(const TemplateDecl *D) { return true; }
+  static bool classof(const FunctionTemplateDecl *D) { return true; }
+  static bool classof(const ClassTemplateDecl *D) { return true; }
+  static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+
+protected:
+  NamedDecl *TemplatedDecl;
+  TemplateParameterList* TemplateParams;
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public TemplateDecl {
+protected:
+  FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+                       TemplateParameterList *Params, NamedDecl *Decl)
+    : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+public:
+  /// Get the underling function declaration of the template.
+  FunctionDecl *getTemplatedDecl() const {
+    return static_cast<FunctionDecl*>(TemplatedDecl);
+  }
+
+  /// Create a template function node.
+  static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+                                      SourceLocation L,
+                                      DeclarationName Name,
+                                      TemplateParameterList *Params,
+                                      NamedDecl *Decl);
+
+  // Implement isa/cast/dyncast support
+  static bool classof(const Decl *D)
+  { return D->getKind() == FunctionTemplate; }
+  static bool classof(const FunctionTemplateDecl *D)
+  { return true; }
+};
+
+/// Declaration of a template class.
+class ClassTemplateDecl : public TemplateDecl {
+protected:
+  ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+                    TemplateParameterList *Params, NamedDecl *Decl)
+    : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
+public:
+  /// Get the underlying class declarations of the template.
+  CXXRecordDecl *getTemplatedDecl() const {
+    return static_cast<CXXRecordDecl*>(TemplatedDecl);
+  }
+
+  /// Create a class teplate node.
+  static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+                                   SourceLocation L,
+                                   DeclarationName Name,
+                                   TemplateParameterList *Params,
+                                   NamedDecl *Decl);
+
+  // Implement isa/cast/dyncast support
+  static bool classof(const Decl *D)
+  { return D->getKind() == ClassTemplate; }
+  static bool classof(const ClassTemplateDecl *D)
+  { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Template Parameters
+//===----------------------------------------------------------------------===//
+
+
+/// The TemplateParmPosition class defines the position of a template parameter
+/// within a template parameter list. Because template parameter can be listed
+/// sequentially for out-of-line template members, each template parameter is
+/// given a Depth - the nesting of template parameter scopes - and a Position -
+/// the occurrence within the parameter list.
+/// This class is inheritedly privately by different kinds of template
+/// parameters and is not part of the Decl hierarchy. Just a facility.
+class TemplateParmPosition
+{
+protected:
+  // FIXME: This should probably never be called, but it's here as
+  TemplateParmPosition()
+    : Depth(0), Position(0)
+  { /* assert(0 && "Cannot create positionless template parameter"); */ }
+
+  TemplateParmPosition(unsigned D, unsigned P)
+    : Depth(D), Position(P)
+  { }
+
+  // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
+  // position? Maybe?
+  unsigned Depth;
+  unsigned Position;
+
+public:
+  /// Get the nesting depth of the template parameter.
+  unsigned getDepth() const { return Depth; }
+
+  /// Get the position of the template parameter within its parameter list.
+  unsigned getPosition() const { return Position; }
+};
+
+/// TemplateTypeParmDecl - Declaration of a template type parameter,
+/// e.g., "T" in
+/// @code
+/// template<typename T> class vector;
+/// @endcode
+class TemplateTypeParmDecl
+  : public TypeDecl, protected TemplateParmPosition {
+  /// Typename - Whether this template type parameter was declaration
+  /// with the 'typename' keyword. If false, it was declared with the
+  /// 'class' keyword.
+  bool Typename : 1;
+
+  TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+                       unsigned P, IdentifierInfo *Id, bool Typename)
+    : TypeDecl(TemplateTypeParm, DC, L, Id), TemplateParmPosition(D, P),
+      Typename(Typename) { }
+public:
+  static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
+                                      SourceLocation L, unsigned D, unsigned P,
+                                      IdentifierInfo *Id, bool Typename);
+
+  /// wasDeclarationWithTypename - Whether this template type
+  /// parameter was declared with the 'typename' keyword. If not, it
+  /// was declared with the 'class' keyword.
+  bool wasDeclaredWithTypename() const { return Typename; }
+
+  using TemplateParmPosition::getDepth;
+  using TemplateParmPosition::getPosition;
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) {
+    return D->getKind() == TemplateTypeParm;
+  }
+  static bool classof(const TemplateTypeParmDecl *D) { return true; }
+
+protected:
+  /// EmitImpl - Serialize this TemplateTypeParmDecl.  Called by Decl::Emit.
+  virtual void EmitImpl(llvm::Serializer& S) const;
+
+  /// CreateImpl - Deserialize a TemplateTypeParmDecl.  Called by Decl::Create.
+  static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+
+  friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
+/// e.g., "Size" in
+/// @code
+/// template<int Size> class array { };
+/// @endcode
+class NonTypeTemplateParmDecl
+  : public VarDecl, protected TemplateParmPosition {
+  NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
+                          unsigned P, IdentifierInfo *Id, QualType T,
+                          SourceLocation TSSL = SourceLocation())
+    : VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL),
+      TemplateParmPosition(D, P) { }
+public:
+  static NonTypeTemplateParmDecl *
+  Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+         unsigned P, IdentifierInfo *Id, QualType T,
+         SourceLocation TypeSpecStartLoc = SourceLocation());
+
+  using TemplateParmPosition::getDepth;
+  using TemplateParmPosition::getPosition;
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) {
+    return D->getKind() == NonTypeTemplateParm;
+  }
+  static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
+
+protected:
+  /// EmitImpl - Serialize this TemplateTypeParmDecl.  Called by Decl::Emit.
+  virtual void EmitImpl(llvm::Serializer& S) const;
+
+  /// CreateImpl - Deserialize a TemplateTypeParmDecl.  Called by Decl::Create.
+  static NonTypeTemplateParmDecl* CreateImpl(llvm::Deserializer& D,
+                                             ASTContext& C);
+
+  friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+/// TemplateTemplateParmDecl - Declares a template template parameter,
+/// e.g., "T" in
+/// @code
+/// template <template <typename> class T> class container { };
+/// @endcode
+/// A template template parameter is a TemplateDecl because it defines the
+/// name of a template and the template parameters allowable for substitution.
+class TemplateTemplateParmDecl
+  : public TemplateDecl, protected TemplateParmPosition {
+  TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+                           unsigned D, unsigned P,
+                           IdentifierInfo *Id, TemplateParameterList *Params)
+    : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+      TemplateParmPosition(D, P)
+    { }
+public:
+  static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
+                                          SourceLocation L, unsigned D,
+                                          unsigned P, IdentifierInfo *Id,
+                                          TemplateParameterList *Params);
+
+  using TemplateParmPosition::getDepth;
+  using TemplateParmPosition::getPosition;
+
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) {
+    return D->getKind() == TemplateTemplateParm;
+  }
+  static bool classof(const TemplateTemplateParmDecl *D) { return true; }
+
+protected:
+  /// EmitImpl - Serialize this TemplateTypeParmDecl.  Called by Decl::Emit.
+  virtual void EmitImpl(llvm::Serializer& S) const;
+
+  /// CreateImpl - Deserialize a TemplateTypeParmDecl.  Called by Decl::Create.
+  static TemplateTemplateParmDecl* CreateImpl(llvm::Deserializer& D,
+                                              ASTContext& C);
+
+  friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
+};
+
+} /* end of namespace clang */
+
+#endif

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Feb  4 13:02:06 2009
@@ -31,6 +31,8 @@
   class Type;
   class TypedefDecl;
   class TemplateTypeParmDecl;
+  class NonTypeTemplateParmDecl;
+  class TemplateTemplateParamDecl;
   class TagDecl;
   class RecordDecl;
   class CXXRecordDecl;

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Feb  4 13:02:06 2009
@@ -1019,16 +1019,16 @@
   /// (otherwise, "class" was used), and KeyLoc is the location of the
   /// "class" or "typename" keyword. ParamName is the name of the
   /// parameter (NULL indicates an unnamed template parameter) and
-  /// ParamName is the location of the parameter name (if any). 
+  /// ParamNameLoc is the location of the parameter name (if any).
   /// If the type parameter has a default argument, it will be added
   /// later via ActOnTypeParameterDefault. Depth and Position provide
   /// the number of enclosing templates (see
   /// ActOnTemplateParameterList) and the number of previous
   /// parameters within this template parameter list.
-  virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, 
-				     SourceLocation KeyLoc,
-				     IdentifierInfo *ParamName,
-				     SourceLocation ParamNameLoc,
+  virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
+                                     SourceLocation KeyLoc,
+                                     IdentifierInfo *ParamName,
+                                     SourceLocation ParamNameLoc,
                                      unsigned Depth, unsigned Position) {
     return 0;
   }
@@ -1041,8 +1041,8 @@
   /// ActOnNonTypeTemplateParameter - Called when a C++ non-type
   /// template parameter (e.g., "int Size" in "template<int Size>
   /// class Array") has been parsed. S is the current scope and D is
-  /// the parsed declarator. Depth and Position provide           
-  /// the number of enclosing templates (see
+  /// the parsed declarator. Depth and Position provide the number of
+  /// enclosing templates (see
   /// ActOnTemplateParameterList) and the number of previous
   /// parameters within this template parameter list.
   virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
@@ -1051,6 +1051,22 @@
     return 0;
   }
 
+  /// ActOnTemplateTemplateParameter - Called when a C++ template template
+  /// parameter (e.g., "int T" in "template<template <typename> class T> class
+  /// Array") has been parsed. TmpLoc is the location of the "template" keyword,
+  /// TemplateParams is the sequence of parameters required by the template,
+  /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc
+  /// is the source location of the identifier (if given).
+  virtual DeclTy *ActOnTemplateTemplateParameter(Scope *S,
+                                                 SourceLocation TmpLoc,
+                                                 TemplateParamsTy *Params,
+                                                 IdentifierInfo *ParamName,
+                                                 SourceLocation ParamNameLoc,
+                                                 unsigned Depth,
+                                                 unsigned Position) {
+    return 0;
+  }
+
   /// ActOnTemplateParameterList - Called when a complete template
   /// parameter list has been parsed, e.g.,
   ///
@@ -1090,6 +1106,7 @@
     return 0;
   }
 
+  
   //===----------------------- Obj-C Declarations -------------------------===//
   
   // ActOnStartClassInterface - this action is called immediately after parsing

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Feb  4 13:02:06 2009
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/TargetInfo.h"

Modified: cfe/trunk/lib/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt (original)
+++ cfe/trunk/lib/AST/CMakeLists.txt Wed Feb  4 13:02:06 2009
@@ -13,6 +13,7 @@
   DeclGroup.cpp
   DeclObjC.cpp
   DeclSerialization.cpp
+  DeclTemplate.cpp
   ExprConstant.cpp
   Expr.cpp
   ExprCXX.cpp

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Feb  4 13:02:06 2009
@@ -13,8 +13,9 @@
 
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/DenseMap.h"

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Feb  4 13:02:06 2009
@@ -21,36 +21,6 @@
 // Decl Allocation/Deallocation Method Implementations
 //===----------------------------------------------------------------------===//
 
-TemplateTypeParmDecl *
-TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
-                             SourceLocation L, IdentifierInfo *Id,
-                             bool Typename) {
-  return new (C) TemplateTypeParmDecl(DC, L, Id, Typename);
-}
-
-NonTypeTemplateParmDecl *
-NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, 
-                                SourceLocation L, IdentifierInfo *Id,
-                                QualType T, SourceLocation TypeSpecStartLoc) {
-  return new (C) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
-}
-
-TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams)
-  : NumParams(NumParams) {
-  for (unsigned Idx = 0; Idx < NumParams; ++Idx)
-    begin()[Idx] = Params[Idx];
-}
-
-TemplateParameterList *
-TemplateParameterList::Create(ASTContext &C, Decl **Params, 
-                              unsigned NumParams) {
-  // FIXME: how do I pass in Size to ASTContext::new?
-  unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
-  unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
-  void *Mem = C.Allocate(Size, Align);
-  return new (Mem) TemplateParameterList(Params, NumParams);
-}
-
 CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
                              SourceLocation L, IdentifierInfo *Id) 
   : RecordDecl(CXXRecord, TK, DC, L, Id),

Modified: cfe/trunk/lib/AST/DeclSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclSerialization.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclSerialization.cpp (original)
+++ cfe/trunk/lib/AST/DeclSerialization.cpp Wed Feb  4 13:02:06 2009
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "llvm/Bitcode/Serialize.h"
 #include "llvm/Bitcode/Deserialize.h"
@@ -597,15 +598,60 @@
 //===----------------------------------------------------------------------===//
 
 void TemplateTypeParmDecl::EmitImpl(Serializer& S) const {
+  S.EmitInt(Depth);
+  S.EmitInt(Position);
   S.EmitBool(Typename);
   NamedDecl::EmitInRec(S);
 }
 
 TemplateTypeParmDecl *
 TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) {
+  unsigned Depth = D.ReadInt();
+  unsigned Position = D.ReadInt();
   bool Typename = D.ReadBool();
   TemplateTypeParmDecl *decl
-    = new (C) TemplateTypeParmDecl(0, SourceLocation(), NULL, Typename);
+    = new (C) TemplateTypeParmDecl(0, SourceLocation(), Depth, Position,
+                                   0, Typename);
+  decl->NamedDecl::ReadInRec(D, C);
+  return decl;
+}
+
+//===----------------------------------------------------------------------===//
+//      NonTypeTemplateParmDecl Serialization.
+//===----------------------------------------------------------------------===//
+void NonTypeTemplateParmDecl::EmitImpl(Serializer& S) const {
+  S.EmitInt(Depth);
+  S.EmitInt(Position);
+  NamedDecl::Emit(S);
+}
+
+NonTypeTemplateParmDecl*
+NonTypeTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) {
+  unsigned Depth = D.ReadInt();
+  unsigned Position = D.ReadInt();
+  NonTypeTemplateParmDecl *decl
+    = new (C) NonTypeTemplateParmDecl(0, SourceLocation(), Depth, Position,
+                                      0, QualType(), SourceLocation());
+  decl->NamedDecl::ReadInRec(D, C);
+  return decl;
+}
+
+//===----------------------------------------------------------------------===//
+//      TemplateTemplateParmDecl Serialization.
+//===----------------------------------------------------------------------===//
+void TemplateTemplateParmDecl::EmitImpl(Serializer& S) const {
+  S.EmitInt(Depth);
+  S.EmitInt(Position);
+  NamedDecl::EmitInRec(S);
+}
+
+TemplateTemplateParmDecl*
+TemplateTemplateParmDecl::CreateImpl(Deserializer& D, ASTContext& C) {
+  unsigned Depth = D.ReadInt();
+  unsigned Position = D.ReadInt();
+  TemplateTemplateParmDecl *decl
+    = new (C) TemplateTemplateParmDecl(0, SourceLocation(), Depth, Position,
+                                       0, 0);
   decl->NamedDecl::ReadInRec(D, C);
   return decl;
 }

Added: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=63750&view=auto

==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (added)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Wed Feb  4 13:02:06 2009
@@ -0,0 +1,108 @@
+//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the C++ related Decl classes for templates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/STLExtras.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TemplateParameterList Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams)
+  : NumParams(NumParams) {
+  for (unsigned Idx = 0; Idx < NumParams; ++Idx)
+    begin()[Idx] = Params[Idx];
+}
+
+TemplateParameterList *
+TemplateParameterList::Create(ASTContext &C, Decl **Params,
+                              unsigned NumParams) {
+  unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
+  unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
+  void *Mem = C.Allocate(Size, Align);
+  return new (Mem) TemplateParameterList(Params, NumParams);
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateDecl::~TemplateDecl() {
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
+                                                   DeclContext *DC,
+                                                   SourceLocation L,
+                                                   DeclarationName Name,
+                                                   TemplateParameterList *Params,
+                                                   NamedDecl *Decl) {
+  return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
+}
+
+//===----------------------------------------------------------------------===//
+// ClassTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
+                                             DeclContext *DC,
+                                             SourceLocation L,
+                                             DeclarationName Name,
+                                             TemplateParameterList *Params,
+                                             NamedDecl *Decl) {
+  return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateTypeParm Allocation/Deallocation Method Implementations
+//===----------------------------------------------------------------------===//
+
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
+                             SourceLocation L, unsigned D, unsigned P,
+                             IdentifierInfo *Id, bool Typename) {
+  return new (C) TemplateTypeParmDecl(DC, L, D, P, Id, Typename);
+}
+
+//===----------------------------------------------------------------------===//
+// NonTypeTemplateParmDecl Method Implementations
+//===----------------------------------------------------------------------===//
+
+NonTypeTemplateParmDecl *
+NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
+                                SourceLocation L, unsigned D, unsigned P,
+                                IdentifierInfo *Id, QualType T,
+                                SourceLocation TypeSpecStartLoc) {
+  return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T,
+                                         TypeSpecStartLoc);
+}
+
+//===----------------------------------------------------------------------===//
+// TemplateTemplateParmDecl Method Implementations
+//===----------------------------------------------------------------------===//
+
+TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
+                                 SourceLocation L, unsigned D, unsigned P,
+                                 IdentifierInfo *Id,
+                                 TemplateParameterList *Params) {
+  return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
+}
+

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Feb  4 13:02:06 2009
@@ -16,6 +16,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/TargetInfo.h"

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Feb  4 13:02:06 2009
@@ -15,6 +15,7 @@
 #include "clang/AST/Type.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "llvm/ADT/StringExtras.h"
 

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Feb  4 13:02:06 2009
@@ -1726,7 +1726,7 @@
 
         // If this identifier is followed by a '<', we may have a template-id.
         DeclTy *Template;
-        if (NextToken().is(tok::less) &&
+        if (getLang().CPlusPlus && NextToken().is(tok::less) &&
             (Template = Actions.isTemplateName(*Tok.getIdentifierInfo(), 
                                                CurScope))) {
           IdentifierInfo *II = Tok.getIdentifierInfo();

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Feb  4 13:02:06 2009
@@ -345,8 +345,8 @@
     return;
   }
 
-  // Parse the tag portion of this.
-  DeclTy *TagDecl 
+  // Create the tag portion of the class, possibly resulting in a template.
+  DeclTy *TagOrTempDecl
     = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
                        NameLoc, Attr,
                        Action::MultiTemplateParamsArg(
@@ -356,15 +356,15 @@
 
   // Parse the optional base clause (C++ only).
   if (getLang().CPlusPlus && Tok.is(tok::colon)) {
-    ParseBaseClause(TagDecl);
+    ParseBaseClause(TagOrTempDecl);
   }
 
   // If there is a body, parse it and inform the actions module.
   if (Tok.is(tok::l_brace))
     if (getLang().CPlusPlus)
-      ParseCXXMemberSpecification(StartLoc, TagType, TagDecl);
+      ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempDecl);
     else
-      ParseStructUnionBody(StartLoc, TagType, TagDecl);
+      ParseStructUnionBody(StartLoc, TagType, TagOrTempDecl);
   else if (TK == Action::TK_Definition) {
     // FIXME: Complain that we have a base-specifier list but no
     // definition.
@@ -372,7 +372,7 @@
   }
 
   const char *PrevSpec = 0;
-  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
+  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl))
     Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
 }
 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed Feb  4 13:02:06 2009
@@ -39,7 +39,7 @@
   //
   // We parse multiple levels non-recursively so that we can build a
   // single data structure containing all of the template parameter
-  // lists, and easily differentiate between the case above and:
+  // lists easily differentiate between the case above and:
   //
   //   template<typename T>
   //   class A {
@@ -82,19 +82,16 @@
   } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
   // Parse the actual template declaration.
-  DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists);
-
-  return TemplateDecl;
+  return ParseDeclarationOrFunctionDefinition(&ParamLists);
 }
 
 /// ParseTemplateParameters - Parses a template-parameter-list enclosed in
-/// angle brackets. Depth is the depth of this
-/// template-parameter-list, which is the number of template headers
-/// directly enclosing this template header. TemplateParams is the
-/// current list of template parameters we're building. The template
-/// parameter we parse will be added to this list. LAngleLoc and
-/// RAngleLoc will receive the positions of the '<' and '>',
-/// respectively, that enclose this template parameter list.
+/// angle brackets. Depth is the depth of this template-parameter-list, which
+/// is the number of template headers directly enclosing this template header.
+/// TemplateParams is the current list of template parameters we're building.
+/// The template parameter we parse will be added to this list. LAngleLoc and
+/// RAngleLoc will receive the positions of the '<' and '>', respectively, 
+/// that enclose this template parameter list.
 bool Parser::ParseTemplateParameters(unsigned Depth,
                                      TemplateParameterList &TemplateParams,
                                      SourceLocation &LAngleLoc,
@@ -223,8 +220,8 @@
     return 0;
   }
   
-  DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, 
-						 KeyLoc, ParamName, NameLoc,
+  DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
+                                                 KeyLoc, ParamName, NameLoc,
                                                  Depth, Position);
 
   // Grab a default type id (if given).
@@ -251,7 +248,7 @@
   SourceLocation TemplateLoc = ConsumeToken();
   TemplateParameterList TemplateParams; 
   SourceLocation LParenLoc, RParenLoc;
-  if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
+  if(!ParseTemplateParameters(Depth + 1, TemplateParams, LParenLoc,
                               RParenLoc)) {
     return 0;
   }
@@ -266,10 +263,11 @@
   SourceLocation ClassLoc = ConsumeToken();
 
   // Get the identifier, if given.
-  IdentifierInfo* ident = 0;
+  SourceLocation NameLoc;
+  IdentifierInfo* ParamName = 0;
   if(Tok.is(tok::identifier)) {
-    ident = Tok.getIdentifierInfo();
-    ConsumeToken();
+    ParamName = Tok.getIdentifierInfo();
+    NameLoc = ConsumeToken();
   } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
     // Unnamed template parameter. Don't have to do anything here, just
     // don't consume this token.
@@ -279,6 +277,8 @@
   }
 
   // Get the a default value, if given.
+  // FIXME: I think that the results of this block need to be passed to the
+  // act-on call, so we can assemble the parameter correctly.
   OwningExprResult DefaultExpr(Actions);
   if(Tok.is(tok::equal)) {
     ConsumeToken();
@@ -288,8 +288,9 @@
     }
   }
 
-  // FIXME: Add an action for template template parameters.
-  return 0;
+  return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
+                                                &TemplateParams, ParamName,
+                                                NameLoc, Depth, Position);
 }
 
 /// ParseNonTypeTemplateParameter - Handle the parsing of non-type

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Feb  4 13:02:06 2009
@@ -379,7 +379,6 @@
   case tok::kw_export:    // As in 'export template'
     // A function definition cannot start with a these keywords.
     return ParseDeclaration(Declarator::FileContext);
-       
   default:
     // We can't tell whether this is a function-definition or declaration yet.
     return ParseDeclarationOrFunctionDefinition();

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb  4 13:02:06 2009
@@ -60,6 +60,7 @@
   class SwitchStmt;
   class ExtVectorType;
   class TypedefDecl;
+  class TemplateDecl;
   class ObjCInterfaceDecl;
   class ObjCCompatibleAliasDecl;
   class ObjCProtocolDecl;
@@ -1479,14 +1480,23 @@
   virtual DeclTy *isTemplateName(IdentifierInfo &II, Scope *S,
                                  const CXXScopeSpec *SS = 0);
   bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
-  virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, 
-				     SourceLocation KeyLoc,
-				     IdentifierInfo *ParamName,
-				     SourceLocation ParamNameLoc,
+  TemplateDecl *AdjustDeclIfTemplate(DeclTy *&Decl);
+
+  virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
+                                     SourceLocation KeyLoc,
+                                     IdentifierInfo *ParamName,
+                                     SourceLocation ParamNameLoc,
                                      unsigned Depth, unsigned Position);
   virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
-                                                unsigned Depth, 
+                                                unsigned Depth,
                                                 unsigned Position);
+  virtual DeclTy *ActOnTemplateTemplateParameter(Scope *S,
+                                                 SourceLocation TmpLoc,
+                                                 TemplateParamsTy *Params,
+                                                 IdentifierInfo *ParamName,
+                                                 SourceLocation ParamNameLoc,
+                                                 unsigned Depth,
+                                                 unsigned Position);
   virtual TemplateParamsTy *
   ActOnTemplateParameterList(unsigned Depth,
                              SourceLocation ExportLoc,
@@ -1495,6 +1505,7 @@
                              DeclTy **Params, unsigned NumParams,
                              SourceLocation RAngleLoc);
   
+
   // Objective-C declarations.
   virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
                                            IdentifierInfo *ClassName,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb  4 13:02:06 2009
@@ -16,6 +16,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/TargetInfo.h"
@@ -1170,7 +1171,7 @@
   // The scope passed in may not be a decl scope.  Zip up the scope tree until
   // we find one that is.
   while ((S->getFlags() & Scope::DeclScope) == 0 ||
-        (S->getFlags() & Scope::TemplateParamScope) != 0)
+         (S->getFlags() & Scope::TemplateParamScope) != 0)
     S = S->getParent();
   
   DeclContext *DC;
@@ -2778,6 +2779,9 @@
 /// former case, Name will be non-null.  In the later case, Name will be null.
 /// TagSpec indicates what kind of tag this is. TK indicates whether this is a
 /// reference/declaration/definition of a tag.
+///
+/// This creates and returns template declarations if any template parameter
+/// lists are given.
 Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
                              SourceLocation KWLoc, const CXXScopeSpec &SS,
                              IdentifierInfo *Name, SourceLocation NameLoc,
@@ -2786,7 +2790,12 @@
   // If this is not a definition, it must have a name.
   assert((Name != 0 || TK == TK_Definition) &&
          "Nameless record must be a definition!");
-  
+  assert((TemplateParameterLists.size() == 0 || TK != TK_Reference) &&
+         "Can't have a reference to a template");
+  assert((TemplateParameterLists.size() == 0 || 
+          TagSpec != DeclSpec::TST_enum) &&
+         "No such thing as an enum template");
+
   TagDecl::TagKind Kind;
   switch (TagSpec) {
   default: assert(0 && "Unknown tag type!");
@@ -2799,6 +2808,7 @@
   DeclContext *SearchDC = CurContext;
   DeclContext *DC = CurContext;
   NamedDecl *PrevDecl = 0;
+  TemplateDecl *PrevTemplate = 0;
 
   bool Invalid = false;
 
@@ -2863,6 +2873,11 @@
   }
 
   if (PrevDecl) {    
+    // If we found a template, keep track of the template and its
+    // underlying declaration.
+    if ((PrevTemplate = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl)))
+      PrevDecl = PrevTemplate->getTemplatedDecl();
+
     if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
       // If this is a use of a previous tag, or if the tag is already declared
       // in the same scope (so that the definition/declaration completes or
@@ -2877,6 +2892,7 @@
           Name = 0;
           PrevDecl = 0;
           Invalid = true;
+          // FIXME: Add template/non-template redecl check
         } else {
           // If this is a use, just return the declaration we found.
 
@@ -2886,7 +2902,7 @@
           // need to be changed with DeclGroups.
           if (TK == TK_Reference)
             return PrevDecl;
-          
+
           // Diagnose attempts to redefine a tag.
           if (TK == TK_Definition) {
             if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {
@@ -2990,6 +3006,7 @@
   // declaration of the same entity, the two will be linked via
   // PrevDecl.
   TagDecl *New;
+  ClassTemplateDecl *NewTemplate = 0;
 
   if (Kind == TagDecl::TK_enum) {
     // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
@@ -3003,11 +3020,28 @@
 
     // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
     // struct X { int A; } D;    D should chain to X.
-    if (getLangOptions().CPlusPlus)
+    if (getLangOptions().CPlusPlus) {
       // FIXME: Look for a way to use RecordDecl for simple structs.
       New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
                                   cast_or_null<CXXRecordDecl>(PrevDecl));
-    else
+
+      // If there's are template parameters, then this must be a class
+      // template. Create the template decl node also.
+      // FIXME: Do we always create template decls? We may not for forward
+      // declarations.
+      // FIXME: What are we actually going to do with the template decl?
+      if (TemplateParameterLists.size() > 0) {
+        // FIXME: The allocation of the parameters is probably incorrect.
+        // FIXME: Does the TemplateDecl have the same name as the class?
+        TemplateParameterList *Params =
+          TemplateParameterList::Create(Context,
+                                        (Decl **)TemplateParameterLists.get(),
+                                        TemplateParameterLists.size());
+        NewTemplate = ClassTemplateDecl::Create(Context, DC, Loc,
+                                                DeclarationName(Name), Params,
+                                                New);
+      }
+    } else
       New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
                                cast_or_null<RecordDecl>(PrevDecl));
   }
@@ -3080,6 +3114,7 @@
 }
 
 void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) {
+  AdjustDeclIfTemplate(TagD);
   TagDecl *Tag = cast<TagDecl>((Decl *)TagD);
 
   // Enter the tag context.
@@ -3105,6 +3140,7 @@
 }
 
 void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
+  AdjustDeclIfTemplate(TagD);
   TagDecl *Tag = cast<TagDecl>((Decl *)TagD);
 
   if (isa<CXXRecordDecl>(Tag))

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb  4 13:02:06 2009
@@ -757,6 +757,7 @@
                                              DeclTy *TagDecl,
                                              SourceLocation LBrac,
                                              SourceLocation RBrac) {
+  AdjustDeclIfTemplate(TagDecl);
   ActOnFields(S, RLoc, TagDecl,
               (DeclTy**)FieldCollector->getCurFields(),
               FieldCollector->getCurNumFields(), LBrac, RBrac, 0);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb  4 13:02:06 2009
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Basic/SourceManager.h"

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Feb  4 13:02:06 2009
@@ -536,7 +536,7 @@
     IEnd = IdResolver.end();
 
   // First we lookup local scope.
-  // We don't consider using-dirctives, as per 7.3.4.p1 [namespace.udir]
+  // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir]
   // ...During unqualified name lookup (3.4.1), the names appear as if
   // they were declared in the nearest enclosing namespace which contains
   // both the using-directive and the nominated namespace.

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Feb  4 13:02:06 2009
@@ -13,6 +13,7 @@
 
 #include "Sema.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/LangOptions.h"
 
@@ -38,6 +39,9 @@
     // FIXME: We need to represent templates via some kind of
     // TemplateDecl, because what follows is a hack that only works in
     // one specific case.
+    if (isa<TemplateDecl>(IIDecl))
+      return IIDecl;
+
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
       if (FD->getType()->isDependentType())
         return FD;
@@ -50,7 +54,6 @@
           return Ovl;
       }
     }
-    return 0;
   }
   return 0;
 }
@@ -75,6 +78,18 @@
   return true;
 }
 
+/// AdjustDeclForTemplates - If the given decl happens to be a template, reset
+/// the parameter D to reference the templated declaration and return a pointer
+/// to the template declaration. Otherwise, do nothing to D and return null.
+TemplateDecl *Sema::AdjustDeclIfTemplate(DeclTy *&D)
+{
+  if(TemplateDecl *Temp = dyn_cast<TemplateDecl>(static_cast<Decl*>(D))) {
+    D = Temp->getTemplatedDecl();
+    return Temp;
+  }
+  return 0;
+}
+
 /// ActOnTypeParameter - Called when a C++ template type parameter
 /// (e.g., "typename T") has been parsed. Typename specifies whether
 /// the keyword "typename" was used to declare the type parameter
@@ -101,8 +116,8 @@
   }
 
   TemplateTypeParmDecl *Param
-    = TemplateTypeParmDecl::Create(Context, CurContext, 
-				   ParamNameLoc, ParamName, Typename);
+    = TemplateTypeParmDecl::Create(Context, CurContext, ParamNameLoc, 
+                                   Depth, Position, ParamName, Typename);
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -124,8 +139,8 @@
                                                   unsigned Position) {
   QualType T = GetTypeForDeclarator(D, S);
 
-  assert(S->isTemplateParamScope() && 
-	 "Template type parameter not in template parameter scope!");
+  assert(S->isTemplateParamScope() &&
+         "Non-type template parameter not in template parameter scope!");
   bool Invalid = false;
 
   IdentifierInfo *ParamName = D.getIdentifier();
@@ -133,12 +148,12 @@
     NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName);
     if (PrevDecl && PrevDecl->isTemplateParameter())
       Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
-							   PrevDecl);
+                                                           PrevDecl);
   }
 
   NonTypeTemplateParmDecl *Param
     = NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(),
-				      ParamName, T);
+                                      Depth, Position, ParamName, T);
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -150,6 +165,46 @@
   return Param;
 }
 
+
+/// ActOnTemplateTemplateParameter - Called when a C++ template template
+/// parameter (e.g. T in template <template <typename> class T> class array)
+/// has been parsed. S is the current scope.
+Sema::DeclTy *Sema::ActOnTemplateTemplateParameter(Scope* S,
+                                                   SourceLocation TmpLoc,
+                                                   TemplateParamsTy *Params,
+                                                   IdentifierInfo *Name,
+                                                   SourceLocation NameLoc,
+                                                   unsigned Depth,
+                                                   unsigned Position)
+{
+  assert(S->isTemplateParamScope() &&
+         "Template template parameter not in template parameter scope!");
+
+  // Construct the parameter object.
+  TemplateTemplateParmDecl *Param =
+    TemplateTemplateParmDecl::Create(Context, CurContext, TmpLoc, Depth,
+                                     Position, Name,
+                                     (TemplateParameterList*)Params);
+
+  // Make sure the parameter is valid.
+  // FIXME: Decl object is not currently invalidated anywhere so this doesn't
+  // do anything yet. However, if the template parameter list or (eventual)
+  // default value is ever invalidated, that will propagate here.
+  bool Invalid = false;
+  if (Invalid) {
+    Param->setInvalidDecl();
+  }
+
+  // If the tt-param has a name, then link the identifier into the scope
+  // and lookup mechanisms.
+  if (Name) {
+    S->AddDecl(Param);
+    IdResolver.AddDecl(Param);
+  }
+
+  return Param;
+}
+
 /// ActOnTemplateParameterList - Builds a TemplateParameterList that
 /// contains the template parameters in Params/NumParams.
 Sema::TemplateParamsTy *
@@ -164,3 +219,4 @@
 
   return TemplateParameterList::Create(Context, (Decl**)Params, NumParams);
 }
+

Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=63750&r1=63749&r2=63750&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Wed Feb  4 13:02:06 2009
@@ -32,9 +32,9 @@
 // Forward declarations w/template template parameters
 template <template <typename> class T> class TTP1;
 template <template <typename> class> class TTP2;
-template <template <typename> class T = foo> TTP3;
-template <template <typename> class = foo> TTP3;
-template <template <typename X, typename Y> class T> TTP5;
+template <template <typename> class T = foo> class TTP3;
+template <template <typename> class = foo> class TTP3;
+template <template <typename X, typename Y> class T> class TTP5;
 
 // Forward declararations with non-type params
 template <int> class NTP0;





More information about the cfe-commits mailing list