// RUN: %check_clang_tidy %s readability-else-after-return %t -- -- -fexceptions -std=c++17 namespace std { struct string { string(const char *); ~string(); }; } // namespace std struct my_exception { my_exception(const std::string &s); }; void f(int a) { if (a > 0) return; 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-1 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-1 return; } if (a > 0) { f(0); if (a > 10) return; } else { return; } if (a > 0) f(0); else if (a > 10) return; else // comment-2 // CHECK-FIXES-NOT: {{^}} // comment-2 f(0); if (a > 0) if (a < 10) return; else // comment-3 // CHECK-FIXES-NOT: {{^}} // comment-3 f(0); else if (a > 10) return; else // comment-4 // CHECK-FIXES-NOT: {{^}} // comment-4 f(0); if (a > 0) { if (a < 10) return; else // comment-5 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} // comment-5 f(0); } else { if (a > 10) return; else // comment-6 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} // comment-6 f(0); } } void foo() { for (unsigned x = 0; x < 42; ++x) { if (x) { continue; } else { // comment-7 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'continue' // CHECK-FIXES: {{^}} } // comment-7 x++; } if (x) { break; } else { // comment-8 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'break' // CHECK-FIXES: {{^}} } // comment-8 x++; } if (x) { throw 42; } else { // comment-9 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw' // CHECK-FIXES: {{^}} } // comment-9 x++; } if (x) { throw my_exception("foo"); } else { // comment-10 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use 'else' after 'throw' // CHECK-FIXES: {{^}} } // comment-10 x++; } } } int g(); int h(int); int declInConditionUsedInElse() { if (int X = g()) { // comment-11 // CHECK-FIXES: {{^}} int X = g(); // CHECK-FIXES-NEXT: {{^}}if (X) { // comment-11 return X; } else { // comment-11 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-11 return h(X); } } int declInConditionUnusedInElse() { if (int X = g()) { return h(X); } else { // comment-12 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-12 return 0; } } int varInitAndCondition() { if (int X = g(); X != 0) { // comment-13 // CHECK-FIXES: {{^}} int X = g(); // CHECK-FIXES-NEXT: {{^}}if ( X != 0) { // comment-13 return X; } else { // comment-13 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-13 return h(X); } } int varInitAndConditionUnusedInElse() { if (int X = g(); X != 0) { return X; } else { // comment-14 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-14 return 0; } } int initAndCondition() { int X; if (X = g(); X != 0) { return X; } else { // comment-15 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-15 return h(X); } } int varInitAndConditionUnusedInElseWithDecl() { int Y = g(); if (int X = g(); X != 0) { return X; } else { // comment-16 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES-NOT: {{^}} } //comment-16 int Y = g(); h(Y); } return Y; } int varInitAndCondVarUsedInElse() { if (int X = g(); int Y = g()) { // comment-17 // CHECK-FIXES: {{^}} int X = g(); // CHECK-FIXES-NEXT: {{^}}int Y = g(); // CHECK-FIXES-NEXT: {{^}}if ( Y) { // comment-17 return X ? X : Y; } else { // comment-17 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-17 return X ? X : h(Y); } } int lifeTimeExtensionTests(int a) { if (a > 0) { return a; } else { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' int b = 0; h(b); } if (int b = a; (b & 1) == 0) { return a; } else { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' b++; } if (int b = a; b > 1) { // comment-18 // CHECK-FIXES: {{^}} int b = a; // CHECK-FIXES-NEXT: {{^}}if ( b > 1) { // comment-18 return a; } else { // comment-18 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use 'else' after 'return' // CHECK-FIXES: {{^}} } // comment-18 return b; } } void test_B44745() { // This is the actual minimum test case for the crash in bug 44745. We aren't // too worried about the warning or fix here, more we don't want a crash. // CHECK-MESSAGES: :[[@LINE+3]]:5: warning: do not use 'else' after 'return' [readability-else-after-return] if (auto X = false) { return; } else { for (;;) { } } return; }