summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
diff options
context:
space:
mode:
authorJonas Toth <jonas.toth@gmail.com>2018-10-22 19:20:01 +0000
committerJonas Toth <jonas.toth@gmail.com>2018-10-22 19:20:01 +0000
commit552b62ed1f24dfbed4b5ee733415572ead5b228e (patch)
treef389feaa5b77a8c10caef76cc0c923be21a00d6e /clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
parentc2e58e726525943ffa6eef3392de42dc0a769470 (diff)
downloadbcm5719-llvm-552b62ed1f24dfbed4b5ee733415572ead5b228e.tar.gz
bcm5719-llvm-552b62ed1f24dfbed4b5ee733415572ead5b228e.zip
[clang-tidy] implement cppcoreguidelines macro rules
Summary: In short macros are discouraged by multiple rules (and sometimes reference randomly). [Enum.1], [ES.30], [ES.31] This check allows only headerguards and empty macros for annotation. Reviewers: aaron.ballman, hokein Reviewed By: aaron.ballman Subscribers: jbcoe, Eugene.Zelenko, klimek, nemanjai, mgorny, xazax.hun, kbarton, cfe-commits Differential Revision: https://reviews.llvm.org/D41648 llvm-svn: 344940
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp95
1 files changed, 95 insertions, 0 deletions
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
OpenPOWER on IntegriCloud