[cfe-commits] r57131 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Parse/ParseTentative.cpp test/SemaCXX/decl-expr-ambiguity.cpp

Argiris Kirtzidis akyrtzi at gmail.com
Sun Oct 5 12:56:23 PDT 2008


Author: akirtzidis
Date: Sun Oct  5 14:56:22 2008
New Revision: 57131

URL: http://llvm.org/viewvc/llvm-project?rev=57131&view=rev
Log:
Handle ambiguities between expressions and type-ids that occur inside parentheses, e.g.:

sizeof(int()) -> "int()" is type-id
sizeof(int()+1) -> "int()+1" is expression.

Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseTentative.cpp
    cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Oct  5 14:56:22 2008
@@ -591,6 +591,15 @@
     return isDeclarationSpecifier();
   }
 
+  /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
+  /// whether the parens contain an expression or a type-id.
+  /// Returns true for a type-id and false for an expression.
+  bool isTypeIdInParens() {
+    if (getLang().CPlusPlus)
+      return isCXXTypeIdInParens();
+    return isTypeSpecifierQualifier();
+  }
+
   /// isCXXDeclarationStatement - C++-specialized function that disambiguates
   /// between a declaration or an expression statement, when parsing function
   /// bodies. Returns true for declaration, false for expression.
@@ -617,6 +626,13 @@
   /// the function returns true to let the declaration parsing code handle it.
   bool isCXXConditionDeclaration();
 
+  /// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to
+  /// know whether the parens contain an expression or a type-id.
+  /// Returns true for a type-id and false for an expression.
+  /// If during the disambiguation process a parsing error is encountered,
+  /// the function returns true to let the declaration parsing code handle it.
+  bool isCXXTypeIdInParens();
+
   /// TPResult - Used as the result value for functions whose purpose is to
   /// disambiguate C++ constructs by "tentatively parsing" them.
   /// This is a class instead of a simple enum because the implicit enum-to-bool
@@ -659,7 +675,7 @@
   TPResult TryParseSimpleDeclaration();
   TPResult TryParseTypeofSpecifier();
   TPResult TryParseInitDeclaratorList();
-  TPResult TryParseDeclarator(bool mayBeAbstract);
+  TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
   TPResult TryParseParameterDeclarationClause();
   TPResult TryParseFunctionDeclarator();
   TPResult TryParseBracketDeclarator();

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sun Oct  5 14:56:22 2008
@@ -1581,7 +1581,7 @@
 
   SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
   
-  if (isTypeSpecifierQualifier()) {
+  if (isTypeIdInParens()) {
     TypeTy *Ty = ParseTypeName();
 
     assert(Ty && "Parser::ParseTypeofSpecifier(): missing type");

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sun Oct  5 14:56:22 2008
@@ -981,7 +981,7 @@
     if (!Stmt.isInvalid && Tok.is(tok::r_paren))
       Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.Val, Tok.getLocation());
     
-  } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
+  } else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
     // Otherwise, this is a compound literal expression or cast expression.
     TypeTy *Ty = ParseTypeName();
 

Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=57131&r1=57130&r2=57131&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Sun Oct  5 14:56:22 2008
@@ -282,6 +282,58 @@
   return TPR == TPResult::True();
 }
 
+/// isCXXTypeIdInParens - Assumes that a '(' was parsed and now we want to
+/// know whether the parens contain an expression or a type-id.
+/// Returns true for a type-id and false for an expression.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+/// type-id:
+///   type-specifier-seq abstract-declarator[opt]
+///
+bool Parser::isCXXTypeIdInParens() {
+  TPResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPResult::Ambiguous())
+    return TPR != TPResult::False(); // Returns true for TPResult::True() or
+                                     // TPResult::Error().
+
+  // FIXME: Add statistics about the number of ambiguous statements encountered
+  // and how they were resolved (number of declarations+number of expressions).
+
+  // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
+  // We need tentative parsing...
+
+  TentativeParsingAction PA(*this);
+
+  // type-specifier-seq
+  if (Tok.is(tok::kw_typeof))
+    TryParseTypeofSpecifier();
+  else
+    ConsumeToken();
+  assert(Tok.is(tok::l_paren) && "Expected '('");
+
+  // declarator
+  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPResult::Error())
+    TPR = TPResult::True();
+
+  if (TPR == TPResult::Ambiguous()) {
+    // We are supposed to be inside parens, so if after the abstract declarator
+    // we encounter a ')' this is a type-id, otherwise it's an expression.
+    if (Tok.is(tok::r_paren))
+      TPR = TPResult::True();
+    else
+      TPR = TPResult::False();
+  }
+
+  PA.Revert();
+
+  assert(TPR == TPResult::True() || TPR == TPResult::False());
+  return TPR == TPResult::True();
+}
+
 ///         declarator:
 ///           direct-declarator
 ///           ptr-operator declarator
@@ -332,7 +384,8 @@
 ///           '~' class-name                                              [TODO]
 ///           template-id                                                 [TODO]
 ///
-Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract) {
+Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
+                                            bool mayHaveIdentifier) {
   // declarator:
   //   direct-declarator
   //   ptr-operator declarator
@@ -353,7 +406,7 @@
   // direct-declarator:
   // direct-abstract-declarator:
 
-  if (Tok.is(tok::identifier)) {
+  if (Tok.is(tok::identifier) && mayHaveIdentifier) {
     // declarator-id
     ConsumeToken();
   } else if (Tok.is(tok::l_paren)) {
@@ -370,7 +423,7 @@
       ConsumeParen();
       if (Tok.is(tok::kw___attribute))
         return TPResult::True(); // attributes indicate declaration
-      TPResult TPR = TryParseDeclarator(mayBeAbstract);
+      TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
       if (TPR != TPResult::Ambiguous())
         return TPR;
       if (Tok.isNot(tok::r_paren))

Modified: cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp?rev=57131&r1=57130&r2=57131&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-expr-ambiguity.cpp Sun Oct  5 14:56:22 2008
@@ -13,6 +13,8 @@
   void(a), ++a; // expected-warning {{statement was disambiguated as expression}} expected-warning {{expression result unused}}
   if (int(a)+1) {}
   for (int(a)+1;;) {}
+  a = sizeof(int()+1);
+  typeof(int()+1) a2;
 
   // Declarations.
   T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}}





More information about the cfe-commits mailing list