summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/cppcoreguidelines
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines')
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp95
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.h48
4 files changed, 147 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 26dbb01fffc..70f6c33c31b 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
AvoidGotoCheck.cpp
CppCoreGuidelinesTidyModule.cpp
InterfacesGlobalInitCheck.cpp
+ MacroUsageCheck.cpp
NarrowingConversionsCheck.cpp
NoMallocCheck.cpp
OwningMemoryCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index 22c84db0bd3..590ec6df10e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -15,6 +15,7 @@
#include "../readability/MagicNumbersCheck.h"
#include "AvoidGotoCheck.h"
#include "InterfacesGlobalInitCheck.h"
+#include "MacroUsageCheck.h"
#include "NarrowingConversionsCheck.h"
#include "NoMallocCheck.h"
#include "OwningMemoryCheck.h"
@@ -45,6 +46,8 @@ public:
"cppcoreguidelines-avoid-magic-numbers");
CheckFactories.registerCheck<InterfacesGlobalInitCheck>(
"cppcoreguidelines-interfaces-global-init");
+ CheckFactories.registerCheck<MacroUsageCheck>(
+ "cppcoreguidelines-macro-usage");
CheckFactories.registerCheck<NarrowingConversionsCheck>(
"cppcoreguidelines-narrowing-conversions");
CheckFactories.registerCheck<NoMallocCheck>("cppcoreguidelines-no-malloc");
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
new file mode 100644
index 00000000000..5791fd0bf1d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
@@ -0,0 +1,95 @@
+//===--- MacroUsageCheck.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 "MacroUsageCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Regex.h"
+#include <algorithm>
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+namespace {
+
+bool isCapsOnly(StringRef Name) {
+ return std::all_of(Name.begin(), Name.end(), [](const char c) {
+ if (std::isupper(c) || std::isdigit(c) || c == '_')
+ return true;
+ return false;
+ });
+}
+
+class MacroUsageCallbacks : public PPCallbacks {
+public:
+ MacroUsageCallbacks(MacroUsageCheck *Check, StringRef RegExp, bool CapsOnly)
+ : Check(Check), RegExp(RegExp), CheckCapsOnly(CapsOnly) {}
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override {
+ if (MD->getMacroInfo()->isUsedForHeaderGuard() ||
+ MD->getMacroInfo()->getNumTokens() == 0)
+ return;
+
+ StringRef MacroName = MacroNameTok.getIdentifierInfo()->getName();
+ if (!CheckCapsOnly && !llvm::Regex(RegExp).match(MacroName))
+ Check->warnMacro(MD);
+
+ if (CheckCapsOnly && !isCapsOnly(MacroName))
+ Check->warnNaming(MD);
+ }
+
+private:
+ MacroUsageCheck *Check;
+ StringRef RegExp;
+ bool CheckCapsOnly;
+};
+} // namespace
+
+void MacroUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "AllowedRegexp", AllowedRegexp);
+ Options.store(Opts, "CheckCapsOnly", CheckCapsOnly);
+}
+
+void MacroUsageCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ Compiler.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<MacroUsageCallbacks>(this, AllowedRegexp,
+ CheckCapsOnly));
+}
+
+void MacroUsageCheck::warnMacro(const MacroDirective *MD) {
+ StringRef Message =
+ "macro used to declare a constant; consider using a 'constexpr' "
+ "constant";
+
+ /// A variadic macro is function-like at the same time. Therefore variadic
+ /// macros are checked first and will be excluded for the function-like
+ /// diagnostic.
+ if (MD->getMacroInfo()->isVariadic())
+ Message = "variadic macro used; consider using a 'constexpr' "
+ "variadic template function";
+ else if (MD->getMacroInfo()->isFunctionLike())
+ Message = "function-like macro used; consider a 'constexpr' template "
+ "function";
+
+ diag(MD->getLocation(), Message);
+}
+
+void MacroUsageCheck::warnNaming(const MacroDirective *MD) {
+ diag(MD->getLocation(), "macro definition does not define the macro name "
+ "using all uppercase characters");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
new file mode 100644
index 00000000000..ff33310e6e5
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.h
@@ -0,0 +1,48 @@
+//===--- MacroUsageCheck.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_CPPCOREGUIDELINES_MACROUSAGECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_MACROUSAGECHECK_H
+
+#include "../ClangTidy.h"
+#include "clang/Lex/Preprocessor.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Find macro usage that is considered problematic because better language
+/// constructs exist for the task.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-macro-usage.html
+class MacroUsageCheck : public ClangTidyCheck {
+public:
+ MacroUsageCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ AllowedRegexp(Options.get("AllowedRegexp", "^DEBUG_*")),
+ CheckCapsOnly(Options.get("CheckCapsOnly", 0)) {}
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerPPCallbacks(CompilerInstance &Compiler) override;
+ void warnMacro(const MacroDirective *MD);
+ void warnNaming(const MacroDirective *MD);
+
+private:
+ /// A regular expression that defines how allowed macros must look like.
+ std::string AllowedRegexp;
+ /// Control if only the check shall only test on CAPS_ONLY macros.
+ bool CheckCapsOnly;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_MACROUSAGECHECK_H
OpenPOWER on IntegriCloud