[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