]> granicus.if.org Git - clang/commitdiff
refactor Parser::ParseStructDeclaration to return a vector of uninterpreted
authorChris Lattner <sabre@nondot.org>
Thu, 10 Apr 2008 06:46:29 +0000 (06:46 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 10 Apr 2008 06:46:29 +0000 (06:46 +0000)
declarators.  This allows the clients (C structs, objc classes, objc
properties, [future] C++ classes) etc, to do custom processing before invoking
an action.

This has two benefits in the short term:
1) objc ivar processing should be split out of ActOnField into its own ActOn method.
2) the new objc ivar action can take visibility info directly, eliminating
   AllVisibilities in ParseObjCClassInstanceVariables.
3) objc properties can pass their own special sauce down to sema as well.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49468 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/DeclSpec.h
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseObjc.cpp

index 6204a383b9a3e4c5660ba52f6442e29ca4d82103..b0efc188ef436b192bad7e997fc37c9ffad9faf2 100644 (file)
@@ -665,6 +665,17 @@ public:
   bool getInvalidType() const { return InvalidType; }
 };
 
+/// FieldDeclarator - This little struct is used to capture information about
+/// structure field declarators, which is basically just a bitfield size.
+struct FieldDeclarator {
+  Declarator D;
+  Action::ExprTy *BitfieldSize;
+  FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
+    BitfieldSize = 0;
+  }
+};
+
+
 } // end namespace clang
 
 #endif
index a45f81a246ac38150a736c860a68758b9fd80746..13535805e2444c3422ce6ef11fd3eace3180f4a6 100644 (file)
@@ -21,6 +21,7 @@ namespace clang {
   class DeclSpec;
   class ObjCDeclSpec;
   class Declarator;
+  class FieldDeclarator;
   class AttributeList;
   class Scope;
 
@@ -453,8 +454,8 @@ private:
   void ParseStructUnionSpecifier(DeclSpec &DS);
   void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
                             DeclTy *TagDecl);
-  void ParseStructDeclaration(DeclTy *TagDecl,
-                              llvm::SmallVectorImpl<DeclTy*> &FieldDecls);
+  void ParseStructDeclaration(DeclSpec &DS,
+                              llvm::SmallVectorImpl<FieldDeclarator> &Fields);
                               
   bool isDeclarationSpecifier() const;
   bool isTypeSpecifierQualifier() const;
index 77287043a53c6b79e8490331c6ba49cfeb8b7787..1d412482ea90271ca966c0432b373f1d2f000157 100644 (file)
@@ -657,14 +657,14 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
 ///         declarator[opt] ':' constant-expression
 /// [GNU]   declarator[opt] ':' constant-expression attributes[opt]
 ///
-void Parser::ParseStructDeclaration(DeclTy *TagDecl,
-  llvm::SmallVectorImpl<DeclTy*> &FieldDecls) {
+void Parser::
+ParseStructDeclaration(DeclSpec &DS,
+                       llvm::SmallVectorImpl<FieldDeclarator> &Fields) {
   // FIXME: When __extension__ is specified, disable extension diagnostics.
-  if (Tok.is(tok::kw___extension__))
+  while (Tok.is(tok::kw___extension__))
     ConsumeToken();
   
   // Parse the common specifier-qualifiers-list piece.
-  DeclSpec DS;
   SourceLocation DSStart = Tok.getLocation();
   ParseSpecifierQualifierList(DS);
   // TODO: Does specifier-qualifier list correctly check that *something* is
@@ -677,33 +677,27 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl,
   }
 
   // Read struct-declarators until we find the semicolon.
-  Declarator DeclaratorInfo(DS, Declarator::MemberContext);
-
+  Fields.push_back(DS);
   while (1) {
+    FieldDeclarator &DeclaratorInfo = Fields.back();
+    
     /// struct-declarator: declarator
     /// struct-declarator: declarator[opt] ':' constant-expression
     if (Tok.isNot(tok::colon))
-      ParseDeclarator(DeclaratorInfo);
+      ParseDeclarator(DeclaratorInfo.D);
     
-    ExprTy *BitfieldSize = 0;
     if (Tok.is(tok::colon)) {
       ConsumeToken();
       ExprResult Res = ParseConstantExpression();
       if (Res.isInvalid)
         SkipUntil(tok::semi, true, true);
       else
-        BitfieldSize = Res.Val;
+        DeclaratorInfo.BitfieldSize = Res.Val;
     }
     
     // If attributes exist after the declarator, parse them.
     if (Tok.is(tok::kw___attribute))
-      DeclaratorInfo.AddAttributes(ParseAttributes());
-    
-    // Install the declarator into the current TagDecl.
-    DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,
-                                       DS.getSourceRange().getBegin(),
-                                       DeclaratorInfo, BitfieldSize);
-    FieldDecls.push_back(Field);
+      DeclaratorInfo.D.AddAttributes(ParseAttributes());
     
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
@@ -714,11 +708,11 @@ void Parser::ParseStructDeclaration(DeclTy *TagDecl,
     ConsumeToken();
     
     // Parse the next declarator.
-    DeclaratorInfo.clear();
+    Fields.push_back(DS);
     
     // Attributes are only allowed on the second declarator.
     if (Tok.is(tok::kw___attribute))
-      DeclaratorInfo.AddAttributes(ParseAttributes());
+      Fields.back().D.AddAttributes(ParseAttributes());
   }
 }
 
@@ -743,7 +737,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
          DeclSpec::getSpecifierName((DeclSpec::TST)TagType));
 
   llvm::SmallVector<DeclTy*, 32> FieldDecls;
-  
+  llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
+
   // While we still have something to read, read the declarations in the struct.
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     // Each iteration of this loop reads one struct-declaration.
@@ -754,7 +749,22 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
       ConsumeToken();
       continue;
     }
-    ParseStructDeclaration(TagDecl, FieldDecls);
+
+    // Parse all the comma separated declarators.
+    DeclSpec DS;
+    FieldDeclarators.clear();
+    ParseStructDeclaration(DS, FieldDeclarators);
+    
+    // Convert them all to fields.
+    for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
+      FieldDeclarator &FD = FieldDeclarators[i];
+      // Install the declarator into the current TagDecl.
+      DeclTy *Field = Actions.ActOnField(CurScope, TagDecl,
+                                         DS.getSourceRange().getBegin(),
+                                         FD.D, FD.BitfieldSize);
+      FieldDecls.push_back(Field);
+    }
+    
 
     if (Tok.is(tok::semi)) {
       ConsumeToken();
index 2aee03ae95b608bd3c6a242b9d2724c721849dc9..5a9b980b6dd436d34c9fc3e10c5a6de89bf37019 100644 (file)
@@ -378,16 +378,31 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl,
                                               SourceLocation AtLoc) {
   assert(Tok.isObjCAtKeyword(tok::objc_property) &&
          "ParseObjCPropertyDecl(): Expected @property");
-  ObjCDeclSpec DS;
+  ObjCDeclSpec OCDS;
   ConsumeToken(); // the "property" identifier
   // Parse property attribute list, if any. 
   if (Tok.is(tok::l_paren)) {
     // property has attribute list.
-    ParseObjCPropertyAttribute(DS);
+    ParseObjCPropertyAttribute(OCDS);
   }
   // Parse declaration portion of @property.
   llvm::SmallVector<DeclTy*, 8> PropertyDecls;
-  ParseStructDeclaration(interfaceDecl, PropertyDecls);
+  
+  // Parse all the comma separated declarators.
+  DeclSpec DS;
+  llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
+  ParseStructDeclaration(DS, FieldDeclarators);
+  
+  // Convert them all to fields.
+  for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
+    FieldDeclarator &FD = FieldDeclarators[i];
+    // Install the declarator into interfaceDecl.
+    DeclTy *Field = Actions.ActOnField(CurScope, interfaceDecl,
+                                       DS.getSourceRange().getBegin(),
+                                       FD.D, FD.BitfieldSize);
+    PropertyDecls.push_back(Field);
+  }
+  
   if (Tok.is(tok::semi)) 
     ConsumeToken();
   else {
@@ -395,7 +410,7 @@ Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl,
     SkipUntil(tok::r_brace, true, true);
   }
   return Actions.ActOnAddObjCProperties(AtLoc,  &PropertyDecls[0],
-                                        PropertyDecls.size(), DS);
+                                        PropertyDecls.size(), OCDS);
 }
 
 ///   objc-method-proto:
@@ -756,10 +771,10 @@ bool Parser::ParseObjCProtocolReferences(
 void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
                                              SourceLocation atLoc) {
   assert(Tok.is(tok::l_brace) && "expected {");
-  llvm::SmallVector<DeclTy*, 16> IvarDecls;
   llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
   llvm::SmallVector<tok::ObjCKeywordKind, 32> AllVisibilities;
-  
+  llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
+
   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
   
   tok::ObjCKeywordKind visibility = tok::objc_private;
@@ -773,6 +788,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
       ConsumeToken();
       continue;
     }
+    
     // Set the default visibility to private.
     if (Tok.is(tok::at)) { // parse objc-visibility-spec
       ConsumeToken(); // eat the @ sign
@@ -786,16 +802,25 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
         continue; 
       default:
         Diag(Tok, diag::err_objc_illegal_visibility_spec);
-        ConsumeToken();
         continue;
       }
     }
-    ParseStructDeclaration(interfaceDecl, IvarDecls);
-    for (unsigned i = 0; i < IvarDecls.size(); i++) {
-      AllIvarDecls.push_back(IvarDecls[i]);
+    
+    // Parse all the comma separated declarators.
+    DeclSpec DS;
+    FieldDeclarators.clear();
+    ParseStructDeclaration(DS, FieldDeclarators);
+    
+    // Convert them all to fields.
+    for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
+      FieldDeclarator &FD = FieldDeclarators[i];
+      // Install the declarator into interfaceDecl.
+      DeclTy *Field = Actions.ActOnField(CurScope, interfaceDecl,
+                                         DS.getSourceRange().getBegin(),
+                                         FD.D, FD.BitfieldSize);
+      AllIvarDecls.push_back(Field);
       AllVisibilities.push_back(visibility);
     }
-    IvarDecls.clear();
     
     if (Tok.is(tok::semi)) {
       ConsumeToken();