summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Bobyrev <omtcyfz@gmail.com>2016-08-10 18:05:47 +0000
committerKirill Bobyrev <omtcyfz@gmail.com>2016-08-10 18:05:47 +0000
commit34789edbbf09f71181d2e6f5a3012667c8dd757a (patch)
treec9ceac2ed4421a95fd90e2c272bf6a1c5fea2056
parent0bbad0fc86ab3e4e51ec77b03b427d3f845c7ddb (diff)
downloadbcm5719-llvm-34789edbbf09f71181d2e6f5a3012667c8dd757a.tar.gz
bcm5719-llvm-34789edbbf09f71181d2e6f5a3012667c8dd757a.zip
[clang-tidy] enhance readability-else-after-return
`readability-else-after-return` only warns about `return` calls, but LLVM Coding Standars stat that `throw`, `continue`, `goto`, etc after `return` calls are bad, too. Reviwers: alexfh, aaron.ballman Differential Revision: https://reviews.llvm.org/D23265 llvm-svn: 278257
-rw-r--r--clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp23
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst59
-rw-r--r--clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp41
3 files changed, 107 insertions, 16 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
index 9560f1261af..21e5224542d 100644
--- a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
@@ -19,20 +19,29 @@ namespace tidy {
namespace readability {
void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
- // FIXME: Support continue, break and throw.
+ const auto ControlFlowInterruptorMatcher =
+ stmt(anyOf(returnStmt().bind("return"), continueStmt().bind("continue"),
+ breakStmt().bind("break"), cxxThrowExpr().bind("throw")));
Finder->addMatcher(
- compoundStmt(
- forEach(ifStmt(hasThen(stmt(anyOf(returnStmt(),
- compoundStmt(has(returnStmt()))))),
- hasElse(stmt().bind("else")))
- .bind("if"))),
+ stmt(forEach(
+ ifStmt(hasThen(stmt(
+ anyOf(ControlFlowInterruptorMatcher,
+ compoundStmt(has(ControlFlowInterruptorMatcher))))),
+ hasElse(stmt().bind("else")))
+ .bind("if"))),
this);
}
void ElseAfterReturnCheck::check(const MatchFinder::MatchResult &Result) {
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
SourceLocation ElseLoc = If->getElseLoc();
- DiagnosticBuilder Diag = diag(ElseLoc, "don't use else after return");
+ std::string ControlFlowInterruptor;
+ for (const auto *BindingName : {"return", "continue", "break", "throw"})
+ if (Result.Nodes.getNodeAs<Stmt>(BindingName))
+ ControlFlowInterruptor = BindingName;
+
+ DiagnosticBuilder Diag = diag(ElseLoc, "do not use 'else' after '%0'")
+ << ControlFlowInterruptor;
Diag << tooling::fixit::createRemoval(ElseLoc);
// FIXME: Removing the braces isn't always safe. Do a more careful analysis.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst
index a8e4c4604a9..11e9bdceaef 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability-else-after-return.rst
@@ -3,7 +3,62 @@
readability-else-after-return
=============================
+`LLVM Coding Standards <http://llvm.org/docs/CodingStandards.html>`_ advises to
+reduce indentation where possible and where it makes understanding code easier.
+Early exit is one of the suggested enforcements of that. Please do not use
+`else` or `else if` after something that interrupts control flow - like
+`return`, `break`, `continue`, `throw`.
-Flags the usages of ``else`` after ``return``.
+The following piece of code illustrates how the check works. This piece of code:
-http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return
+.. code-block:: c++
+
+ void foo(int Value) {
+ int Local = 0;
+ for (int i = 0; i < 42; i++) {
+ if (Value == 1) {
+ return;
+ } else {
+ Local++;
+ }
+
+ if (Value == 2)
+ continue;
+ else
+ Local++;
+
+ if (Value == 3) {
+ throw 42;
+ } else {
+ Local++;
+ }
+ }
+ }
+
+
+Would be transformed into:
+
+.. code-block:: c++
+
+ void foo(int Value) {
+ int Local = 0;
+ for (int i = 0; i < 42; i++) {
+ if (Value == 1) {
+ return;
+ }
+ Local++;
+
+ if (Value == 2)
+ continue;
+ Local++;
+
+ if (Value == 3) {
+ throw 42;
+ }
+ Local++;
+ }
+ }
+
+
+This checks helps to enforce this `Coding Standars recommendation
+<http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return>`_.
diff --git a/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp b/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
index 28fd2ec0f05..27cbfaecbb6 100644
--- a/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
+++ b/clang-tools-extra/test/clang-tidy/readability-else-after-return.cpp
@@ -3,16 +3,16 @@
void f(int a) {
if (a > 0)
return;
- else // comment
-// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: don't use else after return
-// CHECK-FIXES: {{^}} // comment
+ else // comment-0
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} // comment-0
return;
if (a > 0) {
return;
- } else { // comment
-// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: don't use else after return
-// CHECK-FIXES: } // comment
+ } else { // comment-1
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} } // comment-1
return;
}
@@ -28,7 +28,34 @@ void f(int a) {
f(0);
else if (a > 10)
return;
- else
+ else // comment-2
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'else' after 'return'
+ // CHECK-FIXES: {{^}} // comment-2
f(0);
}
+void foo() {
+ for (unsigned x = 0; x < 42; ++x) {
+ if (x) {
+ continue;
+ } else { // comment-3
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'continue'
+ // CHECK-FIXES: {{^}} } // comment-3
+ x++;
+ }
+ if (x) {
+ break;
+ } else { // comment-4
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'break'
+ // CHECK-FIXES: {{^}} } // comment-4
+ x++;
+ }
+ if (x) {
+ throw 42;
+ } else { // comment-5
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw'
+ // CHECK-FIXES: {{^}} } // comment-5
+ x++;
+ }
+ }
+}
OpenPOWER on IntegriCloud