Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "RedundantParenthesesCheck.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/Expr.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
Expand All @@ -32,6 +33,18 @@ AST_MATCHER(ParenExpr, isInMacro) {

} // namespace

RedundantParenthesesCheck::RedundantParenthesesCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
AllowedDecls(utils::options::parseStringList(
Options.get("AllowedDecls", "std::max;std::min"))) {}

void RedundantParenthesesCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "AllowedDecls",
utils::options::serializeStringList(AllowedDecls));
}

void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {
const auto ConstantExpr =
expr(anyOf(integerLiteral(), floatLiteral(), characterLiteral(),
Expand All @@ -47,6 +60,15 @@ void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) {

void RedundantParenthesesCheck::check(const MatchFinder::MatchResult &Result) {
const auto *PE = Result.Nodes.getNodeAs<ParenExpr>("dup");
if (auto *DRE = dyn_cast<DeclRefExpr>(PE->getSubExpr())) {
const std::string Name = DRE->getDecl()->getQualifiedNameAsString();
llvm::errs() << Name << "\n";
bool Allowed = llvm::any_of(AllowedDecls, [&Name](const llvm::Regex &NM) {
return NM.isValid() && NM.match(Name);
});
if (Allowed)
return;
}
diag(PE->getBeginLoc(), "redundant parentheses around expression")
<< FixItHint::CreateRemoval(PE->getLParen())
<< FixItHint::CreateRemoval(PE->getRParen());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ namespace clang::tidy::readability {
/// 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) {}
RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
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;
}

private:
const std::vector<StringRef> AllowedDecls;
};

} // namespace clang::tidy::readability
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@ affect the semantics.
.. code-block:: c++

int a = (1 * 2) + 3; // no warning

Options
-------

.. option:: AllowedDecls

A semicolon-separated list of names of declarations included variables and
functions to ignore when the parenthese around it.
The default is an `std::max;std::min`.

Some std library functions may have the same name as widely used function-like
macro. For example, ``std::max`` and ``max`` macro. A work around to distinguish
them is adding parenthese around functions to prevent function-like macro.
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ void exceptions() {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant parentheses around expression [readability-redundant-parentheses]
// CHECK-FIXES: alignof(3);
}

namespace std {
template<class T> T max(T, T);
template<class T> T min(T, T);
} // namespace std
void ignoreStdMaxMin() {
(std::max)(1,2);
(std::min)(1,2);
}