]> granicus.if.org Git - clang/commitdiff
Disambiguate between a declaration or expression for the 'condition' part of a if...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 5 Oct 2008 15:03:47 +0000 (15:03 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 5 Oct 2008 15:03:47 +0000 (15:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57109 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTentative.cpp
test/SemaCXX/decl-expr-ambiguity.cpp

index aa49530b0e15935059e9d11466e93729fd54ea29..df5e59fda938ac1cdbaf6e21b15aab24c04fe7eb 100644 (file)
@@ -610,6 +610,12 @@ private:
   /// the function returns true to let the declaration parsing code handle it.
   bool isCXXFunctionDeclarator();
 
+  /// isCXXConditionDeclaration - Disambiguates between a declaration or an
+  /// expression for a condition of a if/switch/while/for statement.
+  /// If during the disambiguation process a parsing error is encountered,
+  /// the function returns true to let the declaration parsing code handle it.
+  bool isCXXConditionDeclaration();
+
   /// isCXXDeclarationSpecifier - Returns TPR_true if it is a declaration
   /// specifier, TPR_false if it is not, TPR_ambiguous if it could be either
   /// a decl-specifier or a function-style cast, and TPR_error if a parsing
index 28071b6e29dff0f95e8a55f77edec0cdfac02caa..8b4db309508468cdb620343b5ef58897fae92be9 100644 (file)
@@ -162,7 +162,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
 ///             '=' assignment-expression
 ///
 Parser::ExprResult Parser::ParseCXXCondition() {
-  if (!isDeclarationSpecifier())
+  if (!isCXXConditionDeclaration())
     return ParseExpression(); // expression
 
   SourceLocation StartLoc = Tok.getLocation();
index 5e4888f699058448af3116596ceeb29531ac093d..95512a62693e2dbb73a73cb3d8a7587b4208a5e0 100644 (file)
@@ -225,6 +225,60 @@ Parser::TentativeParsingResult Parser::TryParseInitDeclaratorList() {
   return TPR_ambiguous;
 }
 
+/// isCXXConditionDeclaration - Disambiguates between a declaration or an
+/// expression for a condition of a if/switch/while/for statement.
+/// If during the disambiguation process a parsing error is encountered,
+/// the function returns true to let the declaration parsing code handle it.
+///
+///       condition:
+///         expression
+///         type-specifier-seq declarator '=' assignment-expression
+/// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
+///             '=' assignment-expression
+///
+bool Parser::isCXXConditionDeclaration() {
+  TentativeParsingResult TPR = isCXXDeclarationSpecifier();
+  if (TPR != TPR_ambiguous)
+    return TPR != TPR_false; // Returns true for TPR_true or TPR_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(false/*mayBeAbstract*/);
+
+  PA.Revert();
+
+  // In case of an error, let the declaration parsing code handle it.
+  if (TPR == TPR_error)
+    return true;
+
+  if (TPR == TPR_ambiguous) {
+    // '='
+    // [GNU] simple-asm-expr[opt] attributes[opt]
+    if (Tok.is(tok::equal)  ||
+        Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
+      TPR = TPR_true;
+    else
+      TPR = TPR_false;
+  }
+
+  assert(TPR == TPR_true || TPR == TPR_false);
+  return TPR == TPR_true;
+}
+
 ///         declarator:
 ///           direct-declarator
 ///           ptr-operator declarator
index 48e132097e46c7d9900cbcd43a65d19c118a9d70..5b4ddbea0b841a08428cc9c1fc7f635ba5eefc6d 100644 (file)
@@ -11,6 +11,7 @@ void f() {
   __extension__ int(a)++; // expected-error {{invalid lvalue in increment/decrement expression}}
   typeof(int)(a,5)<<a; // expected-error {{function-style cast to a builtin type can only take one argument}}
   void(a), ++a; // expected-warning {{statement was disambiguated as expression}} expected-warning {{expression result unused}}
+  if (int(a)+1) {}
 
   // Declarations.
   T(*d)(int(p)); // expected-warning {{statement was disambiguated as declaration}} expected-error {{previous definition is here}}