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

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


Author: sabre
Date: Wed Jul 11 11:25:31 2007
New Revision: 38890

URL: http://llvm.org/viewvc/llvm-project?rev=38890&view=rev
Log:
Implement parsing of array declarators like:
int Array[*(int*)P+A];

Modified:
    cfe/cfe/trunk/Parse/ParseDecl.cpp
    cfe/cfe/trunk/Parse/ParseExpr.cpp
    cfe/cfe/trunk/Parse/Parser.cpp
    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=38890&r1=38889&r2=38890&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:25:31 2007
@@ -717,7 +717,7 @@
   
   // Handle "direct-declarator [ type-qual-list[opt] * ]".
   bool isStar = false;
-  void *NumElts = 0;
+  ExprResult NumElements(false);
   if (Tok.getKind() == tok::star) {
     // Remember the '*' token, in case we have to un-get it.
     LexerToken StarTok = Tok;
@@ -733,22 +733,19 @@
     } else {
       // Otherwise, the * must have been some expression (such as '*ptr') that
       // started an assignment-expr.  We already consumed the token, but now we
-      // need to reparse it.
-      // FIXME: We must push 'StarTok' and Tok back into the preprocessor as a
-      // macro expansion context, so they will be read again. It is basically
-      // impossible to refudge the * in otherwise, due to cases like X[*p + 4].
-      assert(0 && "FIXME: int X[*p] unimplemented");
+      // need to reparse it.  This handles cases like 'X[*p + 4]'
+      NumElements = ParseAssignmentExpressionWithLeadingStar(StarTok);
     }
   } else if (Tok.getKind() != tok::r_square) {
     // Parse the assignment-expression now.
-    ExprResult Res = ParseAssignmentExpression();
-    if (Res.isInvalid) {
-      // If the expression was invalid, skip it.
-      SkipUntil(tok::r_square);
-      return;
-    }
-    
-    NumElts = /*TODO: parse array size expr*/0;
+    NumElements = ParseAssignmentExpression();
+  }
+  
+  // If there was an error parsing the assignment-expression, recover.
+  if (NumElements.isInvalid) {
+    // If the expression was invalid, skip it.
+    SkipUntil(tok::r_square);
+    return;
   }
   
   MatchRHSPunctuation(tok::r_square, StartLoc, "[", diag::err_expected_rsquare);
@@ -757,13 +754,13 @@
   // it was not a constant expression.
   if (!getLang().C99) {
     // TODO: check C90 array constant exprness.
-    if (isStar || StaticLoc.isValid() || 0/*NumElts is constantexpr*/)
+    if (isStar || StaticLoc.isValid() || 0/*FIXME: NumElts is constantexpr*/)
       Diag(StartLoc, diag::ext_c99_array_usage);
   }
   
   // Remember that we parsed a pointer type, and remember the type-quals.
   D.AddTypeInfo(DeclaratorTypeInfo::getArray(DS.TypeQualifiers,
                                              StaticLoc.isValid(), isStar,
-                                             NumElts, StartLoc));
+                                             NumElements.Val, StartLoc));
 }
 

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

==============================================================================
--- cfe/cfe/trunk/Parse/ParseExpr.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseExpr.cpp Wed Jul 11 11:25:31 2007
@@ -233,6 +233,39 @@
   return ParseRHSOfBinaryExpression(Res, prec::Comma);
 }
 
+/// ParseAssignmentExpressionWithLeadingStar - This special purpose method is
+/// used in contexts where we have already consumed a '*' (which we saved in
+/// 'Tok'), then discovered that the '*' was really the leading token of an
+/// expression.  For example, in "*(int*)P+B", we consumed "*" (which is
+/// now in 'Tok') and the current token is "(".
+Parser::ExprResult Parser::
+ParseAssignmentExpressionWithLeadingStar(const LexerToken &Tok) {
+  // We know that 'Tok' must correspond to this production:
+  //  unary-expression: unary-operator cast-expression
+  // where 'unary-operator' is '*'.
+  
+  // Parse the cast-expression that follows the '*'.  This will parse the
+  // "*(int*)P" part of "*(int*)P+B".
+  ExprResult Res = ParseCastExpression(false);
+  if (Res.isInvalid) return Res;
+
+  // TODO: Combine Tok + Res to get the new AST.
+  
+  // We have to parse an entire cast-expression before starting the
+  // ParseRHSOfBinaryExpression method (which parses any trailing binops). Since
+  // we know that the only production above us is the cast-expression
+  // production, and because the only alternative productions start with a '('
+  // token (we know we had a '*'), there is no work to do to get a whole
+  // cast-expression.
+  
+  // At this point, the "*(int*)P" part of "*(int*)P+B" has been consumed. Once
+  // this is done, we can invoke ParseRHSOfBinaryExpression to consume any
+  // trailing operators (e.g. "+" in this example) and connected chunks of the
+  // assignment-expression.
+  return ParseRHSOfBinaryExpression(Res, prec::Assignment);
+}
+
+
 /// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
 /// LHS and has a precedence of at least MinPrec.
 Parser::ExprResult
@@ -309,7 +342,6 @@
   }
 }
 
-
 /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
 /// true, parse a unary-expression.
 ///

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

==============================================================================
--- cfe/cfe/trunk/Parse/Parser.cpp (original)
+++ cfe/cfe/trunk/Parse/Parser.cpp Wed Jul 11 11:25:31 2007
@@ -224,7 +224,7 @@
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.getKind() == tok::semi)
-    assert(0 && "Unimp!");
+    assert(0 && "Unimp!");   // FIXME: implement 'struct foo;'.
   
   
   // Parse the first declarator.

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=38890&r1=38889&r2=38890&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:25:31 2007
@@ -179,6 +179,7 @@
   // C99 6.5: Expressions.
   //ExprResult ParseExpression();  // Above.
   ExprResult ParseExpressionWithLeadingIdentifier(const LexerToken &Tok);
+  ExprResult ParseAssignmentExpressionWithLeadingStar(const LexerToken &Tok);
   ExprResult ParseAssignmentExpression();  // Expr that doesn't include commas.
 
   ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec);





More information about the cfe-commits mailing list