diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-10-08 02:39:23 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-10-08 02:39:23 +0000 |
commit | a6eb5f81d13bacac01faff70a947047725b4413f (patch) | |
tree | bcaa31849ec52affed208d74b4a6cd821785fb06 | |
parent | b4eb64d8426c0eaa58d398961e0e74ff85063d7c (diff) |
When we encounter a '==' in a context expecting a '=', assume the user made a typo:
t.c:1:7: error: invalid '==' at end of declaration; did you mean '='?
int x == 0;
^~
=
Implements rdar://8488464.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116035 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 14 | ||||
-rw-r--r-- | test/FixIt/fixit.cpp | 12 |
6 files changed, 38 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 5751ae90f2..430ed9f011 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -112,6 +112,8 @@ def err_expected_fn_body : Error< def err_expected_method_body : Error<"expected method body">; def err_invalid_token_after_toplevel_declarator : Error< "expected ';' after top level declarator">; +def err_invalid_equalequal_after_declarator : Error< + "invalid '==' at end of declaration; did you mean '='?">; def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; def err_expected_lparen_after_id : Error<"expected '(' after %0">; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 1cdeef727e..f1548460e3 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -236,6 +236,11 @@ private: Tok.getKind() == tok::wide_string_literal; } + /// \brief Returns true if the current token is a '=' or '==' and + /// false otherwise. If it's '==', we assume that it's a typo and we emit + /// DiagID and a fixit hint to turn '==' -> '='. + bool isTokenEqualOrMistypedEqualEqual(unsigned DiagID); + /// ConsumeToken - Consume the current 'peek token' and lex the next one. /// This does not work with all kinds of tokens: strings and specific other /// tokens must be consumed with custom methods below. This returns the diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 89b41828b0..e6a4b91e2d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -594,7 +594,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, } // Parse declarator '=' initializer. - if (Tok.is(tok::equal)) { + if (isTokenEqualOrMistypedEqualEqual( + diag::err_invalid_equalequal_after_declarator)) { ConsumeToken(); if (Tok.is(tok::kw_delete)) { SourceLocation DelLoc = ConsumeToken(); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e8b921b8f7..77cb4492f6 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -821,9 +821,10 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, DeclaratorInfo); DeclOut = Dcl.get(); ExprOut = ExprError(); - + // '=' assignment-expression - if (Tok.is(tok::equal)) { + if (isTokenEqualOrMistypedEqualEqual( + diag::err_invalid_equalequal_after_declarator)) { SourceLocation EqualLoc = ConsumeToken(); ExprResult AssignExpr(ParseAssignmentExpression()); if (!AssignExpr.isInvalid()) diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 33c7b7dcb4..8084088afc 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1156,6 +1156,20 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { return false; } +bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) { + if (Tok.is(tok::equalequal)) { + // We have '==' in a context that we would expect a '='. + // The user probably made a typo, intending to type '='. Emit diagnostic, + // fixit hint to turn '==' -> '=' and continue as if the user typed '='. + Diag(Tok, DiagID) + << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), + getTokenSimpleSpelling(tok::equal)); + return true; + } + + return Tok.is(tok::equal); +} + void Parser::CodeCompletionRecovery() { for (Scope *S = getCurScope(); S; S = S->getParent()) { if (S->getFlags() & Scope::FnScope) { diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index 95d8a88af1..1993425c95 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -71,3 +71,15 @@ class C { int C::foo(); }; +namespace rdar8488464 { +int x == 0; // expected-error {{invalid '==' at end of declaration; did you mean '='?}} + +void f() { + int x == 0; // expected-error {{invalid '==' at end of declaration; did you mean '='?}} + (void)x; + if (int x == 0) { // expected-error {{invalid '==' at end of declaration; did you mean '='?}} + (void)x; + } +} +} + |