[cfe-commits] r38897 - in /cfe/cfe/trunk: Parse/ParseDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Parser.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:25:35 PDT 2007


Author: sabre
Date: Wed Jul 11 11:25:34 2007
New Revision: 38897

URL: http://llvm.org/viewvc/llvm-project?rev=38897&view=rev
Log:
Parse struct/union specifiers.

Modified:
    cfe/cfe/trunk/Parse/ParseDecl.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Parse/Parser.h

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

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:25:34 2007
@@ -26,24 +26,7 @@
 void Parser::ParseTypeName() {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS;
-  SourceLocation Loc = Tok.getLocation();
-  ParseDeclarationSpecifiers(DS);
-  
-  // Validate declspec for type-name.
-  unsigned Specs = DS.getParsedSpecifiers();
-  if (Specs == DeclSpec::PQ_None)
-    Diag(Tok, diag::err_typename_requires_specqual);
-  
-  if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
-    Diag(Loc, diag::err_typename_invalid_storageclass);
-    // Remove storage class.
-    DS.StorageClassSpec     = DeclSpec::SCS_unspecified;
-    DS.SCS_thread_specified = false;
-  }
-  if (Specs & DeclSpec::PQ_FunctionSpecifier) {
-    Diag(Loc, diag::err_typename_invalid_functionspec);
-    DS.FS_inline_specified = false;
-  }
+  ParseSpecifierQualifierList(DS);
   
   // Parse the abstract-declarator, if present.
   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
@@ -102,6 +85,33 @@
   }
 }
 
+/// ParseSpecifierQualifierList
+///        specifier-qualifier-list:
+///          type-specifier specifier-qualifier-list[opt]
+///          type-qualifier specifier-qualifier-list[opt]
+///
+void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
+  /// specifier-qualifier-list is a subset of declaration-specifiers.  Just
+  /// parse declaration-specifiers and complain about extra stuff.
+  SourceLocation Loc = Tok.getLocation();
+  ParseDeclarationSpecifiers(DS);
+  
+  // Validate declspec for type-name.
+  unsigned Specs = DS.getParsedSpecifiers();
+  if (Specs == DeclSpec::PQ_None)
+    Diag(Tok, diag::err_typename_requires_specqual);
+  
+  if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
+    Diag(Loc, diag::err_typename_invalid_storageclass);
+    // Remove storage class.
+    DS.StorageClassSpec     = DeclSpec::SCS_unspecified;
+    DS.SCS_thread_specified = false;
+  }
+  if (Specs & DeclSpec::PQ_FunctionSpecifier) {
+    Diag(Loc, diag::err_typename_invalid_functionspec);
+    DS.FS_inline_specified = false;
+  }
+}
 
 /// ParseDeclarationSpecifiers
 ///       declaration-specifiers: [C99 6.7]
@@ -128,7 +138,7 @@
 ///         'double'
 ///         'signed'
 ///         'unsigned'
-///         struct-or-union-specifier             [TODO]
+///         struct-or-union-specifier
 ///         enum-specifier
 ///         typedef-name                          [TODO]
 /// [C99]   '_Bool'
@@ -240,8 +250,10 @@
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
       break;
       
-    //case tok::kw_struct:
-    //case tok::kw_union:
+    case tok::kw_struct:
+    case tok::kw_union:
+      ParseStructUnionSpecifier(DS);
+      continue;
     case tok::kw_enum:
       ParseEnumSpecifier(DS);
       continue;
@@ -278,17 +290,124 @@
   }
 }
 
+
+/// ParseStructUnionSpecifier
+///       struct-or-union-specifier: [C99 6.7.2.1]
+///         struct-or-union identifier[opt] '{' struct-declaration-list '}'
+///         struct-or-union identifier
+///       struct-or-union:
+///         'struct'
+///         'union'
+///       struct-declaration-list:
+///          struct-declaration
+///          struct-declaration-list struct-declaration
+///        struct-declaration:
+///          specifier-qualifier-list struct-declarator-list ';'
+///        struct-declarator-list:
+///          struct-declarator
+///          struct-declarator-list ',' struct-declarator
+///        struct-declarator:
+///          declarator
+///          declarator[opt] ':' constant-expression
+///
+void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
+  assert((Tok.getKind() == tok::kw_struct ||
+          Tok.getKind() == tok::kw_union) && "Not a struct/union specifier");
+  bool isUnion = Tok.getKind() == tok::kw_union;
+  ConsumeToken();
+  
+  // Must have either 'struct name' or 'struct {...}'.
+  if (Tok.getKind() != tok::identifier &&
+      Tok.getKind() != tok::l_brace) {
+    Diag(Tok, diag::err_expected_ident_lbrace);
+    return;
+  }
+  
+  if (Tok.getKind() == tok::identifier)
+    ConsumeToken();
+  
+  if (Tok.getKind() != tok::l_brace)
+    return;
+  
+  SourceLocation LBraceLoc = Tok.getLocation();
+  ConsumeBrace();
+
+  if (Tok.getKind() == tok::r_brace)
+    Diag(Tok, diag::ext_empty_struct_union_enum, isUnion ? "union" : "struct");
+
+  while (Tok.getKind() != tok::r_brace && 
+         Tok.getKind() != tok::eof) {
+    // Each iteration of this loop reads one struct-declaration.
+
+    // Parse the common specifier-qualifiers-list piece.
+    DeclSpec DS;
+    SourceLocation SpecQualLoc = Tok.getLocation();
+    ParseSpecifierQualifierList(DS);
+    // TODO: Does specifier-qualifier list correctly check that *something* is
+    // specified?
+    
+    Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+
+    // If there are no declarators, issue a warning.
+    if (Tok.getKind() == tok::semi) {
+      Diag(SpecQualLoc, diag::w_no_declarators);
+    } else {
+      // Read struct-declarators until we find the semicolon.
+      while (1) {
+        /// struct-declarator: declarator
+        /// struct-declarator: declarator[opt] ':' constant-expression
+        if (Tok.getKind() != tok::colon)
+          ParseDeclarator(DeclaratorInfo);
+        
+        if (Tok.getKind() == tok::colon) {
+          ConsumeToken();
+          ExprResult Res = ParseConstantExpression();
+          if (Res.isInvalid) {
+            SkipUntil(tok::semi, true, true);
+          } else {
+            // Process it.
+          }
+        }
+
+        // TODO: install declarator.
+        
+        // If we don't have a comma, it is either the end of the list (a ';') or
+        // an error, bail out.
+        if (Tok.getKind() != tok::comma)
+          break;
+        
+        // Consume the comma.
+        ConsumeToken();
+        
+        // Parse the next declarator.
+        DeclaratorInfo.clear();
+      }
+    }
+    
+    if (Tok.getKind() == tok::semi) {
+      ConsumeToken();
+    } else {
+      Diag(Tok, diag::err_expected_semi_decl_list);
+      // Skip to end of block or statement
+      SkipUntil(tok::r_brace, true, true);
+    }
+  }
+
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{",diag::err_expected_rbrace);
+}
+
+
 /// ParseEnumSpecifier
-///       enum-specifier:
+///       enum-specifier: [C99 6.7.2.2]
 ///         'enum' identifier[opt] '{' enumerator-list '}'
 /// [C99]   'enum' identifier[opt] '{' enumerator-list ',' '}'
 ///         'enum' identifier
 ///       enumerator-list:
 ///         enumerator
-///         enumerator-list , enumerator
+///         enumerator-list ',' enumerator
 ///       enumerator:
 ///         enumeration-constant
-///         enumeration-constant = constant-expression
+///         enumeration-constant '=' constant-expression
 ///       enumeration-constant:
 ///         identifier
 ///
@@ -306,33 +425,37 @@
   if (Tok.getKind() == tok::identifier)
     ConsumeToken();
   
-  if (Tok.getKind() == tok::l_brace) {
-    SourceLocation LBraceLoc = Tok.getLocation();
-    ConsumeBrace();
+  if (Tok.getKind() != tok::l_brace)
+    return;
+  
+  SourceLocation LBraceLoc = Tok.getLocation();
+  ConsumeBrace();
+  
+  if (Tok.getKind() == tok::r_brace)
+    Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
+  
+  // Parse the enumerator-list.
+  while (Tok.getKind() == tok::identifier) {
+    ConsumeToken();
     
-    // Parse the enumerator-list.
-    while (Tok.getKind() == tok::identifier) {
-      ConsumeToken();
-      
-      if (Tok.getKind() == tok::equal) {
-        ConsumeToken();
-        ExprResult Res = ParseConstantExpression();
-        if (Res.isInvalid) SkipUntil(tok::comma, true, false);
-      }
-      
-      if (Tok.getKind() != tok::comma)
-        break;
-      SourceLocation CommaLoc = Tok.getLocation();
+    if (Tok.getKind() == tok::equal) {
       ConsumeToken();
-      
-      if (Tok.getKind() != tok::identifier && !getLang().C99)
-        Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
+      ExprResult Res = ParseConstantExpression();
+      if (Res.isInvalid) SkipUntil(tok::comma, true, false);
     }
     
-    // Eat the }.
-    MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{", 
-                        diag::err_expected_rbrace);
+    if (Tok.getKind() != tok::comma)
+      break;
+    SourceLocation CommaLoc = Tok.getLocation();
+    ConsumeToken();
+    
+    if (Tok.getKind() != tok::identifier && !getLang().C99)
+      Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
   }
+  
+  // Eat the }.
+  MatchRHSPunctuation(tok::r_brace, LBraceLoc, "{", 
+                      diag::err_expected_rbrace);
   // TODO: semantic analysis on the declspec for enums.
 }
 

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38897&r1=38896&r2=38897&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:25:34 2007
@@ -236,6 +236,8 @@
 
 DIAG(w_type_defaults_to_int, WARNING,
      "type defaults to 'int'")
+DIAG(w_no_declarators, WARNING,
+     "declaration does not declare anything")
 
 DIAG(ext_empty_source_file, EXTENSION,
      "ISO C forbids an empty source file")
@@ -250,6 +252,9 @@
 DIAG(ext_thread_before, EXTENSION,
      "'__thread' before 'static'")
 
+DIAG(ext_empty_struct_union_enum, EXTENSION,
+     "use of empty %s extension")
+
 DIAG(ext_ident_list_in_param, EXTENSION,
      "type-less parameter names in function declaration")
 DIAG(ext_c99_array_usage, EXTENSION,

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:25:34 2007
@@ -242,7 +242,10 @@
   void ParseDeclaration(unsigned Context);
   void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
   void ParseDeclarationSpecifiers(DeclSpec &DS);
+  void ParseSpecifierQualifierList(DeclSpec &DS);
+
   void ParseEnumSpecifier(DeclSpec &DS);
+  void ParseStructUnionSpecifier(DeclSpec &DS);
 
   bool isDeclarationSpecifier() const;
   bool isTypeSpecifierQualifier() const;





More information about the cfe-commits mailing list