clang-tools 23.0.0git
RedundantParenthesesCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "../utils/Matchers.h"
12#include "clang/AST/Expr.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/ASTMatchers/ASTMatchersMacros.h"
16#include "clang/Lex/Lexer.h"
17#include <cassert>
18
19using namespace clang::ast_matchers;
20
22
23namespace {
24
25AST_MATCHER_P(ParenExpr, subExpr, ast_matchers::internal::Matcher<Expr>,
26 InnerMatcher) {
27 return InnerMatcher.matches(*Node.getSubExpr(), Finder, Builder);
28}
29
30AST_MATCHER(ParenExpr, isInMacro) {
31 const Expr *E = Node.getSubExpr();
32 return Node.getLParen().isMacroID() || Node.getRParen().isMacroID() ||
33 E->getBeginLoc().isMacroID() || E->getEndLoc().isMacroID();
34}
35
36} // namespace
37
38static FixItHint createSpacedRemoval(SourceLocation Loc,
39 const SourceManager &SM,
40 const LangOptions &LangOpts) {
41 if (Loc.isValid() && !Loc.isMacroID()) {
42 auto LocInfo = SM.getDecomposedLoc(Loc);
43 bool Invalid = false;
44 StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
45 if (!Invalid && LocInfo.second > 0 && LocInfo.second + 1 < Buffer.size() &&
46 Lexer::isAsciiIdentifierContinueChar(Buffer[LocInfo.second - 1],
47 LangOpts) &&
48 Lexer::isAsciiIdentifierContinueChar(Buffer[LocInfo.second + 1],
49 LangOpts))
50 return FixItHint::CreateReplacement(SourceRange(Loc, Loc), " ");
51 }
52 return FixItHint::CreateRemoval(Loc);
53}
54
56 ClangTidyContext *Context)
57 : ClangTidyCheck(Name, Context),
58 AllowedDecls(utils::options::parseStringList(
59 Options.get("AllowedDecls", "std::max;std::min"))) {}
60
63 Options.store(Opts, "AllowedDecls",
65}
66
68 const auto ConstantExpr =
69 expr(anyOf(integerLiteral(), floatLiteral(), characterLiteral(),
70 cxxBoolLiteral(), stringLiteral(), cxxNullPtrLiteralExpr()));
71 Finder->addMatcher(
72 parenExpr(subExpr(anyOf(
73 parenExpr(), ConstantExpr,
74 declRefExpr(to(namedDecl(unless(
76 memberExpr(),
77 callExpr(unless(cxxOperatorCallExpr(
78 unless(hasAnyOperatorName("()", "[]"))))),
79 arraySubscriptExpr())),
80 unless(anyOf(isInMacro(),
81 // sizeof(...) is common used.
82 hasParent(unaryExprOrTypeTraitExpr()))))
83 .bind("dup"),
84 this);
85}
86
87void RedundantParenthesesCheck::check(const MatchFinder::MatchResult &Result) {
88 const auto *PE = Result.Nodes.getNodeAs<ParenExpr>("dup");
89 diag(PE->getBeginLoc(), "redundant parentheses around expression")
90 << createSpacedRemoval(PE->getLParen(), *Result.SourceManager,
91 getLangOpts())
92 << FixItHint::CreateRemoval(PE->getRParen());
93}
94
95} // namespace clang::tidy::readability
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)
AST_MATCHER(BinaryOperator, isRelationalOperator)
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedRegexName(llvm::ArrayRef< StringRef > NameList)
static FixItHint createSpacedRemoval(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap