summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/modernize
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize')
-rw-r--r--clang-tools-extra/clang-tidy/modernize/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp131
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h37
4 files changed, 172 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 125c6dded25..8fa3b00b1c6 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyModernizeModule
UseEqualsDeleteCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
+ UseTransparentFunctorsCheck.cpp
UseUsingCheck.cpp
LINK_LIBS
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index de8ed0aa887..63147dae4a4 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -27,6 +27,7 @@
#include "UseEqualsDeleteCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
+#include "UseTransparentFunctorsCheck.h"
#include "UseUsingCheck.h"
using namespace clang::ast_matchers;
@@ -61,6 +62,8 @@ public:
"modernize-use-equals-delete");
CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
+ CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
+ "modernize-use-transparent-functors");
CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
}
diff --git a/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
new file mode 100644
index 00000000000..7f592007671
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp
@@ -0,0 +1,131 @@
+//===--- UseTransparentFunctorsCheck.cpp - clang-tidy----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseTransparentFunctorsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+UseTransparentFunctorsCheck::UseTransparentFunctorsCheck(
+ StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context), SafeMode(Options.get("SafeMode", 0)) {}
+
+void UseTransparentFunctorsCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "SafeMode", SafeMode ? 1 : 0);
+}
+
+void UseTransparentFunctorsCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus14)
+ return;
+
+ const auto TransparentFunctors =
+ classTemplateSpecializationDecl(
+ unless(hasAnyTemplateArgument(refersToType(voidType()))),
+ hasAnyName("::std::plus", "::std::minus", "::std::multiplies",
+ "::std::divides", "::std::modulus", "::std::negate",
+ "::std::equal_to", "::std::not_equal_to", "::std::greater",
+ "::std::less", "::std::greater_equal", "::std::less_equal",
+ "::std::logical_and", "::std::logical_or",
+ "::std::logical_not", "::std::bit_and", "::std::bit_or",
+ "::std::bit_xor", "::std::bit_not"))
+ .bind("FunctorClass");
+
+ // Non-transparent functor mentioned as a template parameter. FIXIT.
+ Finder->addMatcher(
+ loc(qualType(
+ unless(elaboratedType()),
+ hasDeclaration(classTemplateSpecializationDecl(
+ unless(hasAnyTemplateArgument(templateArgument(refersToType(
+ qualType(pointsTo(qualType(isAnyCharacter()))))))),
+ hasAnyTemplateArgument(
+ templateArgument(refersToType(qualType(hasDeclaration(
+ TransparentFunctors))))
+ .bind("Functor"))))))
+ .bind("FunctorParentLoc"),
+ this);
+
+ if (SafeMode)
+ return;
+
+ // Non-transparent functor constructed. No FIXIT. There is no easy way
+ // to rule out the problematic char* vs string case.
+ Finder->addMatcher(cxxConstructExpr(hasDeclaration(cxxMethodDecl(
+ ofClass(TransparentFunctors))),
+ unless(isInTemplateInstantiation()))
+ .bind("FuncInst"),
+ this);
+}
+
+static const StringRef Message = "prefer transparent functors '%0'";
+
+template <typename T> static T getInnerTypeLocAs(TypeLoc Loc) {
+ T Result;
+ while (Result.isNull() && !Loc.isNull()) {
+ Result = Loc.getAs<T>();
+ Loc = Loc.getNextTypeLoc();
+ }
+ return Result;
+}
+
+void UseTransparentFunctorsCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *FuncClass =
+ Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("FunctorClass");
+ if (const auto *FuncInst =
+ Result.Nodes.getNodeAs<CXXConstructExpr>("FuncInst")) {
+ diag(FuncInst->getLocStart(), Message)
+ << (FuncClass->getName() + "<>").str();
+ return;
+ }
+
+ const auto *Functor = Result.Nodes.getNodeAs<TemplateArgument>("Functor");
+ const auto FunctorParentLoc =
+ Result.Nodes.getNodeAs<TypeLoc>("FunctorParentLoc")
+ ->getAs<TemplateSpecializationTypeLoc>();
+
+ if (!FunctorParentLoc)
+ return;
+
+ unsigned ArgNum = 0;
+ const auto *FunctorParentType =
+ FunctorParentLoc.getType()->castAs<TemplateSpecializationType>();
+ for (; ArgNum < FunctorParentType->getNumArgs(); ++ArgNum) {
+ const TemplateArgument &Arg = FunctorParentType->getArg(ArgNum);
+ if (Arg.getKind() != TemplateArgument::Type)
+ continue;
+ QualType ParentArgType = Arg.getAsType();
+ if (ParentArgType->isRecordType() &&
+ ParentArgType->getAsCXXRecordDecl() ==
+ Functor->getAsType()->getAsCXXRecordDecl())
+ break;
+ }
+ // Functor is a default template argument.
+ if (ArgNum == FunctorParentType->getNumArgs())
+ return;
+ TemplateArgumentLoc FunctorLoc = FunctorParentLoc.getArgLoc(ArgNum);
+ auto FunctorTypeLoc = getInnerTypeLocAs<TemplateSpecializationTypeLoc>(
+ FunctorLoc.getTypeSourceInfo()->getTypeLoc());
+ if (FunctorTypeLoc.isNull())
+ return;
+
+ SourceLocation ReportLoc = FunctorLoc.getLocation();
+ diag(ReportLoc, Message) << (FuncClass->getName() + "<>").str()
+ << FixItHint::CreateRemoval(
+ FunctorTypeLoc.getArgLoc(0).getSourceRange());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h
new file mode 100644
index 00000000000..4bdce766e97
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.h
@@ -0,0 +1,37 @@
+//===--- UseTransparentFunctorsCheck.h - clang-tidy--------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Prefer using transparent functors to non-transparent ones.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-transparent-functors.html
+class UseTransparentFunctorsCheck : public ClangTidyCheck {
+public:
+ UseTransparentFunctorsCheck(StringRef Name, ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+private:
+ const bool SafeMode;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_TRANSPARENT_FUNCTORS_H
OpenPOWER on IntegriCloud