aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Parse/Parser.h10
-rw-r--r--lib/Parse/ParseDecl.cpp8
-rw-r--r--lib/Parse/ParseExprCXX.cpp8
-rw-r--r--lib/Parse/Parser.cpp25
-rw-r--r--test/FixIt/fixit.cpp6
6 files changed, 40 insertions, 19 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 7675a566eb..fa57dd2a91 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -156,6 +156,8 @@ 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_invalid_plusequal_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 31b5022166..c36f34af8c 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -288,10 +288,12 @@ private:
Tok.getKind() == tok::utf32_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);
+ /// \brief Returns true if the current token is FoundToken. This token
+ /// will be assumed a typo. A diagnostic will be emitted with DiagID with a
+ /// a fixit to replace the current token with ExpectedToken.
+ bool CreateTokenReplacement(tok::TokenKind ExpectedToken,
+ tok::TokenKind FoundToken,
+ 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
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1c7c45e2bd..0de8c53d90 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1269,8 +1269,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D,
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
// Parse declarator '=' initializer.
- if (isTokenEqualOrMistypedEqualEqual(
- diag::err_invalid_equalequal_after_declarator)) {
+ // If a '==' or '+=' is found, suggest a fixit to '='.
+ if (Tok.is(tok::equal) ||
+ CreateTokenReplacement(tok::equal, tok::equalequal,
+ diag::err_invalid_equalequal_after_declarator) ||
+ CreateTokenReplacement(tok::equal, tok::plusequal,
+ diag::err_invalid_plusequal_after_declarator)) {
ConsumeToken();
if (Tok.is(tok::kw_delete)) {
if (D.isFunctionDeclarator())
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index f1cedfebfd..831c446fbb 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1259,8 +1259,12 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut,
ExprOut = ExprError();
// '=' assignment-expression
- if (isTokenEqualOrMistypedEqualEqual(
- diag::err_invalid_equalequal_after_declarator)) {
+ // If a '==' or '+=' is found, suggest a fixit to '='.
+ if (Tok.is(tok::equal) ||
+ CreateTokenReplacement(tok::equal, tok::equalequal,
+ diag::err_invalid_equalequal_after_declarator) ||
+ CreateTokenReplacement(tok::equal, tok::plusequal,
+ diag::err_invalid_plusequal_after_declarator)) {
ConsumeToken();
ExprResult AssignExpr(ParseAssignmentExpression());
if (!AssignExpr.isInvalid())
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 501e50c1e7..6342b10568 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1401,18 +1401,21 @@ 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;
- }
+bool Parser::CreateTokenReplacement(tok::TokenKind ExpectedToken,
+ tok::TokenKind FoundToken,
+ unsigned DiagID) {
+ if (Tok.isNot(FoundToken))
+ return false;
- return Tok.is(tok::equal);
+ // We have FoundToken in a context that we would expect an ExpectedToken.
+ // The user probably made a typo, intending to type ExpectedToken.
+ // Emit diagnostic, fixit hint to turn ReplaceToken -> ExpectedToken
+ // and continue as if the user typed ExpectedToken.
+ Tok.setKind(ExpectedToken);
+ Diag(Tok, DiagID)
+ << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()),
+ getTokenSimpleSpelling(ExpectedToken));
+ return true;
}
SourceLocation Parser::handleUnexpectedCodeCompletionToken() {
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index f7bf35b09e..63726b9b6e 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -69,13 +69,19 @@ class C {
namespace rdar8488464 {
int x == 0; // expected-error {{invalid '==' at end of declaration; did you mean '='?}}
+int y += 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;
+ int y += 0; // expected-error {{invalid '+=' at end of declaration; did you mean '='?}}
+ (void)y;
if (int x == 0) { // expected-error {{invalid '==' at end of declaration; did you mean '='?}}
(void)x;
}
+ if (int y += 0) { // expected-error {{invalid '+=' at end of declaration; did you mean '='?}}
+ (void)y;
+ }
}
}