[clang] 89a0c40 - [clang][diagnostics] Add '-Wundef-prefix' warning option

Cyndy Ishida via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 30 14:01:03 PDT 2020


Author: Zixu Wang
Date: 2020-06-30T13:57:47-07:00
New Revision: 89a0c4066b0e70edd257e30d7189f303e26251a0

URL: https://github.com/llvm/llvm-project/commit/89a0c4066b0e70edd257e30d7189f303e26251a0
DIFF: https://github.com/llvm/llvm-project/commit/89a0c4066b0e70edd257e30d7189f303e26251a0.diff

LOG: [clang][diagnostics] Add '-Wundef-prefix' warning option

Summary:
Add an `-Wundef-prefix=<arg1>,<arg2>...` option, which is similar to `-Wundef`, but only give warnings for undefined macros with the given prefixes.

Reviewers: ributzka, steven_wu, cishida, bruno, arphaman, rsmith

Reviewed By: ributzka, arphaman

Subscribers: riccibruno, dexonsmith, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D80751

This patch was authored by Zixu Wang <zixu_wang at apple.com>

Added: 
    clang/test/Preprocessor/warn-macro-undef.c

Modified: 
    clang/include/clang/Basic/DiagnosticLexKinds.td
    clang/include/clang/Basic/DiagnosticOptions.h
    clang/include/clang/Driver/Options.td
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/Lex/PPExpressions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index fa07e9ae76c8..9cb06cf5b5e1 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -312,6 +312,9 @@ def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore,
 def warn_pp_undef_identifier : Warning<
   "%0 is not defined, evaluates to 0">,
   InGroup<DiagGroup<"undef">>, DefaultIgnore;
+def warn_pp_undef_prefix : Warning<
+  "%0 is not defined, evaluates to 0">,
+  InGroup<DiagGroup<"undef-prefix">>, DefaultIgnore;
 def warn_pp_ambiguous_macro : Warning<
   "ambiguous expansion of macro %0">, InGroup<AmbiguousMacro>;
 def note_pp_ambiguous_macro_chosen : Note<

diff  --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h
index 3e3c4e50a9e0..7fbe534c5994 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/clang/include/clang/Basic/DiagnosticOptions.h
@@ -98,6 +98,10 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
   /// prefixes removed.
   std::vector<std::string> Warnings;
 
+  /// The list of prefixes from -Wundef-prefix=... used to generate warnings
+  /// for undefined macros.
+  std::vector<std::string> UndefPrefixes;
+
   /// The list of -R... options used to alter the diagnostic mappings, with the
   /// prefixes removed.
   std::vector<std::string> Remarks;

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index eca822c6afa3..d030468514c3 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -483,6 +483,9 @@ def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Gr
 def Wp_COMMA : CommaJoined<["-"], "Wp,">,
   HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
   MetaVarName<"<arg>">, Group<Preprocessor_Group>;
+def Wundef_prefix_EQ : CommaJoined<["-"], "Wundef-prefix=">, Group<W_value_Group>,
+  Flags<[CC1Option, CoreOption, HelpHidden]>, MetaVarName<"<arg>">,
+  HelpText<"Enable warnings for undefined macros with a prefix in the comma separated list <arg>">;
 def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
 def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
 def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>,

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8bd248c95030..e12931a5a1b4 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1688,6 +1688,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
   }
   Opts.MessageLength =
       getLastArgIntValue(Args, OPT_fmessage_length_EQ, 0, Diags);
+
+  Opts.UndefPrefixes = Args.getAllArgValues(OPT_Wundef_prefix_EQ);
+
   addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
   addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
 

diff  --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index e5ec2b99f507..7a158a31490d 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -15,7 +15,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -26,9 +25,12 @@
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/Token.h"
 #include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/SaveAndRestore.h"
@@ -251,8 +253,24 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
         // If this identifier isn't 'defined' or one of the special
         // preprocessor keywords and it wasn't macro expanded, it turns
         // into a simple 0
-        if (ValueLive)
+        if (ValueLive) {
           PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
+
+          const DiagnosticsEngine &DiagEngine = PP.getDiagnostics();
+          // If 'Wundef' is enabled, do not emit 'undef-prefix' diagnostics.
+          if (DiagEngine.isIgnored(diag::warn_pp_undef_identifier,
+                                   PeekTok.getLocation())) {
+            const std::vector<std::string> UndefPrefixes =
+                DiagEngine.getDiagnosticOptions().UndefPrefixes;
+            const StringRef IdentifierName = II->getName();
+            if (llvm::any_of(UndefPrefixes,
+                             [&IdentifierName](const std::string &Prefix) {
+                               return IdentifierName.startswith(Prefix);
+                             }))
+              PP.Diag(PeekTok, diag::warn_pp_undef_prefix)
+                  << AddFlagValue{llvm::join(UndefPrefixes, ",")} << II;
+          }
+        }
         Result.Val = 0;
         Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
         Result.setIdentifier(II);

diff  --git a/clang/test/Preprocessor/warn-macro-undef.c b/clang/test/Preprocessor/warn-macro-undef.c
new file mode 100644
index 000000000000..e7d16c836076
--- /dev/null
+++ b/clang/test/Preprocessor/warn-macro-undef.c
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 %s -Eonly -Wundef -verify=undef
+// RUN: %clang_cc1 %s -Eonly -Wundef-prefix=A,BC -verify=undef-prefix
+// RUN: %clang_cc1 %s -Eonly -Wundef -Wundef-prefix=A,BC -verify=both
+// RUN: %clang_cc1 %s -Eonly -Werror=undef -verify=undef-error
+// RUN: %clang_cc1 %s -Eonly -Werror=undef-prefix -Wundef-prefix=A,BC -verify=undef-prefix-error
+// RUN: %clang_cc1 %s -Eonly -Werror=undef -Wundef-prefix=A,BC -verify=both-error
+
+extern int x;
+
+#if AB // #1
+#endif
+// undef-warning@#1 {{'AB' is not defined, evaluates to 0}}
+// undef-prefix-warning@#1 {{'AB' is not defined, evaluates to 0}}
+// both-warning@#1 {{'AB' is not defined, evaluates to 0}}
+// undef-error-error@#1 {{'AB' is not defined, evaluates to 0}}
+// undef-prefix-error-error@#1 {{'AB' is not defined, evaluates to 0}}
+// both-error-error@#1 {{'AB' is not defined, evaluates to 0}}
+
+#if B // #2
+#endif
+// undef-warning@#2 {{'B' is not defined, evaluates to 0}}
+// no warning for undef-prefix
+// both-warning@#2 {{'B' is not defined, evaluates to 0}}
+// undef-error-error@#2 {{'B' is not defined, evaluates to 0}}
+// no error for undef-prefix
+// both-error-error@#2 {{'B' is not defined, evaluates to 0}}
+
+#define BC 0
+#if BC // no warning/error
+#endif
+
+#undef BC
+#if BC // #3
+#endif
+// undef-warning@#3 {{'BC' is not defined, evaluates to 0}}
+// undef-prefix-warning@#3 {{'BC' is not defined, evaluates to 0}}
+// both-warning@#3 {{'BC' is not defined, evaluates to 0}}
+// undef-error-error@#3 {{'BC' is not defined, evaluates to 0}}
+// undef-prefix-error-error@#3 {{'BC' is not defined, evaluates to 0}}
+// both-error-error@#3 {{'BC' is not defined, evaluates to 0}}
+
+// Test that #pragma-enabled 'Wundef' can override 'Wundef-prefix'
+#pragma clang diagnostic error "-Wundef"
+
+#if C // #4
+#endif
+// undef-error@#4 {{'C' is not defined, evaluates to 0}}
+// undef-prefix-error@#4 {{'C' is not defined, evaluates to 0}}
+// both-error@#4 {{'C' is not defined, evaluates to 0}}
+// undef-error-error@#4 {{'C' is not defined, evaluates to 0}}
+// undef-prefix-error-error@#4 {{'C' is not defined, evaluates to 0}}
+// both-error-error@#4 {{'C' is not defined, evaluates to 0}}


        


More information about the cfe-commits mailing list