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

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


Author: sabre
Date: Wed Jul 11 11:25:05 2007
New Revision: 38841

URL: http://llvm.org/viewvc/llvm-project?rev=38841&view=rev
Log:
Simplify and fill out parsing of function bodies.

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

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

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:25:05 2007
@@ -455,12 +455,14 @@
   // NOTE: better to only create a scope if not '()'
   bool IsVariadic;
   bool HasPrototype;
+  bool IsEmpty = false;
   bool ErrorEmitted = false;
 
   if (Tok.getKind() == tok::r_paren) {
     // int() -> no prototype, no '...'.
     IsVariadic   = false;
     HasPrototype = false;
+    IsEmpty      = true;
   } else if (Tok.getKind() == tok::identifier &&
              0/*TODO: !isatypedefname(Tok.getIdentifierInfo())*/) {
     // Identifier list.  Note that '(' identifier-list ')' is only allowed for
@@ -545,7 +547,7 @@
   
   // Remember that we parsed a function type, and remember the attributes.
   D.AddTypeInfo(DeclaratorTypeInfo::getFunction(HasPrototype, IsVariadic,
-                                                StartLoc));
+                                                IsEmpty, StartLoc));
   
   
   // If we have the closing ')', eat it and we're done.

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

==============================================================================
--- cfe/cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/cfe/trunk/Parse/Parser.cpp Wed Jul 11 11:25:05 2007
@@ -187,7 +187,6 @@
 ///
 void Parser::ParseDeclarationOrFunctionDefinition() {
   // Parse the common declaration-specifiers piece.
-  // NOTE: this can not be missing for C99 'declaration's.
   DeclSpec DS;
   ParseDeclarationSpecifiers(DS);
 
@@ -196,41 +195,63 @@
     assert(0 && "Unimp!");
   
   
-  // Parse the declarator.
-  {
-    Declarator DeclaratorInfo(DS, Declarator::FileContext);
-    ParseDeclarator(DeclaratorInfo);
+  // Parse the first declarator.
+  Declarator DeclaratorInfo(DS, Declarator::FileContext);
+  ParseDeclarator(DeclaratorInfo);
+  // Error parsing the declarator?
+  if (DeclaratorInfo.getIdentifier() == 0) {
+    // If so, skip until the semi-colon or a }.
+    SkipUntil(tok::r_brace, true);
+    if (Tok.getKind() == tok::semi)
+      ConsumeToken();
+    return;
+  }
 
-    // If the declarator was the start of a function definition, handle it.
-    if (Tok.getKind() != tok::equal &&  // int X()=  -> not a function def
-        Tok.getKind() != tok::comma &&  // int X(),  -> not a function def
-        Tok.getKind() != tok::semi &&   // int X();  -> not a function def
-        DS.StorageClassSpec != DeclSpec::SCS_typedef && // typedef int X()
-        DeclaratorInfo.isInnermostFunctionType()) {  // int *X -> not a fn def.
-      assert(0 && "unimp");
-      
-      
-    }
+  // If the declarator is the start of a function definition, handle it.
+  if (Tok.getKind() == tok::equal ||  // int X()=  -> not a function def
+      Tok.getKind() == tok::comma ||  // int X(),  -> not a function def
+      Tok.getKind() == tok::semi ||   // int X();  -> not a function def
+      Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
+      Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
+    // FALL THROUGH.
+  } else if (DeclaratorInfo.isInnermostFunctionType() &&
+             (Tok.getKind() == tok::l_brace ||  // int X() {}
+              isDeclarationSpecifier())) {      // int X(f) int f; {}
+    ParseFunctionDefinition(DeclaratorInfo);
+    return;
+  } else {
+    if (DeclaratorInfo.isInnermostFunctionType())
+      Diag(Tok, diag::err_expected_fn_body);
+    else
+      Diag(Tok, diag::err_expected_after_declarator);
+    SkipUntil(tok::r_brace, true);
+    if (Tok.getKind() == tok::semi)
+      ConsumeToken();
+    return;
+  }
 
+  // At this point, we know that it is not a function definition.  Parse the
+  // rest of the init-declarator-list.
+  while (1) {
     // must be: decl-spec[opt] declarator init-declarator-list
     // Parse declarator '=' initializer.
     if (Tok.getKind() == tok::equal)
       assert(0 && "cannot handle initializer yet!");
-  }
 
-  while (Tok.getKind() == tok::comma) {
+    
+    // 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 declarator.
-    Declarator DeclaratorInfo(DS, Declarator::FileContext);
+    // Parse the next declarator.
+    DeclaratorInfo.clear();
     ParseDeclarator(DeclaratorInfo);
-    
-    // declarator '=' initializer
-    if (Tok.getKind() == tok::equal)
-      assert(0 && "cannot handle initializer yet!");
-    
-    
   }
   
   if (Tok.getKind() == tok::semi) {
@@ -244,3 +265,60 @@
   }
 }
 
+/// ParseFunctionDefinition - We parsed and verified that the specified
+/// Declarator is well formed.  If this is a K&R-style function, read the
+/// parameters declaration-list, then start the compound-statement.
+///
+///         declaration-specifiers[opt] declarator declaration-list[opt] 
+///                 compound-statement                           [TODO]
+///
+void Parser::ParseFunctionDefinition(Declarator &D) {
+  const DeclaratorTypeInfo &FnTypeInfo = D.getTypeObject(0);
+  assert(FnTypeInfo.Kind == DeclaratorTypeInfo::Function &&
+         "This isn't a function declarator!");
+  
+  // If this declaration was formed with a K&R-style identifier list for the
+  // arguments, parse declarations for all of the args next.
+  // int foo(a,b) int a; float b; {}
+  if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
+    // Read all the argument declarations.
+    while (isDeclarationSpecifier()) {
+      // Parse the common declaration-specifiers piece.
+      DeclSpec DS;
+      ParseDeclarationSpecifiers(DS);
+      
+      Declarator DeclaratorInfo(DS, Declarator::FileContext);
+      ParseDeclarator(DeclaratorInfo);
+
+      while (Tok.getKind() == tok::comma) {
+        // Consume the comma.
+        ConsumeToken();
+      
+        // Parse the next declarator.
+        DeclaratorInfo.clear();
+        ParseDeclarator(DeclaratorInfo);
+      }
+      
+      if (Tok.getKind() == tok::semi) {
+        ConsumeToken();
+      } else {
+        Diag(Tok, diag::err_expected_semi_knr_fn_body);
+        // Skip to end of block or statement
+        SkipUntil(tok::l_brace, true);
+        if (Tok.getKind() == tok::semi)
+          ConsumeToken();
+      }
+    }
+    
+    // Note, check that we got them all.
+  } else {
+    //if (isDeclarationSpecifier())
+    //  Diag('k&r declspecs with prototype?');
+    
+    // FIXME: Install the arguments into the current scope.
+  }
+
+  
+  
+}
+

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=38841&r1=38840&r2=38841&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:25:05 2007
@@ -264,6 +264,12 @@
      "expected identifier or '('")
 DIAG(err_expected_rparen, ERROR,
      "expected ')'")
+DIAG(err_expected_semi_knr_fn_body, ERROR,
+     "expected ';' at end of K&R-style function argument declaration list")
+DIAG(err_expected_fn_body, ERROR,
+     "expected function body after function declarator")
+DIAG(err_expected_after_declarator, ERROR,
+     "expected '=', ',', ';', 'asm', or '__attribute__' after declarator")
 
 /// err_matching - this is used as a continuation of a previous error, e.g. to 
 /// specify the '(' when we expected a ')'.  This should probably be some

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/DeclSpec.h Wed Jul 11 11:25:05 2007
@@ -172,6 +172,7 @@
     /// with ',...)', this is true.
     bool isVariadic : 1;
     // TODO: capture argument info.
+    bool isEmpty : 1;
   };
   
   union {
@@ -209,12 +210,14 @@
   /// getFunction - Return a DeclaratorTypeInfo for a function.
   ///
   static DeclaratorTypeInfo getFunction(bool hasProto, bool isVariadic,
+                                        bool isEmpty /*fixme arg info*/,
                                         SourceLocation Loc) {
     DeclaratorTypeInfo I;
     I.Kind             = Function;
     I.Loc              = Loc;
     I.Fun.hasPrototype = hasProto;
     I.Fun.isVariadic   = isVariadic;
+    I.Fun.isEmpty      = isEmpty;
     return I;
   }
 };





More information about the cfe-commits mailing list