diff --git a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp @@ -18,19 +18,32 @@ namespace readability { namespace { -tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM, - const ASTContext *Context) { - Token Tok; +bool tryGetTokenKind(SourceLocation Loc, const SourceManager &SM, + const ASTContext *Context, tok::TokenKind &Kind) { + Kind = tok::NUM_TOKENS; SourceLocation Beginning = Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts()); + + Token Tok; const bool Invalid = Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts()); - assert(!Invalid && "Expected a valid token."); + if (!Invalid) { + Kind = Tok.getKind(); + } + + return !Invalid; +} + +tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM, + const ASTContext *Context) { + tok::TokenKind Kind; + if (tryGetTokenKind(Loc, SM, Context, Kind)) { + return Kind; + } - if (Invalid) - return tok::NUM_TOKENS; + assert(false && "Expected a valid token."); - return Tok.getKind(); + return tok::NUM_TOKENS; } SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc, @@ -58,8 +71,21 @@ // Loc points to the beginning of the last (non-comment non-ws) token // before end or ';'. assert(Loc.isValid()); - bool SkipEndWhitespaceAndComments = true; tok::TokenKind TokKind = getTokenKind(Loc, SM, Context); + + // We need to check that it is not 'InitListExpr' which ends with + // the tokens '};' because it will break the following analysis + tok::TokenKind NextTokKind; + SourceLocation NextLoc = + Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts()); + if (tryGetTokenKind(NextLoc, SM, Context, NextTokKind)) { + if (TokKind == tok::r_brace && NextTokKind == tok::semi) { + Loc = NextLoc; + TokKind = NextTokKind; + } + } + + bool SkipEndWhitespaceAndComments = true; if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi || TokKind == tok::r_brace) { // If we are at ";" or "}", we found the last token. We could use as well diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp @@ -204,3 +204,28 @@ // CHECK-FIXES-NEXT: {{^ ;$}} // CHECK-FIXES-NEXT: {{^}$}} } + +class X {}; +X test_initListExpr() +{ + if (cond("x")) return {}; + else return {}; + // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces + // CHECK-FIXES: if (cond("x")) { return {}; + // CHECK-FIXES: } else { + // CHECK-FIXES: return {}; + // CHECK-FIXES: } + + if (cond("y1")) + if (cond("y2") && cond("y3")) + return {}; + else + return {}; + // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: statement should be inside braces + // CHECK-FIXES: if (cond("y1")) { + // CHECK-FIXES: if (cond("y2") && cond("y3")) { + // CHECK-FIXES: return {}; + // CHECK-FIXES: } else { + // CHECK-FIXES: return {}; + // CHECK-FIXES: } +}