[PATCH] D74214: [clang-tidy] Fix PR#34798 'readability-braces-around-statements breaks statements containing braces.'

Karasev Nikita via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 7 04:34:32 PST 2020


f00kat created this revision.
f00kat added reviewers: aaron.ballman, alexfh.
f00kat added projects: clang, clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun.

In method 'BracesAroundStatementsCheck::checkStmt' the call 'Lexer::makeFileCharRange(line 253)' return different EndSourceLocation for different statements.

  CharSourceRange FileRange = Lexer::makeFileCharRange(
        CharSourceRange::getTokenRange(S->getSourceRange()), SM,
        Context->getLangOpts());

For example

  class c {};
  c test()
  {
  	if (true)
  		return {};
  	if (true)
  		bool b[2] = { true, true };
  }

In case

  return {};

FileRange.getEnd() will be ';'
In case

  bool b[2] = { true, true };

FileRange.getEnd() will be '\r'

Before call 'findEndLocation' we do this

  const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);

so 'findEndLocation' received '}' in the first case and ';' in the second what breaks the logic of 'findEndLocation'.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D74214

Files:
  clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp


Index: clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-braces-around-statements.cpp
+++ 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: }
+}
Index: clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
+++ 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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D74214.243131.patch
Type: text/x-patch
Size: 3500 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200207/44a41a29/attachment.bin>


More information about the cfe-commits mailing list