[cfe-commits] r79570 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/member-function-template.cpp

Douglas Gregor dgregor at apple.com
Thu Aug 20 15:52:59 PDT 2009


Author: dgregor
Date: Thu Aug 20 17:52:58 2009
New Revision: 79570

URL: http://llvm.org/viewvc/llvm-project?rev=79570&view=rev
Log:
Initial support for parsing and representation of member function templates.

Added:
    cfe/trunk/test/SemaTemplate/member-function-template.cpp
Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Aug 20 17:52:58 2009
@@ -1276,6 +1276,7 @@
   /// specifier on the function.
   virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
                                              Declarator &D,
+                                 MultiTemplateParamsArg TemplateParameterLists,
                                              ExprTy *BitfieldWidth,
                                              ExprTy *Init,
                                              bool Deleted = false) {

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug 20 17:52:58 2009
@@ -580,18 +580,6 @@
     }
   };
 
-  void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
-  void DeallocateParsedClasses(ParsingClass *Class);
-  void PopParsingClass();
-
-  DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D);
-  void ParseLexedMethodDeclarations(ParsingClass &Class);
-  void ParseLexedMethodDefs(ParsingClass &Class);
-  bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 
-                            CachedTokens &Toks,
-                            tok::TokenKind EarlyAbortIf = tok::unknown,
-                            bool ConsumeFinalToken = true);
-
   /// \brief Contains information about any template-specific
   /// information that has been parsed prior to parsing declaration
   /// specifiers.
@@ -628,6 +616,19 @@
     /// instantiation.
     SourceLocation TemplateLoc;
   };
+  
+  void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
+  void DeallocateParsedClasses(ParsingClass *Class);
+  void PopParsingClass();
+
+  DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+                                    const ParsedTemplateInfo &TemplateInfo);
+  void ParseLexedMethodDeclarations(ParsingClass &Class);
+  void ParseLexedMethodDefs(ParsingClass &Class);
+  bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, 
+                            CachedTokens &Toks,
+                            tok::TokenKind EarlyAbortIf = tok::unknown,
+                            bool ConsumeFinalToken = true);
 
   //===--------------------------------------------------------------------===//
   // C99 6.9: External Definitions.
@@ -1157,7 +1158,8 @@
                            AccessSpecifier AS = AS_none);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    DeclPtrTy TagDecl);
-  void ParseCXXClassMemberDeclaration(AccessSpecifier AS);
+  void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+                const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
   void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
   MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
   void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Aug 20 17:52:58 2009
@@ -21,17 +21,23 @@
 /// Declarator is a well formed C++ inline method definition. Now lex its body
 /// and store its tokens for parsing after the C++ class is complete.
 Parser::DeclPtrTy
-Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
+Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+                                const ParsedTemplateInfo &TemplateInfo) {
   assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
          "This isn't a function declarator!");
   assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
          "Current token not a '{', ':' or 'try'!");
 
+  Action::MultiTemplateParamsArg TemplateParams(Actions,
+                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+                                                TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
   DeclPtrTy FnD;
   if (D.getDeclSpec().isFriendSpecified())
+    // FIXME: Friend templates
     FnD = Actions.ActOnFriendDecl(CurScope, &D, /*IsDefinition*/ true);
-  else
-    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
+  else // FIXME: pass template information through
+    FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 
+                                           move(TemplateParams), 0, 0);
 
   HandleMemberFunctionDefaultArgs(D, FnD);
 

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Aug 20 17:52:58 2009
@@ -905,15 +905,19 @@
 ///       constant-initializer:
 ///         '=' constant-expression
 ///
-void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+                                       const ParsedTemplateInfo &TemplateInfo) {
   // static_assert-declaration
   if (Tok.is(tok::kw_static_assert)) {
+    // FIXME: Check for templates
     SourceLocation DeclEnd;
     ParseStaticAssertDeclaration(DeclEnd);
     return;
   }
       
   if (Tok.is(tok::kw_template)) {
+    assert(!TemplateInfo.TemplateParams && 
+           "Nested template improperly parsed?");
     SourceLocation DeclEnd;
     ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd, 
                                          AS);
@@ -925,10 +929,12 @@
     // __extension__ silences extension warnings in the subexpression.
     ExtensionRAIIObject O(Diags);  // Use RAII to do this.
     ConsumeToken();
-    return ParseCXXClassMemberDeclaration(AS);
+    return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
   }
 
   if (Tok.is(tok::kw_using)) {
+    // FIXME: Check for template aliases
+    
     // Eat 'using'.
     SourceLocation UsingLoc = ConsumeToken();
 
@@ -948,11 +954,12 @@
   // decl-specifier-seq:
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
-  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_class);
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
 
   if (Tok.is(tok::semi)) {
     ConsumeToken();
 
+    // FIXME: Friend templates?
     if (DS.isFriendSpecified())
       Actions.ActOnFriendDecl(CurScope, &DS, /*IsDefinition*/ false);
     else
@@ -996,7 +1003,7 @@
         return;
       }
 
-      ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+      ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo);
       return;
     }
   }
@@ -1059,15 +1066,20 @@
 
     DeclPtrTy ThisDecl;
     if (DS.isFriendSpecified()) {
-      // TODO: handle initializers, bitfields, 'delete'
+      // TODO: handle initializers, bitfields, 'delete', friend templates
       ThisDecl = Actions.ActOnFriendDecl(CurScope, &DeclaratorInfo,
                                          /*IsDefinition*/ false);
-    } else
+    } else {
+      Action::MultiTemplateParamsArg TemplateParams(Actions,
+          TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+          TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
       ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
                                                   DeclaratorInfo,
+                                                  move(TemplateParams),
                                                   BitfieldSize.release(),
                                                   Init.release(),
                                                   Deleted);
+    }
     if (ThisDecl)
       DeclsInGroup.push_back(ThisDecl);
 
@@ -1181,6 +1193,8 @@
       continue;
     }
 
+    // FIXME: Make sure we don't have a template here.
+    
     // Parse all the comma separated declarators.
     ParseCXXClassMemberDeclaration(CurAS);
   }

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Aug 20 17:52:58 2009
@@ -151,6 +151,12 @@
   assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
          "Template information required");
 
+  if (Context == Declarator::MemberContext) {
+    // We are parsing a member template.
+    ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+    return DeclPtrTy::make((void*)0);
+  }
+  
   // Parse the declaration specifiers.
   DeclSpec DS;
   // FIXME: Pass TemplateLoc through for explicit template instantiations

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Aug 20 17:52:58 2009
@@ -2038,6 +2038,7 @@
 
   virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
                                              Declarator &D,
+                                 MultiTemplateParamsArg TemplateParameterLists,
                                              ExprTy *BitfieldWidth,
                                              ExprTy *Init,
                                              bool Deleted = false);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug 20 17:52:58 2009
@@ -550,6 +550,7 @@
 /// any.
 Sema::DeclPtrTy
 Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+                               MultiTemplateParamsArg TemplateParameterLists,
                                ExprTy *BW, ExprTy *InitExpr, bool Deleted) {
   const DeclSpec &DS = D.getDeclSpec();
   DeclarationName Name = GetNameForDeclarator(D);
@@ -627,11 +628,13 @@
 
   Decl *Member;
   if (isInstField) {
+    // FIXME: Check for template parameters!
     Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
                          AS);
     assert(Member && "HandleField never returns null");
   } else {
-    Member = ActOnDeclarator(S, D).getAs<Decl>();
+    Member = HandleDeclarator(S, D, move(TemplateParameterLists), false)
+               .getAs<Decl>();
     if (!Member) {
       if (BitWidth) DeleteExpr(BitWidth);
       return DeclPtrTy();
@@ -664,6 +667,11 @@
     }
 
     Member->setAccess(AS);
+    
+    // If we have declared a member function template, set the access of the
+    // templated declaration as well.
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
+      FunTmpl->getTemplatedDecl()->setAccess(AS);
   }
 
   assert((Name || isInstField) && "No identifier for non-field ?");

Added: cfe/trunk/test/SemaTemplate/member-function-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-function-template.cpp?rev=79570&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/member-function-template.cpp (added)
+++ cfe/trunk/test/SemaTemplate/member-function-template.cpp Thu Aug 20 17:52:58 2009
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only %s
+
+struct X {
+  template<typename T> T& f(T);
+};





More information about the cfe-commits mailing list