[cfe-commits] r61413 - in /cfe/trunk: Driver/PrintParserCallbacks.cpp include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h include/clang/Parse/Ownership.h include/clang/Parse/Parser.h lib/AST/DeclCXX.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/Parser/cxx-template-decl.cpp

Douglas Gregor dgregor at apple.com
Tue Dec 23 18:52:10 PST 2008


Author: dgregor
Date: Tue Dec 23 20:52:09 2008
New Revision: 61413

URL: http://llvm.org/viewvc/llvm-project?rev=61413&view=rev
Log:
Keep track of template arguments when we parse them. Right now, we don't actually do anything with the template arguments, but they'll be used to create template declarations

Modified:
    cfe/trunk/Driver/PrintParserCallbacks.cpp
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Ownership.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/DeclCXX.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/SemaTemplate.cpp
    cfe/trunk/test/Parser/cxx-template-decl.cpp

Modified: cfe/trunk/Driver/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintParserCallbacks.cpp?rev=61413&r1=61412&r2=61413&view=diff

==============================================================================
--- cfe/trunk/Driver/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/Driver/PrintParserCallbacks.cpp Tue Dec 23 20:52:09 2008
@@ -189,7 +189,8 @@
     virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                              SourceLocation KWLoc, const CXXScopeSpec &SS,
                              IdentifierInfo *Name, SourceLocation NameLoc,
-                             AttributeList *Attr) {
+                             AttributeList *Attr,
+                             MultiTemplateParamsArg TemplateParameterLists) {
       // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
       // is (struct/union/enum/class).
       llvm::cout << __FUNCTION__ << "\n";

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Dec 23 20:52:09 2008
@@ -945,6 +945,34 @@
   void ReadInRec(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// 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/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61413&r1=61412&r2=61413&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Dec 23 20:52:09 2008
@@ -976,6 +976,8 @@
      "declaration of %0 shadows template parameter")
 DIAG(note_template_param_here, NOTE,
      "template parameter is declared here")
+DIAG(note_template_export_unsupported, NOTE, 
+     "exported templates are unsupported")
 
 DIAG(err_unexpected_typedef, ERROR,
      "unexpected type name %0: expected expression")

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Dec 23 20:52:09 2008
@@ -63,6 +63,7 @@
   typedef void BaseTy;
   typedef void MemInitTy;
   typedef void CXXScopeTy;
+  typedef void TemplateParamsTy;
   typedef void TemplateArgTy;
 
   /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
@@ -90,6 +91,7 @@
   /// Multiple expressions or statements as arguments.
   typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
   typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
+  typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
   typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgArg;
 
   // Utilities for Action implementations to return smart results.
@@ -303,7 +305,8 @@
   virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                            SourceLocation KWLoc, const CXXScopeSpec &SS,
                            IdentifierInfo *Name, SourceLocation NameLoc,
-                           AttributeList *Attr) {
+                           AttributeList *Attr,
+                           MultiTemplateParamsArg TemplateParameterLists) {
     // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
     // is (struct/union/enum/class).
     return 0;
@@ -944,11 +947,15 @@
   /// parameter (NULL indicates an unnamed template parameter) and
   /// ParamName is the location of the parameter name (if any). 
   /// If the type parameter has a default argument, it will be added
-  /// later via ActOnTypeParameterDefault.
+  /// 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) {
+				     SourceLocation ParamNameLoc,
+                                     unsigned Depth, unsigned Position) {
     return 0;
   }
 
@@ -960,12 +967,54 @@
   /// 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.
-  virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) {
+  /// 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,
+                                                unsigned Depth, 
+                                                unsigned Position) {
     return 0;
   }
 
-  
+  /// ActOnTemplateParameterList - Called when a complete template
+  /// parameter list has been parsed, e.g.,
+  ///
+  /// @code
+  /// export template<typename T, T Size>
+  /// @endcode
+  ///
+  /// Depth is the number of enclosing template parameter lists. This
+  /// value does not include templates from outer scopes. For example:
+  ///
+  /// @code
+  /// template<typename T> // depth = 0
+  ///   class A {
+  ///     template<typename U> // depth = 0
+  ///       class B;
+  ///   };
+  ///
+  /// template<typename T> // depth = 0
+  ///   template<typename U> // depth = 1
+  ///     class A<T>::B { ... };
+  /// @endcode
+  ///
+  /// ExportLoc, if valid, is the position of the "export"
+  /// keyword. Otherwise, "export" was not specified. 
+  /// TemplateLoc is the position of the template keyword, LAngleLoc
+  /// is the position of the left angle bracket, and RAngleLoc is the
+  /// position of the corresponding right angle bracket.
+  /// Params/NumParams provides the template parameters that were
+  /// parsed as part of the template-parameter-list.
+  virtual TemplateParamsTy *
+  ActOnTemplateParameterList(unsigned Depth,
+                             SourceLocation ExportLoc,
+                             SourceLocation TemplateLoc, 
+                             SourceLocation LAngleLoc,
+                             DeclTy **Params, unsigned NumParams,
+                             SourceLocation RAngleLoc) {
+    return 0;
+  }
 
   //===----------------------- Obj-C Declarations -------------------------===//
   

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Ownership.h (original)
+++ cfe/trunk/include/clang/Parse/Ownership.h Tue Dec 23 20:52:09 2008
@@ -118,6 +118,7 @@
     // what types are required to be identical for the actions.
     typedef void ExprTy;
     typedef void StmtTy;
+    typedef void TemplateParamsTy;
     typedef void TemplateArgTy;
 
     /// ActionResult - This structure is used while parsing/acting on
@@ -146,6 +147,7 @@
     /// pointers need access to them.
     virtual void DeleteExpr(ExprTy *E) {}
     virtual void DeleteStmt(StmtTy *E) {}
+    virtual void DeleteTemplateParams(TemplateParamsTy *E) {}
     virtual void DeleteTemplateArg(TemplateArgTy *E) {}
   };
 

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Dec 23 20:52:09 2008
@@ -78,8 +78,11 @@
   typedef Action::BaseTy BaseTy;
   typedef Action::MemInitTy MemInitTy;
   typedef Action::CXXScopeTy CXXScopeTy;
+  typedef Action::TemplateParamsTy TemplateParamsTy;
   typedef Action::TemplateArgTy TemplateArgTy;
 
+  typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
+
   typedef Action::ExprResult        ExprResult;
   typedef Action::StmtResult        StmtResult;
   typedef Action::BaseResult        BaseResult;
@@ -500,7 +503,8 @@
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
   DeclTy *ParseExternalDeclaration();
-  DeclTy *ParseDeclarationOrFunctionDefinition();
+  DeclTy *ParseDeclarationOrFunctionDefinition(
+            TemplateParameterLists *TemplateParams = 0);
   DeclTy *ParseFunctionDefinition(Declarator &D);
   void ParseKNRParamDeclarations(Declarator &D);
   OwningExprResult ParseSimpleAsm();
@@ -751,9 +755,11 @@
   DeclTy *ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
   DeclTy *ParseFunctionStatementBody(DeclTy *Decl, 
                                      SourceLocation L, SourceLocation R);
-  void ParseDeclarationSpecifiers(DeclSpec &DS);
+  void ParseDeclarationSpecifiers(DeclSpec &DS, 
+                                  TemplateParameterLists *TemplateParams = 0);
   bool MaybeParseTypeSpecifier(DeclSpec &DS, int &isInvalid, 
-                               const char *&PrevSpec);
+                               const char *&PrevSpec,
+                               TemplateParameterLists *TemplateParams = 0);
   void ParseSpecifierQualifierList(DeclSpec &DS);
   
   void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
@@ -928,7 +934,8 @@
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
   TypeTy *ParseClassName(const CXXScopeSpec *SS = 0);
-  void ParseClassSpecifier(DeclSpec &DS);
+  void ParseClassSpecifier(DeclSpec &DS, 
+                           TemplateParameterLists *TemplateParams = 0);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    DeclTy *TagDecl);
   DeclTy *ParseCXXClassMemberDeclaration(AccessSpecifier AS);
@@ -948,14 +955,20 @@
 
   //===--------------------------------------------------------------------===//
   // C++ 14: Templates [temp]
+  typedef llvm::SmallVector<DeclTy *, 4> TemplateParameterList;
+
   // C++ 14.1: Template Parameters [temp.param]
   DeclTy *ParseTemplateDeclaration(unsigned Context);
-  bool ParseTemplateParameters(DeclTy* TempDecl);
-  bool ParseTemplateParameterList(DeclTy *TmpDecl);
-  DeclTy *ParseTemplateParameter();
-  DeclTy *ParseTypeParameter();
-  DeclTy *ParseTemplateTemplateParameter();
-  DeclTy *ParseNonTypeTemplateParameter();
+  bool ParseTemplateParameters(unsigned Depth, 
+                               TemplateParameterList &TemplateParams,
+                               SourceLocation &LAngleLoc, 
+                               SourceLocation &RAngleLoc);
+  bool ParseTemplateParameterList(unsigned Depth,
+                                  TemplateParameterList &TemplateParams);
+  DeclTy *ParseTemplateParameter(unsigned Depth, unsigned Position);
+  DeclTy *ParseTypeParameter(unsigned Depth, unsigned Position);
+  DeclTy *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+  DeclTy *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
   // C++ 14.3: Template arguments [temp.arg]
   typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
   void AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS = 0);

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Dec 23 20:52:09 2008
@@ -37,6 +37,21 @@
   return new (Mem) 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) {
+  unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
+  unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
+  void *Mem = C.getAllocator().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/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61413&r1=61412&r2=61413&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Dec 23 20:52:09 2008
@@ -419,7 +419,8 @@
 /// [C++]   'virtual'
 /// [C++]   'explicit'
 ///
-void Parser::ParseDeclarationSpecifiers(DeclSpec &DS)
+void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
+                                        TemplateParameterLists *TemplateParams)
 {
   DS.SetRangeStart(Tok.getLocation());
   while (1) {
@@ -436,7 +437,7 @@
     default: 
       // Try to parse a type-specifier; if we found one, continue. If it's not
       // a type, this falls through.
-      if (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
+      if (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec, TemplateParams)) {
         continue;
       }
 
@@ -661,7 +662,8 @@
 /// [OBJC]  class-name objc-protocol-refs[opt]    [TODO]
 /// [OBJC]  typedef-name objc-protocol-refs[opt]  [TODO]
 bool Parser::MaybeParseTypeSpecifier(DeclSpec &DS, int& isInvalid,
-                                     const char *&PrevSpec) {
+                                     const char *&PrevSpec,
+                                     TemplateParameterLists *TemplateParams) {
   // Annotate typenames and C++ scope specifiers.
   TryAnnotateTypeOrScopeToken();
 
@@ -748,7 +750,7 @@
   case tok::kw_class:
   case tok::kw_struct:
   case tok::kw_union:
-    ParseClassSpecifier(DS);
+    ParseClassSpecifier(DS, TemplateParams);
     return true;
 
   // enum-specifier:
@@ -1036,7 +1038,8 @@
   else
     TK = Action::TK_Reference;
   DeclTy *TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TK, StartLoc,
-                                     SS, Name, NameLoc, Attr);
+                                     SS, Name, NameLoc, Attr, 
+                                     Action::MultiTemplateParamsArg(Actions));
   
   if (Tok.is(tok::l_brace))
     ParseEnumBody(StartLoc, TagDecl);

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Dec 23 20:52:09 2008
@@ -202,7 +202,8 @@
 ///       struct-or-union:
 ///         'struct'
 ///         'union'
-void Parser::ParseClassSpecifier(DeclSpec &DS) {
+void Parser::ParseClassSpecifier(DeclSpec &DS,
+                                 TemplateParameterLists *TemplateParams) {
   assert((Tok.is(tok::kw_class) || 
           Tok.is(tok::kw_struct) || 
           Tok.is(tok::kw_union)) &&
@@ -258,8 +259,13 @@
   }
 
   // Parse the tag portion of this.
-  DeclTy *TagDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
-                                     NameLoc, Attr);
+  DeclTy *TagDecl 
+    = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
+                       NameLoc, Attr,
+                       Action::MultiTemplateParamsArg(
+                         Actions,
+                         TemplateParams? &(*TemplateParams)[0] : 0,
+                         TemplateParams? TemplateParams->size() : 0));
 
   // Parse the optional base clause (C++ only).
   if (getLang().CPlusPlus && Tok.is(tok::colon)) {

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue Dec 23 20:52:09 2008
@@ -27,59 +27,94 @@
   assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) && 
 	 "Token does not start a template declaration.");
   
-  // Consume the optional export token, if it exists, followed by the
-  // namespace token.
-  bool isExported = false;
-  if(Tok.is(tok::kw_export)) {
-    SourceLocation ExportLoc = ConsumeToken();
-    if(!Tok.is(tok::kw_template)) {
+  // Enter template-parameter scope.
+  ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+
+  // Parse multiple levels of template headers within this template
+  // parameter scope, e.g.,
+  //
+  //   template<typename T>
+  //     template<typename U>
+  //       class A<T>::B { ... };
+  //
+  // 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:
+  //
+  //   template<typename T>
+  //   class A {
+  //     template<typename U> class B;
+  //   };
+  //
+  // In the first case, the action for declaring A<T>::B receives
+  // both template parameter lists. In the second case, the action for
+  // defining A<T>::B receives just the inner template parameter list
+  // (and retrieves the outer template parameter list from its
+  // context).
+  TemplateParameterLists ParamLists;
+  do {
+    // Consume the 'export', if any.
+    SourceLocation ExportLoc;
+    if (Tok.is(tok::kw_export)) {
+      ExportLoc = ConsumeToken();
+    }
+
+    // Consume the 'template', which should be here.
+    SourceLocation TemplateLoc;
+    if (Tok.is(tok::kw_template)) {
+      TemplateLoc = ConsumeToken();
+    } else {
       Diag(Tok.getLocation(), diag::err_expected_template);
       return 0;
     }
-    isExported = true;
-  }
-  SourceLocation TemplateLoc = ConsumeToken();
   
-  // Enter template-parameter scope.
-  ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+    // Parse the '<' template-parameter-list '>'
+    SourceLocation LAngleLoc, RAngleLoc;
+    TemplateParameterList TemplateParams;
+    ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc, 
+                            RAngleLoc);
+
+    ParamLists.push_back(
+      Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc, 
+                                         TemplateLoc, LAngleLoc, 
+                                         &TemplateParams[0],
+                                         TemplateParams.size(), RAngleLoc));
+  } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
-  // Try to parse the template parameters, and the declaration if
-  // successful.
-  DeclTy *TemplateDecl = 0;
-  if (Tok.is(tok::less) && NextToken().is(tok::greater)) {
-    // This is a template specialization. Just consume the angle
-    // brackets and parse the declaration or function definition that
-    // follows.
-    // FIXME: Record somehow that we're in an explicit specialization.
-    ConsumeToken();
-    ConsumeToken();
-    TemplateParmScope.Exit();
-    TemplateDecl = ParseDeclarationOrFunctionDefinition();
-  } else {
-    if(ParseTemplateParameters(0))
-      TemplateDecl = ParseDeclarationOrFunctionDefinition();
-  }
+  // Parse the actual template declaration.
+  DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists);
 
   return TemplateDecl;
 }
 
 /// ParseTemplateParameters - Parses a template-parameter-list enclosed in
-/// angle brackets.
-bool Parser::ParseTemplateParameters(DeclTy* TmpDecl) {
+/// 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,
+                                     SourceLocation &RAngleLoc) {
   // Get the template parameter list.
   if(!Tok.is(tok::less)) {
     Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
     return false;
   }
-  ConsumeToken();
+  LAngleLoc = ConsumeToken();
   
   // Try to parse the template parameter list.
-  if(ParseTemplateParameterList(0)) {
+  if (Tok.is(tok::greater))
+    RAngleLoc = ConsumeToken();
+  else if(ParseTemplateParameterList(Depth, TemplateParams)) {
     if(!Tok.is(tok::greater)) {
       Diag(Tok.getLocation(), diag::err_expected_greater);
       return false;
     }
-    ConsumeToken();
+    RAngleLoc = ConsumeToken();
   }
   return true;
 }
@@ -92,13 +127,14 @@
 ///       template-parameter-list:    [C++ temp]
 ///         template-parameter
 ///         template-parameter-list ',' template-parameter
-bool Parser::ParseTemplateParameterList(DeclTy* TmpDecl) {
-  // FIXME: For now, this is just going to consume the template parameters.
-  // Eventually, we should pass the template decl AST node as a parameter and
-  // apply template parameters as we find them.
+bool 
+Parser::ParseTemplateParameterList(unsigned Depth,
+                                   TemplateParameterList &TemplateParams) {
   while(1) {
-    DeclTy* TmpParam = ParseTemplateParameter();
-    if(!TmpParam) {
+    if (DeclTy* TmpParam 
+          = ParseTemplateParameter(Depth, TemplateParams.size())) {
+      TemplateParams.push_back(TmpParam);
+    } else {
       // If we failed to parse a template parameter, skip until we find
       // a comma or closing brace.
       SkipUntil(tok::comma, tok::greater, true, true);
@@ -137,20 +173,21 @@
 ///         'typename' identifier[opt] '=' type-id
 ///         'template' '<' template-parameter-list '>' 'class' identifier[opt]
 ///         'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclTy *Parser::ParseTemplateParameter() {
+Parser::DeclTy *
+Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
   TryAnnotateCXXScopeToken();
 
   if(Tok.is(tok::kw_class) 
      || (Tok.is(tok::kw_typename) && 
 	 NextToken().isNot(tok::annot_qualtypename))) {
-    return ParseTypeParameter();
+    return ParseTypeParameter(Depth, Position);
   } else if(Tok.is(tok::kw_template)) {
-    return ParseTemplateTemplateParameter();
+    return ParseTemplateTemplateParameter(Depth, Position);
   } else {
     // If it's none of the above, then it must be a parameter declaration.
     // NOTE: This will pick up errors in the closure of the template parameter
     // list (e.g., template < ; Check here to implement >> style closures.
-    return ParseNonTypeTemplateParameter();
+    return ParseNonTypeTemplateParameter(Depth, Position);
   }
   return 0;
 }
@@ -164,7 +201,7 @@
 ///         'class' identifier[opt] '=' type-id
 ///         'typename' identifier[opt]
 ///         'typename' identifier[opt] '=' type-id
-Parser::DeclTy *Parser::ParseTypeParameter() {
+Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
   assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
 	 "A type-parameter starts with 'class' or 'typename'");
 
@@ -188,13 +225,13 @@
   }
   
   DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword, 
-						 KeyLoc, ParamName, NameLoc);
+						 KeyLoc, ParamName, NameLoc,
+                                                 Depth, Position);
 
   // Grab a default type id (if given).
   if(Tok.is(tok::equal)) {
     SourceLocation EqualLoc = ConsumeToken();
-    TypeTy *DefaultType = ParseTypeName();
-    if(DefaultType)
+    if (TypeTy *DefaultType = ParseTypeName())
       Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
   }
   
@@ -207,12 +244,16 @@
 ///       type-parameter:    [C++ temp.param]
 ///         'template' '<' template-parameter-list '>' 'class' identifier[opt]
 ///         'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclTy* Parser::ParseTemplateTemplateParameter() {
+Parser::DeclTy * 
+Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
   assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
 
   // Handle the template <...> part.
   SourceLocation TemplateLoc = ConsumeToken();
-  if(!ParseTemplateParameters(0)) {
+  TemplateParameterList TemplateParams; 
+  SourceLocation LParenLoc, RParenLoc;
+  if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
+                              RParenLoc)) {
     return 0;
   }
 
@@ -265,7 +306,8 @@
 /// parameters.
 /// FIXME: We need to make a ParseParameterDeclaration that works for
 /// non-type template parameters and normal function parameters.
-Parser::DeclTy* Parser::ParseNonTypeTemplateParameter() {
+Parser::DeclTy * 
+Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
   SourceLocation StartLoc = Tok.getLocation();
 
   // Parse the declaration-specifiers (i.e., the type).
@@ -288,7 +330,8 @@
   }
 
   // Create the parameter. 
-  DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl);
+  DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
+                                                        Depth, Position);
 
   // Is there a default value? Parsing this can be fairly annoying because
   // we have to stop on the first non-nested (paren'd) '>' as the closure

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

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Dec 23 20:52:09 2008
@@ -373,7 +373,9 @@
 
 /// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
 /// a declaration.  We can't tell which we have until we read up to the
-/// compound-statement in function-definition.
+/// compound-statement in function-definition. TemplateParams, if
+/// non-NULL, provides the template parameters when we're parsing a
+/// C++ template-declaration. 
 ///
 ///       function-definition: [C99 6.9.1]
 ///         decl-specs      declarator declaration-list[opt] compound-statement
@@ -385,10 +387,12 @@
 /// [!C99]  init-declarator-list ';'                   [TODO: warn in c99 mode]
 /// [OMP]   threadprivate-directive                              [TODO]
 ///
-Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
+Parser::DeclTy *
+Parser::ParseDeclarationOrFunctionDefinition(
+                                  TemplateParameterLists *TemplateParams) {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
-  ParseDeclarationSpecifiers(DS);
+  ParseDeclarationSpecifiers(DS, TemplateParams);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
   // declaration-specifiers init-declarator-list[opt] ';'

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Dec 23 20:52:09 2008
@@ -307,7 +307,8 @@
   virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                            SourceLocation KWLoc, const CXXScopeSpec &SS,
                            IdentifierInfo *Name, SourceLocation NameLoc,
-                           AttributeList *Attr);
+                           AttributeList *Attr,
+                           MultiTemplateParamsArg TemplateParameterLists);
   
   virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
                          IdentifierInfo *ClassName,
@@ -1034,9 +1035,19 @@
   virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename, 
 				     SourceLocation KeyLoc,
 				     IdentifierInfo *ParamName,
-				     SourceLocation ParamNameLoc);
-  virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D);
-
+				     SourceLocation ParamNameLoc,
+                                     unsigned Depth, unsigned Position);
+  virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                                unsigned Depth, 
+                                                unsigned Position);
+  virtual TemplateParamsTy *
+  ActOnTemplateParameterList(unsigned Depth,
+                             SourceLocation ExportLoc,
+                             SourceLocation TemplateLoc, 
+                             SourceLocation LAngleLoc,
+                             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=61413&r1=61412&r2=61413&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 23 20:52:09 2008
@@ -2527,7 +2527,8 @@
 Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
                              SourceLocation KWLoc, const CXXScopeSpec &SS,
                              IdentifierInfo *Name, SourceLocation NameLoc,
-                             AttributeList *Attr) {
+                             AttributeList *Attr,
+                             MultiTemplateParamsArg TemplateParameterLists) {
   // If this is not a definition, it must have a name.
   assert((Name != 0 || TK == TK_Definition) &&
          "Nameless record must be a definition!");

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Dec 23 20:52:09 2008
@@ -86,7 +86,8 @@
 Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename, 
 				       SourceLocation KeyLoc,
 				       IdentifierInfo *ParamName,
-				       SourceLocation ParamNameLoc) {
+				       SourceLocation ParamNameLoc,
+                                       unsigned Depth, unsigned Position) {
   assert(S->isTemplateParamScope() && 
 	 "Template type parameter not in template parameter scope!");
   bool Invalid = false;
@@ -117,7 +118,9 @@
 /// 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.
-Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) {
+Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                                  unsigned Depth, 
+                                                  unsigned Position) {
   QualType T = GetTypeForDeclarator(D, S);
 
   assert(S->isTemplateParamScope() && 
@@ -145,3 +148,18 @@
   }
   return Param;
 }
+
+/// ActOnTemplateParameterList - Builds a TemplateParameterList that
+/// contains the template parameters in Params/NumParams.
+Sema::TemplateParamsTy *
+Sema::ActOnTemplateParameterList(unsigned Depth,
+                                 SourceLocation ExportLoc,
+                                 SourceLocation TemplateLoc, 
+                                 SourceLocation LAngleLoc,
+                                 DeclTy **Params, unsigned NumParams,
+                                 SourceLocation RAngleLoc) {
+  if (ExportLoc.isValid())
+    Diag(ExportLoc, diag::note_template_export_unsupported);
+
+  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=61413&r1=61412&r2=61413&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Tue Dec 23 20:52:09 2008
@@ -3,7 +3,8 @@
 // Errors
 export class foo { };   // expected-error {{expected template}}
 template  x;            // expected-error {{expected '<' after 'template'}}
-export template x;      // expected-error {{expected '<' after 'template'}}
+export template x;      // expected-error {{expected '<' after 'template'}} \
+                        // expected-note {{exported templates are unsupported}}
 template < ;            // expected-error {{parse error}}
 template <template X> ; // expected-error {{expected '<' after 'template'}}
 template <template <typename> > ;       // expected-error {{expected 'class' before '>'}}





More information about the cfe-commits mailing list