Author: jonastoth Date: Mon Oct 22 12:20:01 2018 New Revision: 344940 URL: http://llvm.org/viewvc/llvm-project?rev=344940&view=rev Log: [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 Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.h clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage.cpp Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/trunk/docs/ReleaseNotes.rst clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=344940&r1=344939&r2=344940&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt (original) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt Mon Oct 22 12:20:01 2018 @@ -4,6 +4,7 @@ add_clang_library(clangTidyCppCoreGuidel AvoidGotoCheck.cpp CppCoreGuidelinesTidyModule.cpp InterfacesGlobalInitCheck.cpp + MacroUsageCheck.cpp NarrowingConversionsCheck.cpp NoMallocCheck.cpp OwningMemoryCheck.cpp Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=344940&r1=344939&r2=344940&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp Mon Oct 22 12:20:01 2018 @@ -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"); Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp (added) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp Mon Oct 22 12:20:01 2018 @@ -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 Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.h?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.h (added) +++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/MacroUsageCheck.h Mon Oct 22 12:20:01 2018 @@ -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 Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=344940&r1=344939&r2=344940&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original) +++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Mon Oct 22 12:20:01 2018 @@ -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. Added: clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst (added) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst Mon Oct 22 12:20:01 2018 @@ -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`. Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=344940&r1=344939&r2=344940&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original) +++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Mon Oct 22 12:20:01 2018 @@ -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> Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp (added) +++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp Mon Oct 22 12:20:01 2018 @@ -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 Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp (added) +++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp Mon Oct 22 12:20:01 2018 @@ -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 Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage.cpp?rev=344940&view=auto ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage.cpp (added) +++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-macro-usage.cpp Mon Oct 22 12:20:01 2018 @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits