diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 4b4c49d3b17d1..0d0641c4b22bf 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -44,6 +44,7 @@ add_clang_library(clangTidyReadabilityModule STATIC RedundantDeclarationCheck.cpp RedundantFunctionPtrDereferenceCheck.cpp RedundantMemberInitCheck.cpp + RedundantParenthesesCheck.cpp RedundantPreprocessorCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringCStrCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index d01882dfc9daa..fcfac05b000e4 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -47,6 +47,7 @@ #include "RedundantFunctionPtrDereferenceCheck.h" #include "RedundantInlineSpecifierCheck.h" #include "RedundantMemberInitCheck.h" +#include "RedundantParenthesesCheck.h" #include "RedundantPreprocessorCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" @@ -138,6 +139,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck( "readability-redundant-member-init"); + CheckFactories.registerCheck( + "readability-redundant-parentheses"); CheckFactories.registerCheck( "readability-redundant-preprocessor"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp new file mode 100644 index 0000000000000..0ab59fff39d88 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RedundantParenthesesCheck.h" +#include "clang/AST/Expr.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +namespace { + +AST_MATCHER_P(ParenExpr, subExpr, ast_matchers::internal::Matcher, + InnerMatcher) { + return InnerMatcher.matches(*Node.getSubExpr(), Finder, Builder); +} + +AST_MATCHER(ParenExpr, isInMacro) { + const Expr *E = Node.getSubExpr(); + return Node.getLParen().isMacroID() || Node.getRParen().isMacroID() || + E->getBeginLoc().isMacroID() || E->getEndLoc().isMacroID(); +} + +} // namespace + +void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) { + const auto ConstantExpr = + expr(anyOf(integerLiteral(), floatLiteral(), characterLiteral(), + cxxBoolLiteral(), stringLiteral(), cxxNullPtrLiteralExpr())); + Finder->addMatcher( + parenExpr(subExpr(anyOf(parenExpr(), ConstantExpr, declRefExpr())), + unless(anyOf(isInMacro(), + // sizeof(...) is common used. + hasParent(unaryExprOrTypeTraitExpr())))) + .bind("dup"), + this); +} + +void RedundantParenthesesCheck::check(const MatchFinder::MatchResult &Result) { + const auto *PE = Result.Nodes.getNodeAs("dup"); + diag(PE->getBeginLoc(), "redundant parentheses around expression") + << FixItHint::CreateRemoval(PE->getLParen()) + << FixItHint::CreateRemoval(PE->getRParen()); +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h new file mode 100644 index 0000000000000..9a0409b83fff3 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H + +#include "../ClangTidyCheck.h" +#include "clang/Basic/LangOptions.h" + +namespace clang::tidy::readability { + +/// Detect redundant parentheses. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-parentheses.html +class RedundantParenthesesCheck : public ClangTidyCheck { +public: + RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus | LangOpts.C99; + } +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8c7426c33d13b..c7ba1195f84f6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -203,6 +203,11 @@ New checks Finds virtual function overrides with different visibility than the function in the base class. +- New :doc:`readability-redundant-parentheses + ` check. + + Detect redundant parentheses. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e705958f9033f..f94696d4ef9c7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -404,6 +404,7 @@ Clang-Tidy Checks :doc:`readability-redundant-function-ptr-dereference `, "Yes" :doc:`readability-redundant-inline-specifier `, "Yes" :doc:`readability-redundant-member-init `, "Yes" + :doc:`readability-redundant-parentheses `, "Yes" :doc:`readability-redundant-preprocessor `, :doc:`readability-redundant-smartptr-get `, "Yes" :doc:`readability-redundant-string-cstr `, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-parentheses.rst new file mode 100644 index 0000000000000..23d975e646490 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-parentheses.rst @@ -0,0 +1,29 @@ +.. title:: clang-tidy - readability-redundant-parentheses + +readability-redundant-parentheses +================================= + +Detect redundant parentheses. + +When modifying code, one often forgets to remove the corresponding parentheses. +This results in overly lengthy code. When the expression is complex, finding +the matching parentheses becomes particularly difficult. + +Example +------- + +.. code-block:: c++ + + (1); + ((a + 2)) * 3; + (a); + ("aaa"); + +Currently this check does not take into account the precedence of operations. +Even if the expression within the parentheses has a higher priority than that +outside the parentheses. In other words, removing the parentheses will not +affect the semantics. + +.. code-block:: c++ + + int a = (1 * 2) + 3; // no warning diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp new file mode 100644 index 0000000000000..926cb118c77cf --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-parentheses.cpp @@ -0,0 +1,64 @@ +// RUN: %check_clang_tidy %s readability-redundant-parentheses %t + +void parenExpr() { + 1 + 1; + (1 + 1); + ((1 + 1)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: (1 + 1); + (((1 + 1))); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-MESSAGES: :[[@LINE-2]]:4: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: (1 + 1); + ((((1 + 1)))); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-MESSAGES: :[[@LINE-2]]:4: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: (1 + 1); +} + +#define EXP (1 + 1) +#define PAREN(e) (e) +void parenExprWithMacro() { + EXP; // 1 + (EXP); // 2 + ((EXP)); // 3 + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: (EXP); // 3 + PAREN((1)); +} + +void constant() { + (1); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: 1; + (1.0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: 1.0; + (true); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: true; + (','); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: ','; + ("v4"); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: "v4"; + (nullptr); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: nullptr; +} + +void declRefExpr(int a) { + (a); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: a; +} + +void exceptions() { + sizeof(1); + alignof(2); + alignof((3)); + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant parentheses around expression [readability-redundant-parentheses] + // CHECK-FIXES: alignof(3); +}