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_w...@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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits