diff options
| author | Jonas Toth <jonas.toth@gmail.com> | 2018-10-22 19:20:01 +0000 |
|---|---|---|
| committer | Jonas Toth <jonas.toth@gmail.com> | 2018-10-22 19:20:01 +0000 |
| commit | 552b62ed1f24dfbed4b5ee733415572ead5b228e (patch) | |
| tree | f389feaa5b77a8c10caef76cc0c923be21a00d6e /clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp | |
| parent | c2e58e726525943ffa6eef3392de42dc0a769470 (diff) | |
| download | bcm5719-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.cpp | 95 |
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 |

