mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-15 12:39:19 +00:00
[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
This commit is contained in:
parent
c2e58e7265
commit
552b62ed1f
@ -4,6 +4,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
|
||||
AvoidGotoCheck.cpp
|
||||
CppCoreGuidelinesTidyModule.cpp
|
||||
InterfacesGlobalInitCheck.cpp
|
||||
MacroUsageCheck.cpp
|
||||
NarrowingConversionsCheck.cpp
|
||||
NoMallocCheck.cpp
|
||||
OwningMemoryCheck.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");
|
||||
|
@ -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
|
@ -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
|
@ -103,6 +103,12 @@ Improvements to clang-tidy
|
||||
Flags uses of ``absl::StrCat()`` to append to a ``std::string``. Suggests
|
||||
``absl::StrAppend()`` should be used instead.
|
||||
|
||||
- New :doc:`cppcoreguidelines-macro-usage
|
||||
<clang-tidy/checks/cppcoreguidelines-macro-usage>` check.
|
||||
|
||||
Find macro usage that is considered problematic because better language
|
||||
constructs exist for the task.
|
||||
|
||||
- New :doc:`misc-non-private-member-variables-in-classes
|
||||
<clang-tidy/checks/misc-non-private-member-variables-in-classes>` check.
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
.. title:: clang-tidy - cppcoreguidelines-macro-usage
|
||||
|
||||
cppcoreguidelines-macro-usage
|
||||
=============================
|
||||
|
||||
Find macro usage that is considered problematic because better language
|
||||
constructs exist for the task.
|
||||
|
||||
The relevant sections in the C++ Core Guidelines are
|
||||
`Enum.1 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#enum1-prefer-enumerations-over-macros>`_,
|
||||
`ES.30 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es30-dont-use-macros-for-program-text-manipulation>`_,
|
||||
`ES.31 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es31-dont-use-macros-for-constants-or-functions>`_ and
|
||||
`ES.33 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es33-if-you-must-use-macros-give-them-unique-names>`_.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
.. option:: AllowedRegexp
|
||||
|
||||
A regular expression to filter allowed macros. For example
|
||||
`DEBUG*|LIBTORRENT*|TORRENT*|UNI*` could be applied to filter `libtorrent`.
|
||||
Default value is `^DEBUG_*`.
|
||||
|
||||
.. option:: CheckCapsOnly
|
||||
|
||||
Boolean flag to warn on all macros except those with CAPS_ONLY names.
|
||||
This option is intended to ease introduction of this check into older
|
||||
code bases. Default value is `0`/`false`.
|
@ -89,6 +89,7 @@ Clang-Tidy Checks
|
||||
cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) <cppcoreguidelines-avoid-magic-numbers>
|
||||
cppcoreguidelines-c-copy-assignment-signature (redirects to misc-unconventional-assign-operator) <cppcoreguidelines-c-copy-assignment-signature>
|
||||
cppcoreguidelines-interfaces-global-init
|
||||
cppcoreguidelines-macro-usage
|
||||
cppcoreguidelines-narrowing-conversions
|
||||
cppcoreguidelines-no-malloc
|
||||
cppcoreguidelines-non-private-member-variables-in-classes (redirects to misc-non-private-member-variables-in-classes) <cppcoreguidelines-non-private-member-variables-in-classes>
|
||||
|
@ -0,0 +1,24 @@
|
||||
// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t \
|
||||
// RUN: -config='{CheckOptions: \
|
||||
// RUN: [{key: cppcoreguidelines-macro-usage.CheckCapsOnly, value: 1}]}' --
|
||||
|
||||
#ifndef INCLUDE_GUARD
|
||||
#define INCLUDE_GUARD
|
||||
|
||||
#define problematic_constant 0
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters
|
||||
|
||||
#define problematic_function(x, y) ((a) > (b) ? (a) : (b))
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters
|
||||
|
||||
#define problematic_variadic(...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters
|
||||
//
|
||||
#define problematic_variadic2(x, ...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters
|
||||
|
||||
#define OKISH_CONSTANT 42
|
||||
#define OKISH_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
|
||||
#define OKISH_VARIADIC(...) (__VA_ARGS__)
|
||||
|
||||
#endif
|
@ -0,0 +1,28 @@
|
||||
// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t \
|
||||
// RUN: -config='{CheckOptions: \
|
||||
// RUN: [{key: cppcoreguidelines-macro-usage.AllowedRegexp, value: "DEBUG_*|TEST_*"}]}' --
|
||||
|
||||
#ifndef INCLUDE_GUARD
|
||||
#define INCLUDE_GUARD
|
||||
|
||||
#define PROBLEMATIC_CONSTANT 0
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant
|
||||
|
||||
#define PROBLEMATIC_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro used; consider a 'constexpr' template function
|
||||
|
||||
#define PROBLEMATIC_VARIADIC(...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function
|
||||
|
||||
#define PROBLEMATIC_VARIADIC2(x, ...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function
|
||||
|
||||
#define DEBUG_CONSTANT 0
|
||||
#define DEBUG_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
|
||||
#define DEBUG_VARIADIC(...) (__VA_ARGS__)
|
||||
#define TEST_CONSTANT 0
|
||||
#define TEST_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
|
||||
#define TEST_VARIADIC(...) (__VA_ARGS__)
|
||||
#define TEST_VARIADIC2(x, ...) (__VA_ARGS__)
|
||||
|
||||
#endif
|
@ -0,0 +1,18 @@
|
||||
// RUN: %check_clang_tidy %s cppcoreguidelines-macro-usage %t
|
||||
|
||||
#ifndef INCLUDE_GUARD
|
||||
#define INCLUDE_GUARD
|
||||
|
||||
#define PROBLEMATIC_CONSTANT 0
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant
|
||||
|
||||
#define PROBLEMATIC_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro used; consider a 'constexpr' template function
|
||||
|
||||
#define PROBLEMATIC_VARIADIC(...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function
|
||||
|
||||
#define PROBLEMATIC_VARIADIC2(x, ...) (__VA_ARGS__)
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user