[cfe-commits] r164085 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseExpr.cpp lib/Parse/Parser.cpp test/FixIt/fixit.c test/Parser/cxx-stmt.cpp test/Parser/cxx11-brace-initializers.cpp test/Parser/statements.c

Richard Smith richard-llvm at metafoo.co.uk
Mon Sep 17 17:52:05 PDT 2012


Author: rsmith
Date: Mon Sep 17 19:52:05 2012
New Revision: 164085

URL: http://llvm.org/viewvc/llvm-project?rev=164085&view=rev
Log:
If a comma operator is followed by a token which unambiguously indicates the
start of a statement or the end of a compound-statement, diagnose the comma as
a typo for a semicolon. Patch by Ahmed Bougacha! Additional test cases and
minor refactoring by me.

Added:
    cfe/trunk/test/Parser/cxx11-brace-initializers.cpp
Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/test/FixIt/fixit.c
    cfe/trunk/test/Parser/cxx-stmt.cpp
    cfe/trunk/test/Parser/statements.c

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Sep 17 19:52:05 2012
@@ -1221,6 +1221,9 @@
                                  bool isAddressOfOperand = false,
                                  TypeCastState isTypeCast = NotTypeCast);
 
+  /// Returns true if the next token cannot start an expression.
+  bool isNotExpressionStart();
+
   /// Returns true if the next token would start a postfix-expression
   /// suffix.
   bool isPostfixExpressionSuffixStart() {
@@ -1633,6 +1636,15 @@
   /// specifier or if we're not sure.
   bool isKnownToBeTypeSpecifier(const Token &Tok) const;
 
+  /// \brief Return true if we know that we are definitely looking at a
+  /// decl-specifier, and isn't part of an expression such as a function-style
+  /// cast. Return false if it's no a decl-specifier, or we're not sure.
+  bool isKnownToBeDeclarationSpecifier() {
+    if (getLangOpts().CPlusPlus)
+      return isCXXDeclarationSpecifier() == TPResult::True();
+    return isDeclarationSpecifier(true);
+  }
+
   /// isDeclarationStatement - Disambiguates between a declaration or an
   /// expression statement, when parsing function bodies.
   /// Returns true for declaration, false for expression.

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Sep 17 19:52:05 2012
@@ -265,6 +265,17 @@
   return Actions.ActOnConstantExpression(Res);
 }
 
+bool Parser::isNotExpressionStart() {
+  tok::TokenKind K = Tok.getKind();
+  if (K == tok::l_brace || K == tok::r_brace  ||
+      K == tok::kw_for  || K == tok::kw_while ||
+      K == tok::kw_if   || K == tok::kw_else  ||
+      K == tok::kw_goto || K == tok::kw_try)
+    return true;
+  // If this is a decl-specifier, we can't be at the start of an expression.
+  return isKnownToBeDeclarationSpecifier();
+}
+
 /// \brief Parse a binary expression that starts with \p LHS and has a
 /// precedence of at least \p MinPrec.
 ExprResult
@@ -285,6 +296,17 @@
     Token OpToken = Tok;
     ConsumeToken();
 
+    // Bail out when encountering a comma followed by a token which can't
+    // possibly be the start of an expression. For instance:
+    //   int f() { return 1, }
+    // We can't do this before consuming the comma, because
+    // isNotExpressionStart() looks at the token stream.
+    if (OpToken.is(tok::comma) && isNotExpressionStart()) {
+      PP.EnterToken(Tok);
+      Tok = OpToken;
+      return LHS;
+    }
+
     // Special case handling for the ternary operator.
     ExprResult TernaryMiddle(true);
     if (NextTokPrec == prec::Conditional) {

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Sep 17 19:52:05 2012
@@ -154,7 +154,8 @@
 
 static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
   switch (ExpectedTok) {
-  case tok::semi: return Tok.is(tok::colon); // : for ;
+  case tok::semi:
+    return Tok.is(tok::colon) || Tok.is(tok::comma); // : or , for ;
   default: return false;
   }
 }

Modified: cfe/trunk/test/FixIt/fixit.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.c?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit.c (original)
+++ cfe/trunk/test/FixIt/fixit.c Mon Sep 17 19:52:05 2012
@@ -81,6 +81,13 @@
   &a == &b ? oopsMoreCommas() : removeUnusedLabels(a[0]);
 }
 
+int commaAtEndOfStatement() {
+  int a = 1;
+  a = 5, // expected-error {{';'}}
+  int m = 5, // expected-error {{';'}}
+  return 0, // expected-error {{';'}}
+}
+
 int noSemiAfterLabel(int n) {
   switch (n) {
     default:

Modified: cfe/trunk/test/Parser/cxx-stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-stmt.cpp?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-stmt.cpp (original)
+++ cfe/trunk/test/Parser/cxx-stmt.cpp Mon Sep 17 19:52:05 2012
@@ -58,3 +58,11 @@
   asm volatile ("":: :"memory");
   asm volatile ("": ::"memory");
 }
+
+int f6() {
+  int k, // expected-note {{change this ',' to a ';' to call 'f6'}}
+  f6(), // expected-error {{expected ';'}} expected-warning {{interpreted as a function declaration}} expected-note {{replace paren}}
+  int n = 0, // expected-error {{expected ';'}}
+  return f5(), // ok
+  int(n);
+}

Added: cfe/trunk/test/Parser/cxx11-brace-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-brace-initializers.cpp?rev=164085&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx11-brace-initializers.cpp (added)
+++ cfe/trunk/test/Parser/cxx11-brace-initializers.cpp Mon Sep 17 19:52:05 2012
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+
+struct S {
+  S(int, int) {}
+};
+
+void f(int, S const&, int) {}
+
+void test1()
+{
+  S X1{1, 1,};
+  S X2 = {1, 1,};
+
+  f(0, {1, 1}, 0);
+}

Modified: cfe/trunk/test/Parser/statements.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/statements.c?rev=164085&r1=164084&r2=164085&view=diff
==============================================================================
--- cfe/trunk/test/Parser/statements.c (original)
+++ cfe/trunk/test/Parser/statements.c Mon Sep 17 19:52:05 2012
@@ -62,3 +62,18 @@
   // Should not skip '}' and produce a "expected '}'" error.
   undecl // expected-error {{use of undeclared identifier 'undecl'}}
 }
+
+int test9() {
+  int T[] = {1, 2, };
+
+  int X;
+  X = 0, // expected-error {{expected ';' after expression}}
+    {
+    }
+
+  X = 0, // expected-error {{expected ';' after expression}}
+  if (0)
+    ;
+
+  return 4, // expected-error {{expected ';' after return statement}}
+}





More information about the cfe-commits mailing list