[clang-tools-extra] r259362 - Add a new check, readability-redundant-control-flow, that check for some forms of redundant control flow statements. Currently checks for return statements at the end of a function with a void return type and continue statements at the end of looping statements.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 1 07:31:16 PST 2016


Author: aaronballman
Date: Mon Feb  1 09:31:15 2016
New Revision: 259362

URL: http://llvm.org/viewvc/llvm-project?rev=259362&view=rev
Log:
Add a new check, readability-redundant-control-flow, that check for some forms of redundant control flow statements. Currently checks for return statements at the end of a function with a void return type and continue statements at the end of looping statements.

Patch by Richard Thomson.

Added:
    clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.cpp
    clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/readability-redundant-control-flow.rst
    clang-tools-extra/trunk/test/clang-tidy/readability-redundant-control-flow.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=259362&r1=259361&r2=259362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Mon Feb  1 09:31:15 2016
@@ -11,6 +11,7 @@ add_clang_library(clangTidyReadabilityMo
   NamedParameterCheck.cpp
   NamespaceCommentCheck.cpp
   ReadabilityTidyModule.cpp
+  RedundantControlFlowCheck.cpp
   RedundantStringCStrCheck.cpp
   RedundantSmartptrGetCheck.cpp
   SimplifyBooleanExprCheck.cpp

Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=259362&r1=259361&r2=259362&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Mon Feb  1 09:31:15 2016
@@ -18,6 +18,7 @@
 #include "ImplicitBoolCastCheck.h"
 #include "InconsistentDeclarationParameterNameCheck.h"
 #include "NamedParameterCheck.h"
+#include "RedundantControlFlowCheck.h"
 #include "RedundantSmartptrGetCheck.h"
 #include "RedundantStringCStrCheck.h"
 #include "SimplifyBooleanExprCheck.h"
@@ -44,6 +45,8 @@ public:
         "readability-implicit-bool-cast");
     CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
         "readability-inconsistent-declaration-parameter-name");
+    CheckFactories.registerCheck<RedundantControlFlowCheck>(
+        "readability-redundant-control-flow");
     CheckFactories.registerCheck<UniqueptrDeleteReleaseCheck>(
         "readability-uniqueptr-delete-release");
     CheckFactories.registerCheck<readability::NamedParameterCheck>(

Added: clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.cpp?rev=259362&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.cpp Mon Feb  1 09:31:15 2016
@@ -0,0 +1,99 @@
+//===--- RedundantControlFlowCheck.cpp - clang-tidy------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantControlFlowCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+const char *const RedundantReturnDiag = "redundant return statement at the end "
+                                        "of a function with a void return type";
+const char *const RedundantContinueDiag = "redundant continue statement at the "
+                                          "end of loop statement";
+
+bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) {
+  return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc);
+}
+
+} // namespace
+
+void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      functionDecl(isDefinition(), returns(voidType()),
+                   has(compoundStmt(hasAnySubstatement(returnStmt(
+                                        unless(has(expr()))))).bind("return"))),
+      this);
+  auto CompoundContinue =
+      has(compoundStmt(hasAnySubstatement(continueStmt())).bind("continue"));
+  Finder->addMatcher(
+      stmt(anyOf(forStmt(), cxxForRangeStmt(), whileStmt(), doStmt()),
+           CompoundContinue),
+      this);
+}
+
+void RedundantControlFlowCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Return = Result.Nodes.getNodeAs<CompoundStmt>("return"))
+    checkRedundantReturn(Result, Return);
+  else if (const auto *Continue =
+               Result.Nodes.getNodeAs<CompoundStmt>("continue"))
+    checkRedundantContinue(Result, Continue);
+}
+
+void RedundantControlFlowCheck::checkRedundantReturn(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Block) {
+  CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin();
+  if (const auto *Return = dyn_cast<ReturnStmt>(*last))
+    issueDiagnostic(Result, Block, Return->getSourceRange(),
+                    RedundantReturnDiag);
+}
+
+void RedundantControlFlowCheck::checkRedundantContinue(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Block) {
+  CompoundStmt::const_reverse_body_iterator last = Block->body_rbegin();
+  if (const auto *Continue = dyn_cast<ContinueStmt>(*last))
+    issueDiagnostic(Result, Block, Continue->getSourceRange(),
+                    RedundantContinueDiag);
+}
+
+void RedundantControlFlowCheck::issueDiagnostic(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *const Block,
+    const SourceRange &StmtRange, const char *const Diag) {
+  SourceManager &SM = *Result.SourceManager;
+  if (isLocationInMacroExpansion(SM, StmtRange.getBegin()))
+    return;
+
+  CompoundStmt::const_reverse_body_iterator Previous = ++Block->body_rbegin();
+  SourceLocation Start;
+  if (Previous != Block->body_rend())
+    Start = Lexer::findLocationAfterToken(
+        dyn_cast<Stmt>(*Previous)->getLocEnd(), tok::semi, SM,
+        Result.Context->getLangOpts(),
+        /*SkipTrailingWhitespaceAndNewLine=*/true);
+  else
+    Start = StmtRange.getBegin();
+  auto RemovedRange = CharSourceRange::getCharRange(
+      Start,
+      Lexer::findLocationAfterToken(StmtRange.getEnd(), tok::semi, SM,
+                                    Result.Context->getLangOpts(),
+                                    /*SkipTrailingWhitespaceAndNewLine=*/true));
+
+  diag(StmtRange.getBegin(), Diag) << FixItHint::CreateRemoval(RemovedRange);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.h?rev=259362&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/RedundantControlFlowCheck.h Mon Feb  1 09:31:15 2016
@@ -0,0 +1,51 @@
+//===--- RedundantControlFlowCheck.h - clang-tidy----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// Eliminates redundant `return` statements at the end of a function that
+/// returns `void`.
+///
+/// Eliminates redundant `continue` statements at the end of a loop body.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-control-flow.html
+class RedundantControlFlowCheck : public ClangTidyCheck {
+public:
+  RedundantControlFlowCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void
+  checkRedundantReturn(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const CompoundStmt *Block);
+
+  void
+  checkRedundantContinue(const ast_matchers::MatchFinder::MatchResult &Result,
+                         const CompoundStmt *Block);
+
+  void issueDiagnostic(const ast_matchers::MatchFinder::MatchResult &Result,
+                       const CompoundStmt *Block, const SourceRange &StmtRange,
+                       const char *Diag);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_CONTROL_FLOW_H

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=259362&r1=259361&r2=259362&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Mon Feb  1 09:31:15 2016
@@ -86,6 +86,7 @@ Clang-Tidy Checks
    readability-implicit-bool-cast
    readability-inconsistent-declaration-parameter-name
    readability-named-parameter
+   readability-redundant-control-flow
    readability-redundant-smartptr-get
    readability-redundant-string-cstr
    readability-simplify-boolean-expr

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-redundant-control-flow.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-redundant-control-flow.rst?rev=259362&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-redundant-control-flow.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-redundant-control-flow.rst Mon Feb  1 09:31:15 2016
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - readability-redundant-control-flow
+
+readability-redundant-control-flow
+==================================
+
+This check looks for procedures (functions returning no value) with `return`
+statements at the end of the function.  Such `return` statements are redundant.
+
+Loop statements (`for`, `while`, `do while`) are checked for redundant
+`continue` statements at the end of the loop body.
+
+Examples:
+
+The following function `f` contains a redundant `return` statement:
+
+.. code:: c++
+
+  extern void g();
+  void f() {
+    g();
+    return;
+  }
+
+becomes
+
+.. code:: c++
+
+  extern void g();
+  void f() {
+    g();
+  }
+
+The following function `k` contains a redundant `continue` statement:
+
+.. code:: c++
+
+  void k() {
+    for (int i = 0; i < 10; ++i) {
+      continue;
+    }
+  }
+
+becomes
+
+.. code:: c++
+
+  void k() {
+    for (int i = 0; i < 10; ++i) {
+    }
+  }

Added: clang-tools-extra/trunk/test/clang-tidy/readability-redundant-control-flow.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-redundant-control-flow.cpp?rev=259362&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-redundant-control-flow.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-redundant-control-flow.cpp Mon Feb  1 09:31:15 2016
@@ -0,0 +1,222 @@
+// RUN: %check_clang_tidy %s readability-redundant-control-flow %t
+
+void g(int i);
+void j();
+
+void f() {
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow]
+// CHECK-FIXES: {{^}}void f() {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g() {
+  f();
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^  }}f();{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void g(int i) {
+  if (i < 0) {
+    return;
+  }
+  if (i < 10) {
+    f();
+  }
+}
+
+int h() {
+  return 1;
+}
+
+void j() {
+}
+
+void k() {
+  for (int i = 0; i < 10; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement at the end of loop statement
+// CHECK-FIXES: {{^}}  for (int i = 0; i < 10; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void k2() {
+  int v[10] = { 0 };
+  for (auto i : v) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (auto i : v) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void m() {
+  int i = 0;
+  do {
+    ++i;
+    continue;
+  } while (i < 10);
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^  do {$}}
+// CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}}} while (i < 10);{{$}}
+
+void p() {
+  int i = 0;
+  while (i < 10) {
+    ++i;
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  while (i < 10) {{{$}}
+// CHECK-FIXES-NEXT: {{^}}    ++i;{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void im_not_dead(int i) {
+  if (i > 0) {
+    return;
+  }
+  g();
+}
+
+void im_still_not_dead(int i) {
+  for (int j = 0; j < 10; ++j) {
+    if (i < 10) {
+      continue;
+    }
+    g();
+  }
+}
+
+void im_dead(int i) {
+  if (i > 0) {
+    return;
+    g();
+  }
+  g();
+}
+
+void im_still_dead(int i) {
+  for (int j = 0; j < 10; ++j) {
+    if (i < 10) {
+      continue;
+      g();
+    }
+    g();
+  }
+}
+
+void void_return() {
+  return g();
+}
+
+void nested_return_unmolested() {
+  g();
+  {
+    g();
+    return;
+  }
+}
+
+void nested_continue_unmolested() {
+  for (int i = 0; i < 10; ++i) {
+    if (i < 5) {
+      continue;
+    }
+  }
+}
+
+#define MACRO_RETURN_UNMOLESTED(fn_)  \
+  (fn_)();                            \
+  return
+
+#define MACRO_CONTINUE_UNMOLESTED(x_) \
+  do {                                \
+    for (int i = 0; i < (x_); ++i) {  \
+      continue;                       \
+    }                                 \
+  } while (false)
+
+void macro_return() {
+  MACRO_RETURN_UNMOLESTED(g);
+}
+
+void macro_continue() {
+  MACRO_CONTINUE_UNMOLESTED(10);
+}
+
+#define MACRO_RETURN_ARG(stmt_) \
+  stmt_
+
+#define MACRO_CONTINUE_ARG(stmt_)   \
+  do {                              \
+    for (int i = 0; i < 10; ++i) {  \
+      stmt_;                        \
+    }                               \
+  } while (false)
+
+void macro_arg_return() {
+  MACRO_RETURN_ARG(return);
+}
+
+void macro_arg_continue() {
+  MACRO_CONTINUE_ARG(continue);
+}
+
+template <typename T>
+void template_return(T check) {
+  if (check < T(0)) {
+    return;
+  }
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}}  if (check < T(0)) {{{$}}
+// CHECK-FIXES-NEXT: {{^    return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_return(int check) {
+  if (check < 0) {
+    return;
+  }
+  return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: {{^}}  if (check < 0) {{{$}}
+// CHECK-FIXES-NEXT: {{^    return;$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <typename T>
+void template_loop(T end) {
+  for (T i = 0; i < end; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (T i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+template <>
+void template_loop(int end) {
+  for (int i = 0; i < end; ++i) {
+    continue;
+  }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: {{^}}  for (int i = 0; i < end; ++i) {{{$}}
+// CHECK-FIXES-NEXT: {{^ *}$}}
+
+void call_templates() {
+  template_return(10);
+  template_return(10.0f);
+  template_return(10.0);
+  template_loop(10);
+  template_loop(10L);
+  template_loop(10U);
+}




More information about the cfe-commits mailing list