summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2017-06-02 17:36:32 +0000
committerAlexander Kornienko <alexfh@google.com>2017-06-02 17:36:32 +0000
commitd9a4491b0a05a70733a80622d29a49d79210622a (patch)
treef4cb0a552e8a0096874142cf045bc67ee1bf07cb /clang-tools-extra/clang-tidy/misc
parentcdb5dad4cc4039e357c0437d9789b0353a989565 (diff)
downloadbcm5719-llvm-d9a4491b0a05a70733a80622d29a49d79210622a.tar.gz
bcm5719-llvm-d9a4491b0a05a70733a80622d29a49d79210622a.zip
[clang-tidy] check for __func__/__FUNCTION__ in lambdas
Add a clang-tidy check for using func__/FUNCTION__ inside lambdas. This evaluates to the string operator(), which is almost never useful and almost certainly not what the author intended. Patch by Bryce Liu! Differential Revision: https://reviews.llvm.org/D33497 llvm-svn: 304570
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc')
-rw-r--r--clang-tools-extra/clang-tidy/misc/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.cpp99
-rw-r--r--clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.h51
-rw-r--r--clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp3
4 files changed, 154 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index 36321e98c2e..9e74387d4ab 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangTidyMiscModule
ArgumentCommentCheck.cpp
AssertSideEffectCheck.cpp
ForwardingReferenceOverloadCheck.cpp
+ LambdaFunctionNameCheck.cpp
MisplacedConstCheck.cpp
UnconventionalAssignOperatorCheck.cpp
BoolPointerImplicitConversionCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.cpp
new file mode 100644
index 00000000000..85dad5c4fd4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.cpp
@@ -0,0 +1,99 @@
+//===--- LambdaFunctionNameCheck.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 "LambdaFunctionNameCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+
+// Keep track of macro expansions that contain both __FILE__ and __LINE__. If
+// such a macro also uses __func__ or __FUNCTION__, we don't want to issue a
+// warning because __FILE__ and __LINE__ may be useful even if __func__ or
+// __FUNCTION__ is not, especially if the macro could be used in the context of
+// either a function body or a lambda body.
+class MacroExpansionsWithFileAndLine : public PPCallbacks {
+public:
+ explicit MacroExpansionsWithFileAndLine(
+ LambdaFunctionNameCheck::SourceRangeSet *SME)
+ : SuppressMacroExpansions(SME) {}
+
+ void MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MD, SourceRange Range,
+ const MacroArgs *Args) override {
+ bool has_file = false;
+ bool has_line = false;
+ for (const auto& T : MD.getMacroInfo()->tokens()) {
+ if (T.is(tok::identifier)) {
+ StringRef IdentName = T.getIdentifierInfo()->getName();
+ if (IdentName == "__FILE__") {
+ has_file = true;
+ } else if (IdentName == "__LINE__") {
+ has_line = true;
+ }
+ }
+ }
+ if (has_file && has_line) {
+ SuppressMacroExpansions->insert(Range);
+ }
+ }
+
+private:
+ LambdaFunctionNameCheck::SourceRangeSet* SuppressMacroExpansions;
+};
+
+} // namespace
+
+void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) {
+ // Match on PredefinedExprs inside a lambda.
+ Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"),
+ this);
+}
+
+void LambdaFunctionNameCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+ Compiler.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<MacroExpansionsWithFileAndLine>(
+ &SuppressMacroExpansions));
+}
+
+void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *E = Result.Nodes.getNodeAs<PredefinedExpr>("E");
+ if (E->getIdentType() != PredefinedExpr::Func &&
+ E->getIdentType() != PredefinedExpr::Function) {
+ // We don't care about other PredefinedExprs.
+ return;
+ }
+ if (E->getLocation().isMacroID()) {
+ auto ER =
+ Result.SourceManager->getImmediateExpansionRange(E->getLocation());
+ if (SuppressMacroExpansions.find(SourceRange(ER.first, ER.second)) !=
+ SuppressMacroExpansions.end()) {
+ // This is a macro expansion for which we should not warn.
+ return;
+ }
+ }
+ diag(E->getLocation(),
+ "inside a lambda, '%0' expands to the name of the function call "
+ "operator; consider capturing the name of the enclosing function "
+ "explicitly")
+ << PredefinedExpr::getIdentTypeName(E->getIdentType());
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.h b/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.h
new file mode 100644
index 00000000000..f5940c1b820
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/LambdaFunctionNameCheck.h
@@ -0,0 +1,51 @@
+//===--- LambdaFunctionNameCheck.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_MISC_LAMBDA_FUNCTION_NAME_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_LAMBDA_FUNCTION_NAME_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Detect when __func__ or __FUNCTION__ is being used from within a lambda. In
+/// that context, those expressions expand to the name of the call operator
+/// (i.e., `operator()`).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-lambda-function-name.html
+class LambdaFunctionNameCheck : public ClangTidyCheck {
+public:
+ struct SourceRangeLessThan {
+ bool operator()(const SourceRange &L, const SourceRange &R) {
+ if (L.getBegin() == R.getBegin()) {
+ return L.getEnd() < R.getEnd();
+ }
+ return L.getBegin() < R.getBegin();
+ }
+ };
+ using SourceRangeSet = std::set<SourceRange, SourceRangeLessThan>;
+
+ LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ SourceRangeSet SuppressMacroExpansions;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_LAMBDA_FUNCTION_NAME_H
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index 43d09c75388..5448c04d3ad 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -21,6 +21,7 @@
#include "InaccurateEraseCheck.h"
#include "IncorrectRoundings.h"
#include "InefficientAlgorithmCheck.h"
+#include "LambdaFunctionNameCheck.h"
#include "MacroParenthesesCheck.h"
#include "MacroRepeatedSideEffectsCheck.h"
#include "MisplacedConstCheck.h"
@@ -68,6 +69,8 @@ public:
"misc-assert-side-effect");
CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
"misc-forwarding-reference-overload");
+ CheckFactories.registerCheck<LambdaFunctionNameCheck>(
+ "misc-lambda-function-name");
CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
CheckFactories.registerCheck<UnconventionalAssignOperatorCheck>(
"misc-unconventional-assign-operator");
OpenPOWER on IntegriCloud