73 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "RedundantParenthesesCheck.h"10#include "../utils/Matchers.h"11#include "../utils/OptionsUtils.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 <cassert>17 18using namespace clang::ast_matchers;19 20namespace clang::tidy::readability {21 22namespace {23 24AST_MATCHER_P(ParenExpr, subExpr, ast_matchers::internal::Matcher<Expr>,25 InnerMatcher) {26 return InnerMatcher.matches(*Node.getSubExpr(), Finder, Builder);27}28 29AST_MATCHER(ParenExpr, isInMacro) {30 const Expr *E = Node.getSubExpr();31 return Node.getLParen().isMacroID() || Node.getRParen().isMacroID() ||32 E->getBeginLoc().isMacroID() || E->getEndLoc().isMacroID();33}34 35} // namespace36 37RedundantParenthesesCheck::RedundantParenthesesCheck(StringRef Name,38 ClangTidyContext *Context)39 : ClangTidyCheck(Name, Context),40 AllowedDecls(utils::options::parseStringList(41 Options.get("AllowedDecls", "std::max;std::min"))) {}42 43void RedundantParenthesesCheck::storeOptions(44 ClangTidyOptions::OptionMap &Opts) {45 Options.store(Opts, "AllowedDecls",46 utils::options::serializeStringList(AllowedDecls));47}48 49void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {50 const auto ConstantExpr =51 expr(anyOf(integerLiteral(), floatLiteral(), characterLiteral(),52 cxxBoolLiteral(), stringLiteral(), cxxNullPtrLiteralExpr()));53 Finder->addMatcher(54 parenExpr(55 subExpr(anyOf(parenExpr(), ConstantExpr,56 declRefExpr(to(namedDecl(unless(57 matchers::matchesAnyListedName(AllowedDecls))))))),58 unless(anyOf(isInMacro(),59 // sizeof(...) is common used.60 hasParent(unaryExprOrTypeTraitExpr()))))61 .bind("dup"),62 this);63}64 65void RedundantParenthesesCheck::check(const MatchFinder::MatchResult &Result) {66 const auto *PE = Result.Nodes.getNodeAs<ParenExpr>("dup");67 diag(PE->getBeginLoc(), "redundant parentheses around expression")68 << FixItHint::CreateRemoval(PE->getLParen())69 << FixItHint::CreateRemoval(PE->getRParen());70}71 72} // namespace clang::tidy::readability73