Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
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,8 @@
//===----------------------------------------------------------------------===//

#include "RedundantParenthesesCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/Expr.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
Expand All @@ -32,15 +34,30 @@ 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(),
cxxBoolLiteral(), stringLiteral(), cxxNullPtrLiteralExpr()));
Finder->addMatcher(
parenExpr(subExpr(anyOf(parenExpr(), ConstantExpr, declRefExpr())),
unless(anyOf(isInMacro(),
// sizeof(...) is common used.
hasParent(unaryExprOrTypeTraitExpr()))))
parenExpr(
subExpr(anyOf(parenExpr(), ConstantExpr,
declRefExpr(to(namedDecl(unless(
matchers::matchesAnyListedName(AllowedDecls))))))),
unless(anyOf(isInMacro(),
// sizeof(...) is common used.
hasParent(unaryExprOrTypeTraitExpr()))))
.bind("dup"),
this);
}
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,17 @@ affect the semantics.
.. code-block:: c++

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

Options
-------

.. option:: AllowedDecls

Semicolon-separated list of regular expressions matching names of declarations
to ignore when the parentheses are around. Declarations can include variables
or functions.
The default is an `std::max;std::min`.

Some STL library functions may have the same name as widely used function-like
macro. For example, ``std::max`` and ``max`` macro. A workaround to distinguish
them is adding parentheses 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);
}
Loading