Index: clang-tools-extra/clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -39,6 +39,7 @@ RedundantSmartptrGetCheck.cpp RedundantStringCStrCheck.cpp RedundantStringInitCheck.cpp + ReturnWithRedundantParensCheck.cpp SimplifyBooleanExprCheck.cpp SimplifySubscriptExprCheck.cpp StaticAccessedThroughInstanceCheck.cpp Index: clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -42,6 +42,7 @@ #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" +#include "ReturnWithRedundantParensCheck.h" #include "SimplifyBooleanExprCheck.h" #include "SimplifySubscriptExprCheck.h" #include "StaticAccessedThroughInstanceCheck.h" @@ -143,6 +144,8 @@ "readability-uppercase-literal-suffix"); CheckFactories.registerCheck( "readability-use-anyofallof"); + CheckFactories.registerCheck( + "readability-return-with-redundant-parens"); } }; Index: clang-tools-extra/clang-tidy/readability/ReturnWithRedundantParensCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/readability/ReturnWithRedundantParensCheck.h @@ -0,0 +1,38 @@ +//===--- ReturnWithRedundantParensCheck.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_RETURNBRACKETSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_RETURNBRACKETSCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Find and remove redundant parenthesis surrounding returned expression. +/// +/// Examples: +/// \code +/// void f() { return (1); } ==> void f() { return 1; } +/// \endcode +class ReturnWithRedundantParensCheck : public ClangTidyCheck { +public: + ReturnWithRedundantParensCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_RETURNBRACKETSCHECK_H Index: clang-tools-extra/clang-tidy/readability/ReturnWithRedundantParensCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/readability/ReturnWithRedundantParensCheck.cpp @@ -0,0 +1,85 @@ +//===--- ReturnWithRedundantParensCheck.cpp - clang-tidy --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ReturnWithRedundantParensCheck.h" +#include "clang/Lex/Lexer.h" +#include + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +namespace { +bool isLocationInMacroExpansion(const SourceManager &SM, SourceLocation Loc) { + return SM.isMacroBodyExpansion(Loc) || SM.isMacroArgExpansion(Loc); +} +} // namespace + +void ReturnWithRedundantParensCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + functionDecl(isDefinition(), returns(unless(voidType())), + hasBody(compoundStmt(hasAnySubstatement( + returnStmt(has(expr())).bind("return"))))), + this); + Finder->addMatcher( + functionDecl(isDefinition(), returns(unless(voidType())), + hasBody(has(ifStmt( + hasThen(returnStmt(has(expr())).bind("return")))))), + this); + Finder->addMatcher( + functionDecl(isDefinition(), returns(unless(voidType())), + hasBody(has(ifStmt(hasThen(compoundStmt(hasAnySubstatement( + returnStmt(has(expr())).bind("return")))))))), + this); + Finder->addMatcher( + functionDecl(isDefinition(), returns(unless(voidType())), + hasBody(has(ifStmt( + hasElse(returnStmt(has(expr())).bind("return")))))), + this); + Finder->addMatcher( + functionDecl(isDefinition(), returns(unless(voidType())), + hasBody(has(ifStmt(hasElse(compoundStmt(hasAnySubstatement( + returnStmt(has(expr())).bind("return")))))))), + this); +} + +void ReturnWithRedundantParensCheck::check( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto *Return = Result.Nodes.getNodeAs("return"); + assert(Return); + SourceManager &SM = *Result.SourceManager; + + if (isLocationInMacroExpansion(SM, Return->getSourceRange().getBegin())) + return; + + assert(!Return->children().empty()); + auto ChildExpr = *Return->children().begin(); + if (!isa(ChildExpr)) + return; + + auto Expr = cast(ChildExpr); + auto LParen = Expr->getLParen(); + assert(LParen.isValid()); + auto RParen = Expr->getRParen(); + assert(RParen.isValid()); + auto RemovedRange1 = + CharSourceRange::getCharRange(LParen, LParen.getLocWithOffset(1)); + auto RemovedRange2 = + CharSourceRange::getCharRange(RParen, RParen.getLocWithOffset(1)); + + diag(LParen, "Redundant parens in the 'return' statement") + << FixItHint::CreateRemoval(RemovedRange1) + << FixItHint::CreateRemoval(RemovedRange2); +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -104,6 +104,11 @@ Warns when a struct or class uses const or reference (lvalue or rvalue) data members. +- New :doc:`readability-return-with-redundant-parens + ` check. + + Checks for ``return`` statements with redundant parenthesis. + New check aliases ^^^^^^^^^^^^^^^^^ Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -353,6 +353,7 @@ `readability-redundant-smartptr-get `_, "Yes" `readability-redundant-string-cstr `_, "Yes" `readability-redundant-string-init `_, "Yes" + `readability-return-with-redundant-parens `_, "Yes" `readability-simplify-boolean-expr `_, "Yes" `readability-simplify-subscript-expr `_, "Yes" `readability-static-accessed-through-instance `_, "Yes" Index: clang-tools-extra/docs/clang-tidy/checks/readability/return-with-redundant-parens.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/readability/return-with-redundant-parens.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - readability-return-with-redundant-parens + +readability-return-with-redundant-parens +======================================== + +Checks for ``return`` statements with redundant parenthesis. + +Example +------- + +.. code-block:: c++ + + void f() { + return (1); // Note, the parenthesis here are redundant. + } + Index: clang-tools-extra/test/clang-tidy/readability-return-with-redundant-parens.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/readability-return-with-redundant-parens.cpp @@ -0,0 +1,50 @@ +// RUN: %check_clang_tidy %s readability-return-with-redundant-parens %t + +int good() { + return 1; +} + +int simple1() { + return (1); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ }}return 1;{{$}} +} + +int complex1() { + int a = 0; + return (a + a * (a + a)); + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ }}return a + a * (a + a);{{$}} +} + +int no_space() { + return(1); + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ }}return 1;{{$}} +} + +bool helper(); + +bool if1(int *p) { + if (p) return(helper()); + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ }}if (p) return helper();{{$}} +} + +bool if2(int *p) { + if (p) p = nullptr; else return(helper()); + // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ }}if (p) p = nullptr; else return helper();{{$}} +} + +bool if3(int *arg) { + if (arg) { + return(helper()); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ +}}return helper();{{$}} + } else { + return(helper()); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: Redundant parens in the 'return' statement [readability-return-with-redundant-parens] + // CHECK-FIXES: {{^ +}}return helper();{{$}} + } +}