Skip to content

Commit ad8fc03

Browse files
committed
[clang-tidy] add readability-redundant-parentheses
This check wants to detect a common happened case that forgetting to remove parenthese during modifying code.
1 parent be6c4d9 commit ad8fc03

File tree

8 files changed

+182
-0
lines changed

8 files changed

+182
-0
lines changed

clang-tools-extra/clang-tidy/readability/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ add_clang_library(clangTidyReadabilityModule STATIC
4444
RedundantDeclarationCheck.cpp
4545
RedundantFunctionPtrDereferenceCheck.cpp
4646
RedundantMemberInitCheck.cpp
47+
RedundantParenthesesCheck.cpp
4748
RedundantPreprocessorCheck.cpp
4849
RedundantSmartptrGetCheck.cpp
4950
RedundantStringCStrCheck.cpp

clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "RedundantFunctionPtrDereferenceCheck.h"
4848
#include "RedundantInlineSpecifierCheck.h"
4949
#include "RedundantMemberInitCheck.h"
50+
#include "RedundantParenthesesCheck.h"
5051
#include "RedundantPreprocessorCheck.h"
5152
#include "RedundantSmartptrGetCheck.h"
5253
#include "RedundantStringCStrCheck.h"
@@ -138,6 +139,8 @@ class ReadabilityModule : public ClangTidyModule {
138139
"readability-redundant-function-ptr-dereference");
139140
CheckFactories.registerCheck<RedundantMemberInitCheck>(
140141
"readability-redundant-member-init");
142+
CheckFactories.registerCheck<RedundantParenthesesCheck>(
143+
"readability-redundant-parentheses");
141144
CheckFactories.registerCheck<RedundantPreprocessorCheck>(
142145
"readability-redundant-preprocessor");
143146
CheckFactories.registerCheck<ReferenceToConstructedTemporaryCheck>(
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "RedundantParenthesesCheck.h"
11+
#include "clang/AST/Expr.h"
12+
#include "clang/ASTMatchers/ASTMatchFinder.h"
13+
#include "clang/ASTMatchers/ASTMatchers.h"
14+
#include "clang/ASTMatchers/ASTMatchersMacros.h"
15+
#include <cassert>
16+
17+
using namespace clang::ast_matchers;
18+
19+
namespace clang::tidy::readability {
20+
21+
namespace {
22+
23+
AST_MATCHER_P(ParenExpr, subExpr, ast_matchers::internal::Matcher<Expr>,
24+
InnerMatcher) {
25+
return InnerMatcher.matches(*Node.getSubExpr(), Finder, Builder);
26+
}
27+
28+
} // namespace
29+
30+
void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {
31+
Finder->addMatcher(
32+
parenExpr(subExpr(anyOf(parenExpr(), integerLiteral(), floatLiteral(),
33+
characterLiteral(), cxxBoolLiteral(),
34+
stringLiteral(), declRefExpr())),
35+
unless(
36+
// sizeof(...) is common used.
37+
hasParent(unaryExprOrTypeTraitExpr())))
38+
.bind("dup"),
39+
this);
40+
}
41+
42+
void RedundantParenthesesCheck::check(const MatchFinder::MatchResult &Result) {
43+
const auto *PE = Result.Nodes.getNodeAs<ParenExpr>("dup");
44+
assert(PE);
45+
const Expr *E = PE->getSubExpr();
46+
if (PE->getLParen().isMacroID() || PE->getRParen().isMacroID() ||
47+
E->getBeginLoc().isMacroID() || E->getEndLoc().isMacroID())
48+
return;
49+
diag(PE->getBeginLoc(), "redundant parentheses around expression")
50+
<< FixItHint::CreateRemoval(PE->getLParen())
51+
<< FixItHint::CreateRemoval(PE->getRParen());
52+
}
53+
54+
} // namespace clang::tidy::readability
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H
11+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H
12+
13+
#include "../ClangTidyCheck.h"
14+
15+
namespace clang::tidy::readability {
16+
17+
/// Detect redundant parentheses.
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-parentheses.html
21+
class RedundantParenthesesCheck : public ClangTidyCheck {
22+
public:
23+
RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context)
24+
: ClangTidyCheck(Name, Context) {}
25+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
26+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
27+
};
28+
29+
} // namespace clang::tidy::readability
30+
31+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPARENTHESESCHECK_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ New checks
203203
Finds virtual function overrides with different visibility than the function
204204
in the base class.
205205

206+
- New :doc:`readability-redundant-parentheses
207+
<clang-tidy/checks/readability/redundant-parentheses>` check.
208+
209+
Detect redundant parentheses.
210+
206211
New check aliases
207212
^^^^^^^^^^^^^^^^^
208213

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ Clang-Tidy Checks
404404
:doc:`readability-redundant-function-ptr-dereference <readability/redundant-function-ptr-dereference>`, "Yes"
405405
:doc:`readability-redundant-inline-specifier <readability/redundant-inline-specifier>`, "Yes"
406406
:doc:`readability-redundant-member-init <readability/redundant-member-init>`, "Yes"
407+
:doc:`readability-redundant-parentheses <readability/redundant-parentheses>`, "Yes"
407408
:doc:`readability-redundant-preprocessor <readability/redundant-preprocessor>`,
408409
:doc:`readability-redundant-smartptr-get <readability/redundant-smartptr-get>`, "Yes"
409410
:doc:`readability-redundant-string-cstr <readability/redundant-string-cstr>`, "Yes"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.. title:: clang-tidy - readability-redundant-parentheses
2+
3+
readability-redundant-parentheses
4+
=================================
5+
6+
Detect redundant parentheses.
7+
8+
When modifying the code, one often forgets to remove the corresponding parentheses.
9+
This results in overly lengthy code. When the expression is complex, finding
10+
the matching parentheses becomes particularly difficult.
11+
12+
Example
13+
-------
14+
15+
.. code-block:: c++
16+
17+
(1);
18+
((a + 2)) * 3;
19+
(a);
20+
("aaa");
21+
22+
Currently this check does not take into account the precedence of operations.
23+
Even if the expression within the parentheses has a higher priority than that
24+
outside the parentheses, in other words, removing the parentheses will not
25+
affect the semantic.
26+
27+
.. code-block:: c++
28+
29+
int a = (1 * 2) + 3; // no warning
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %check_clang_tidy %s readability-redundant-parentheses %t
2+
3+
void parenExpr() {
4+
1 + 1;
5+
(1 + 1);
6+
((1 + 1));
7+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
8+
// CHECK-FIXES: (1 + 1);
9+
(((1 + 1)));
10+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
11+
// CHECK-MESSAGES: :[[@LINE-2]]:4: warning: redundant parentheses around expression [readability-redundant-parentheses]
12+
// CHECK-FIXES: (1 + 1);
13+
((((1 + 1))));
14+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
15+
// CHECK-MESSAGES: :[[@LINE-2]]:4: warning: redundant parentheses around expression [readability-redundant-parentheses]
16+
// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant parentheses around expression [readability-redundant-parentheses]
17+
// CHECK-FIXES: (1 + 1);
18+
}
19+
20+
#define EXP (1 + 1)
21+
#define PAREN(e) (e)
22+
void parenExprWithMacro() {
23+
EXP; // 1
24+
(EXP); // 2
25+
((EXP)); // 3
26+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
27+
// CHECK-FIXES: (EXP); // 3
28+
PAREN((1));
29+
}
30+
31+
void constant() {
32+
(1);
33+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
34+
// CHECK-FIXES: 1;
35+
(1.0);
36+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
37+
// CHECK-FIXES: 1.0;
38+
(true);
39+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
40+
// CHECK-FIXES: true;
41+
(',');
42+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
43+
// CHECK-FIXES: ',';
44+
("v4");
45+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
46+
// CHECK-FIXES: "v4";
47+
}
48+
49+
void declRefExpr(int a) {
50+
(a);
51+
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant parentheses around expression [readability-redundant-parentheses]
52+
// CHECK-FIXES: a;
53+
}
54+
55+
void exceptions() {
56+
sizeof(1);
57+
alignof(2);
58+
}

0 commit comments

Comments
 (0)