lebedev.ri updated this revision to Diff 171583.
lebedev.ri added a comment.

Add an opt-in option to diagnose such command-line-based macros.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53817

Files:
  clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
  clang-tidy/cppcoreguidelines/MacroUsageCheck.h
  docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst
  test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp
  test/clang-tidy/cppcoreguidelines-macro-usage-command-line-macros.cpp
  test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp
  test/clang-tidy/cppcoreguidelines-macro-usage.cpp

Index: test/clang-tidy/cppcoreguidelines-macro-usage.cpp
===================================================================
--- test/clang-tidy/cppcoreguidelines-macro-usage.cpp
+++ test/clang-tidy/cppcoreguidelines-macro-usage.cpp
@@ -4,15 +4,15 @@
 #define INCLUDE_GUARD
 
 #define PROBLEMATIC_CONSTANT 0
-// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro 'PROBLEMATIC_FUNCTION' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC2' used; consider using a 'constexpr' variadic template function
 
 #endif
Index: test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp
===================================================================
--- test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp
+++ test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp
@@ -6,16 +6,16 @@
 #define INCLUDE_GUARD
 
 #define PROBLEMATIC_CONSTANT 0
-// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro 'PROBLEMATIC_FUNCTION' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC2' used; consider using a 'constexpr' variadic template function
 
 #define DEBUG_CONSTANT 0
 #define DEBUG_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
Index: test/clang-tidy/cppcoreguidelines-macro-usage-command-line-macros.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/cppcoreguidelines-macro-usage-command-line-macros.cpp
@@ -0,0 +1,8 @@
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreLocationless, value: 1}]}' -- -D_ZZZ_IM_A_MACRO
+// RUN: %check_clang_tidy -check-suffixes=NORMAL,CL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreLocationless, value: 0}]}' -- -D_ZZZ_IM_A_MACRO
+
+// CHECK-MESSAGES-CL: warning: macro '_ZZZ_IM_A_MACRO' used to declare a constant; consider using a 'constexpr' constant
+
+#define PROBLEMATIC_CONSTANT 0
+// CHECK-MESSAGES-NORMAL: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' used to declare a constant; consider using a 'constexpr' constant
Index: test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp
===================================================================
--- test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp
+++ test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp
@@ -6,16 +6,16 @@
 #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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_constant' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_function' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_variadic' 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
+// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_variadic2' using all uppercase characters
 
 #define OKISH_CONSTANT 42
 #define OKISH_FUNCTION(x, y) ((a) > (b) ? (a) : (b))
Index: docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst
===================================================================
--- docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst
+++ docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst
@@ -26,3 +26,8 @@
     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`.
+
+.. option:: IgnoreLocationless
+
+    Boolean flag to toggle ignoring command-line-defined macros.
+    Default value is `1`/`true`.
Index: clang-tidy/cppcoreguidelines/MacroUsageCheck.h
===================================================================
--- clang-tidy/cppcoreguidelines/MacroUsageCheck.h
+++ clang-tidy/cppcoreguidelines/MacroUsageCheck.h
@@ -28,17 +28,20 @@
   MacroUsageCheck(StringRef Name, ClangTidyContext *Context)
       : ClangTidyCheck(Name, Context),
         AllowedRegexp(Options.get("AllowedRegexp", "^DEBUG_*")),
-        CheckCapsOnly(Options.get("CheckCapsOnly", 0)) {}
+        CheckCapsOnly(Options.get("CheckCapsOnly", 0)),
+        IgnoreLocationless(Options.get("IgnoreLocationless", 1)) {}
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerPPCallbacks(CompilerInstance &Compiler) override;
-  void warnMacro(const MacroDirective *MD);
-  void warnNaming(const MacroDirective *MD);
+  void warnMacro(const MacroDirective *MD, StringRef MacroName);
+  void warnNaming(const MacroDirective *MD, StringRef MacroName);
 
 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;
+  /// Should the macros without a valid location be diagnosed?
+  bool IgnoreLocationless;
 };
 
 } // namespace cppcoreguidelines
Index: clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
===================================================================
--- clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
+++ clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp
@@ -31,64 +31,75 @@
 
 class MacroUsageCallbacks : public PPCallbacks {
 public:
-  MacroUsageCallbacks(MacroUsageCheck *Check, StringRef RegExp, bool CapsOnly)
-      : Check(Check), RegExp(RegExp), CheckCapsOnly(CapsOnly) {}
+  MacroUsageCallbacks(MacroUsageCheck *Check, const SourceManager &SM,
+                      StringRef RegExp, bool CapsOnly, bool Locationless)
+      : Check(Check), SM(SM), RegExp(RegExp), CheckCapsOnly(CapsOnly),
+        IgnoreLocationless(Locationless) {}
   void MacroDefined(const Token &MacroNameTok,
                     const MacroDirective *MD) override {
     if (MD->getMacroInfo()->isUsedForHeaderGuard() ||
         MD->getMacroInfo()->getNumTokens() == 0)
       return;
 
+    if (IgnoreLocationless && SM.isWrittenInCommandLineFile(MD->getLocation()))
+      return;
+
     StringRef MacroName = MacroNameTok.getIdentifierInfo()->getName();
     if (!CheckCapsOnly && !llvm::Regex(RegExp).match(MacroName))
-      Check->warnMacro(MD);
+      Check->warnMacro(MD, MacroName);
 
     if (CheckCapsOnly && !isCapsOnly(MacroName))
-      Check->warnNaming(MD);
+      Check->warnNaming(MD, MacroName);
   }
 
 private:
   MacroUsageCheck *Check;
+  const SourceManager &SM;
   StringRef RegExp;
   bool CheckCapsOnly;
+  bool IgnoreLocationless;
 };
 } // namespace
 
 void MacroUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "AllowedRegexp", AllowedRegexp);
   Options.store(Opts, "CheckCapsOnly", CheckCapsOnly);
+  Options.store(Opts, "IgnoreLocationless", IgnoreLocationless);
 }
 
 void MacroUsageCheck::registerPPCallbacks(CompilerInstance &Compiler) {
   if (!getLangOpts().CPlusPlus11)
     return;
 
   Compiler.getPreprocessor().addPPCallbacks(
-      llvm::make_unique<MacroUsageCallbacks>(this, AllowedRegexp,
-                                             CheckCapsOnly));
+      llvm::make_unique<MacroUsageCallbacks>(this, Compiler.getSourceManager(),
+                                             AllowedRegexp, CheckCapsOnly,
+                                             IgnoreLocationless));
 }
 
-void MacroUsageCheck::warnMacro(const MacroDirective *MD) {
+void MacroUsageCheck::warnMacro(const MacroDirective *MD, StringRef MacroName) {
   StringRef Message =
-      "macro used to declare a constant; consider using a 'constexpr' "
+      "macro '%0' 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' "
+    Message = "variadic macro '%0' used; consider using a 'constexpr' "
               "variadic template function";
   else if (MD->getMacroInfo()->isFunctionLike())
-    Message = "function-like macro used; consider a 'constexpr' template "
+    Message = "function-like macro '%0' used; consider a 'constexpr' template "
               "function";
 
-  diag(MD->getLocation(), Message);
+  diag(MD->getLocation(), Message) << MacroName;
 }
 
-void MacroUsageCheck::warnNaming(const MacroDirective *MD) {
+void MacroUsageCheck::warnNaming(const MacroDirective *MD,
+                                 StringRef MacroName) {
   diag(MD->getLocation(), "macro definition does not define the macro name "
-                          "using all uppercase characters");
+                          "'%0' using all uppercase characters")
+      << MacroName;
 }
 
 } // namespace cppcoreguidelines
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to