[cfe-commits] r38873 - in /cfe/cfe/trunk: Parse/ParseExpr.cpp Parse/ParseStmt.cpp include/clang/Parse/Parser.h

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


Author: sabre
Date: Wed Jul 11 11:25:22 2007
New Revision: 38873

URL: http://llvm.org/viewvc/llvm-project?rev=38873&view=rev
Log:
Return information about whether expression parsing was successful

Modified:
    cfe/cfe/trunk/Parse/ParseExpr.cpp
    cfe/cfe/trunk/Parse/ParseStmt.cpp
    cfe/cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/cfe/trunk/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseExpr.cpp?rev=38873&r1=38872&r2=38873&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseExpr.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseExpr.cpp Wed Jul 11 11:25:22 2007
@@ -17,7 +17,7 @@
 using namespace clang;
 
 // C99 6.7.8
-void Parser::ParseInitializer() {
+Parser::ExprResult Parser::ParseInitializer() {
   // FIXME: STUB.
   if (Tok.getKind() == tok::l_brace) {
     ConsumeBrace();
@@ -29,22 +29,21 @@
     // Match the '}'.
     MatchRHSPunctuation(tok::r_brace, Tok.getLocation(), "{",
                         diag::err_expected_rbrace);
-    return;
+    return ExprResult(false);
   }
   
-  ParseAssignmentExpression();
+  return ParseAssignmentExpression();
 }
 
 
 
-Parser::ExprTy Parser::ParseExpression() {
-  ParseCastExpression(false);
-  return 0;
+Parser::ExprResult Parser::ParseExpression() {
+  return ParseCastExpression(false);
 }
 
 // Expr that doesn't include commas.
-void Parser::ParseAssignmentExpression() {
-  ParseExpression();
+Parser::ExprResult Parser::ParseAssignmentExpression() {
+  return ParseExpression();
 }
 
 /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
@@ -116,7 +115,9 @@
 /// [GNU]   offsetof-member-designator '[' expression ']'
 ///
 ///
-void Parser::ParseCastExpression(bool isUnaryExpression) {
+Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
+  ExprResult Res;
+  
   // This handles all of cast-expression, unary-expression, postfix-expression,
   // and primary-expression.  We handle them together like this for efficiency
   // and to simplify handling of an expression starting with a '(' token: which
@@ -133,8 +134,9 @@
     // not start a cast expression.
     ParenParseOption ParenExprType =
       isUnaryExpression ? CompoundLiteral : CastExpr;
-    ParseParenExpression(ParenExprType);
-
+    Res = ParseParenExpression(ParenExprType);
+    if (Res.isInvalid) return Res;
+    
     switch (ParenExprType) {
     case SimpleExpr:   break;    // Nothing else to do.
     case CompoundStmt: break;  // Nothing else to do.
@@ -145,11 +147,10 @@
     case CastExpr:
       // We parsed '(' type-name ')' and the thing after it wasn't a '{'.  Parse
       // the cast-expression that follows it next.
-      ParseCastExpression(false);
-      return;
+      return ParseCastExpression(false);
     }
     break;  // These can be followed by postfix-expr pieces.
-      
+    
     // primary-expression
   case tok::identifier:        // primary-expression: identifier
                                // constant: enumeration-constant
@@ -162,7 +163,8 @@
     ConsumeToken();
     break;
   case tok::string_literal:    // primary-expression: string-literal
-    ParseStringLiteralExpression();
+    Res = ParseStringLiteralExpression();
+    if (Res.isInvalid) return Res;
     break;
   case tok::kw___builtin_va_arg:
   case tok::kw___builtin_offsetof:
@@ -172,8 +174,7 @@
   case tok::plusplus:      // unary-expression: '++' unary-expression
   case tok::minusminus:    // unary-expression: '--' unary-expression
     ConsumeToken();
-    ParseCastExpression(true);
-    return;
+    return ParseCastExpression(true);
   case tok::amp:           // unary-expression: '&' cast-expression
   case tok::star:          // unary-expression: '*' cast-expression
   case tok::plus:          // unary-expression: '+' cast-expression
@@ -184,15 +185,13 @@
   case tok::kw___imag:     // unary-expression: '__real' cast-expression [GNU]
   //case tok::kw__extension__:  [TODO]
     ConsumeToken();
-    ParseCastExpression(false);
-    return;
+    return ParseCastExpression(false);
     
   case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression
                            // unary-expression: 'sizeof' '(' type-name ')'
   case tok::kw___alignof:  // unary-expression: '__alignof' unary-expression
                            // unary-expression: '__alignof' '(' type-name ')'
-    ParseSizeofAlignofExpression();
-    return;
+    return ParseSizeofAlignofExpression();
   case tok::ampamp:        // unary-expression: '&&' identifier
     Diag(Tok, diag::ext_gnu_address_of_label);
     ConsumeToken();
@@ -200,18 +199,12 @@
       ConsumeToken();
     } else {
       Diag(Tok, diag::err_expected_ident);
-      ConsumeToken(); // FIXME: Should just return error!
-      return;
+      return ExprResult(true);
     }
-    return;
+    return ExprResult(false);
   default:
     Diag(Tok, diag::err_expected_expression);
-    // Guarantee forward progress.
-    // FIXME: this dies on 'if ({1; });'.  Expression parsing should return a
-    // bool for failure.  This will cause higher-level parsing stuff to do the
-    // right thing.
-    ConsumeToken();
-    return;
+    return ExprResult(true);
   }
   
   // Now that the primary-expression piece of the postfix-expression has been
@@ -219,47 +212,47 @@
   SourceLocation Loc;
   while (1) {
     switch (Tok.getKind()) {
-      default:
-        return;
-      case tok::l_square:    // postfix-expression: p-e '[' expression ']'
-        Loc = Tok.getLocation();
-        ConsumeBracket();
-        ParseExpression();
-        // Match the ']'.
-        MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
-        break;
-        
-      case tok::l_paren:     // p-e: p-e '(' argument-expression-list[opt] ')'
-        Loc = Tok.getLocation();
-        ConsumeParen();
-        
-        while (1) {
-          // FIXME: This should be argument-expression!
-          ParseAssignmentExpression();
-          
-          if (Tok.getKind() != tok::comma)
-            break;
-          ConsumeToken();  // Next argument.
-        }
-          
-          // Match the ')'.
-          MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
-        break;
+    default:
+      return ExprResult(false);
+    case tok::l_square:    // postfix-expression: p-e '[' expression ']'
+      Loc = Tok.getLocation();
+      ConsumeBracket();
+      ParseExpression();
+      // Match the ']'.
+      MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
+      break;
+      
+    case tok::l_paren:     // p-e: p-e '(' argument-expression-list[opt] ')'
+      Loc = Tok.getLocation();
+      ConsumeParen();
+      
+      while (1) {
+        // FIXME: This should be argument-expression!
+        ParseAssignmentExpression();
         
-      case tok::arrow:       // postfix-expression: p-e '->' identifier
-      case tok::period:      // postfix-expression: p-e '.' identifier
-        ConsumeToken();
-        if (Tok.getKind() != tok::identifier) {
-          Diag(Tok, diag::err_expected_ident);
-          return;
-        }
-          ConsumeToken();
-        break;
+        if (Tok.getKind() != tok::comma)
+          break;
+        ConsumeToken();  // Next argument.
+      }
         
-      case tok::plusplus:    // postfix-expression: postfix-expression '++'
-      case tok::minusminus:  // postfix-expression: postfix-expression '--'
-        ConsumeToken();
-        break;
+      // Match the ')'.
+      MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
+      break;
+      
+    case tok::arrow:       // postfix-expression: p-e '->' identifier
+    case tok::period:      // postfix-expression: p-e '.' identifier
+      ConsumeToken();
+      if (Tok.getKind() != tok::identifier) {
+        Diag(Tok, diag::err_expected_ident);
+        return ExprResult(true);
+      }
+      ConsumeToken();
+      break;
+      
+    case tok::plusplus:    // postfix-expression: postfix-expression '++'
+    case tok::minusminus:  // postfix-expression: postfix-expression '--'
+      ConsumeToken();
+      break;
     }
   }
 }
@@ -270,7 +263,7 @@
 ///         'sizeof' '(' type-name ')'
 /// [GNU]   '__alignof' unary-expression
 /// [GNU]   '__alignof' '(' type-name ')'
-void Parser::ParseSizeofAlignofExpression() {
+Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
   assert((Tok.getKind() == tok::kw_sizeof ||
           Tok.getKind() == tok::kw___alignof) &&
          "Not a sizeof/alignof expression!");
@@ -278,15 +271,14 @@
   
   // If the operand doesn't start with an '(', it must be an expression.
   if (Tok.getKind() != tok::l_paren) {
-    ParseCastExpression(true);
-    return;
+    return ParseCastExpression(true);
   }
   
   // If it starts with a '(', we know that it is either a parenthesized
   // type-name, or it is a unary-expression that starts with a compound literal,
   // or starts with a primary-expression that is a parenthesized expression.
   ParenParseOption ExprType = CastExpr;
-  ParseParenExpression(ExprType);
+  return ParseParenExpression(ExprType);
 }
 
 /// ParseStringLiteralExpression - This handles the various token types that
@@ -295,7 +287,7 @@
 ///
 ///       primary-expression: [C99 6.5.1]
 ///         string-literal
-void Parser::ParseStringLiteralExpression() {
+Parser::ExprResult Parser::ParseStringLiteralExpression() {
   assert(isTokenStringLiteral() && "Not a string literal!");
   ConsumeStringToken();
   
@@ -303,6 +295,7 @@
   // considered to be strings.
   while (isTokenStringLiteral())
     ConsumeStringToken();
+  return ExprResult(false);
 }
 
 
@@ -319,10 +312,11 @@
 ///       cast-expression: [C99 6.5.4]
 ///         '(' type-name ')' cast-expression
 ///
-void Parser::ParseParenExpression(ParenParseOption &ExprType) {
+Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
   assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
   SourceLocation OpenLoc = Tok.getLocation();
   ConsumeParen();
+  ExprResult Result(false);
   
   if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace &&
       !getLang().NoExtensions) {
@@ -337,21 +331,25 @@
     MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
 
     if (Tok.getKind() == tok::l_brace) {
-      ParseInitializer();
+      Result = ParseInitializer();
       ExprType = CompoundLiteral;
     } else if (ExprType == CastExpr) {
       // Note that this doesn't parse the subsequence cast-expression.
       ExprType = CastExpr;
     } else {
       Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
-      return;
+      return ExprResult(true);
     }
-    return;
+    return Result;
   } else {
-    ParseExpression();
+    Result = ParseExpression();
     ExprType = SimpleExpr;
   }
   
   // Match the ')'.
-  MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
+  if (Result.isInvalid)
+    SkipUntil(tok::r_paren);
+  else
+    MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
+  return Result;
 }

Modified: cfe/cfe/trunk/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseStmt.cpp?rev=38873&r1=38872&r2=38873&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseStmt.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseStmt.cpp Wed Jul 11 11:25:22 2007
@@ -91,7 +91,13 @@
       Diag(Tok, diag::err_expected_statement);
     } else {
       // expression[opt] ';'
-      ParseExpression();
+      ExprResult Res = ParseExpression();
+      if (Res.isInvalid) {
+        // If the expression is invalid, skip ahead to the next semicolon.  Not
+        // doing this opens us up to the possibility of infinite loops if
+        // ParseExpression does not consume any tokens.
+        SkipUntil(tok::semi);
+      }
     }
     return;
     
@@ -407,6 +413,8 @@
   SourceLocation LParenLoc = Tok.getLocation();
   ConsumeParen();
   
+  ExprResult Value;
+  
   // Parse the first part of the for specifier.
   if (Tok.getKind() == tok::semi) {  // for (;
     // no first part, eat the ';'.
@@ -417,12 +425,12 @@
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
     ParseDeclaration(Declarator::ForContext);
   } else {
-    ParseExpression();
+    Value = ParseExpression();
   
     if (Tok.getKind() == tok::semi) {
       ConsumeToken();
     } else {
-      Diag(Tok, diag::err_expected_semi_for);
+      if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
       SkipUntil(tok::semi);
     }
   }
@@ -430,22 +438,24 @@
   // Parse the second part of the for specifier.
   if (Tok.getKind() == tok::semi) {  // for (...;;
     // no second part.
+    Value = ExprResult();
   } else {
-    ParseExpression();
+    Value = ParseExpression();
   }
   
   if (Tok.getKind() == tok::semi) {
     ConsumeToken();
   } else {
-    Diag(Tok, diag::err_expected_semi_for);
+    if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
     SkipUntil(tok::semi);
   }
   
   // Parse the third part of the for specifier.
   if (Tok.getKind() == tok::r_paren) {  // for (...;...;)
     // no third part.
+    Value = ExprResult();
   } else {
-    ParseExpression();
+    Value = ParseExpression();
   }
   
   // Match the ')'.

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=38873&r1=38872&r2=38873&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:25:22 2007
@@ -50,7 +50,15 @@
   
   // Parsing methods.
   void ParseTranslationUnit();
-  ExprTy ParseExpression();
+  
+  struct ExprResult {
+    ExprTy Val;
+    bool isInvalid;
+    
+    ExprResult(bool Invalid = false) : isInvalid(Invalid) {}
+  };
+  
+  ExprResult ParseExpression();
   
 
   // Diagnostics.
@@ -169,11 +177,11 @@
 
   //===--------------------------------------------------------------------===//
   // C99 6.5: Expressions.
-  //ExprTy ParseExpression();  // Above.
-  void ParseAssignmentExpression();  // Expr that doesn't include commas.
+  //ExprResult ParseExpression();  // Above.
+  ExprResult ParseAssignmentExpression();  // Expr that doesn't include commas.
 
-  void ParseCastExpression(bool isUnaryExpression);
-  void ParseSizeofAlignofExpression();
+  ExprResult ParseCastExpression(bool isUnaryExpression);
+  ExprResult ParseSizeofAlignofExpression();
   
   /// ParenParseOption - Control what ParseParenExpression will parse.
   enum ParenParseOption {
@@ -182,10 +190,10 @@
     CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
     CastExpr         // Also allow '(' type-name ')' <anything>
   };
-  void ParseParenExpression(ParenParseOption &ExprType);
-  void ParseStringLiteralExpression();
+  ExprResult ParseParenExpression(ParenParseOption &ExprType);
+  ExprResult ParseStringLiteralExpression();
   
-  void ParseInitializer();   // C99 6.7.8
+  ExprResult ParseInitializer();   // C99 6.7.8
   
   //===--------------------------------------------------------------------===//
   // C99 6.8: Statements and Blocks.





More information about the cfe-commits mailing list