Skip to content

Commit 3a11d5a

Browse files
authored
[clang][diagnostics] add -Wundef-true warning option (llvm#128265)
New option `-Wundef-true` added and enabled by default to warn when `true` is used in the C preprocessor without being defined before C23.
1 parent 00e7463 commit 3a11d5a

File tree

5 files changed

+91
-4
lines changed

5 files changed

+91
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ Non-comprehensive list of changes in this release
114114
New Compiler Flags
115115
------------------
116116

117+
- New option ``-Wundef-true`` added and enabled by default to warn when `true` is used in the C preprocessor without being defined before C23.
118+
117119
- New option ``-fprofile-continuous`` added to enable continuous profile syncing to file (#GH124353, `docs <https://clang.llvm.org/docs/UsersManual.html#cmdoption-fprofile-continuous>`_).
118120
The feature has `existed <https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program>`_)
119121
for a while and this is just a user facing option.

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,8 @@ def ReservedIdAsMacroAlias : DiagGroup<"reserved-id-macro", [ReservedIdAsMacro]>
791791
def ReservedAttributeIdentifier : DiagGroup<"reserved-attribute-identifier">;
792792
def RestrictExpansionMacro : DiagGroup<"restrict-expansion">;
793793
def FinalMacro : DiagGroup<"final-macro">;
794+
def UndefinedTrueIdentifier : DiagGroup<"undef-true">;
795+
def UndefinedIdentifier : DiagGroup<"undef", [UndefinedTrueIdentifier]>;
794796

795797
// Just silence warnings about -Wstrict-aliasing for now.
796798
def : DiagGroup<"strict-aliasing=0">;

clang/include/clang/Basic/DiagnosticLexKinds.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,10 @@ def pp_macro_not_used : Warning<"macro is not used">, DefaultIgnore,
392392
InGroup<DiagGroup<"unused-macros">>;
393393
def warn_pp_undef_identifier : Warning<
394394
"%0 is not defined, evaluates to 0">,
395-
InGroup<DiagGroup<"undef">>, DefaultIgnore;
395+
InGroup<UndefinedIdentifier>, DefaultIgnore;
396+
def warn_pp_undef_true_identifier : Warning<
397+
"'true' is not defined, evaluates to 0">,
398+
InGroup<UndefinedTrueIdentifier>;
396399
def warn_pp_undef_prefix : Warning<
397400
"%0 is not defined, evaluates to 0">,
398401
InGroup<DiagGroup<"undef-prefix">>, DefaultIgnore;

clang/lib/Lex/PPExpressions.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,14 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
257257
// preprocessor keywords and it wasn't macro expanded, it turns
258258
// into a simple 0
259259
if (ValueLive) {
260-
PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
260+
unsigned DiagID = II->getName() == "true"
261+
? diag::warn_pp_undef_true_identifier
262+
: diag::warn_pp_undef_identifier;
263+
PP.Diag(PeekTok, DiagID) << II;
261264

262265
const DiagnosticsEngine &DiagEngine = PP.getDiagnostics();
263266
// If 'Wundef' is enabled, do not emit 'undef-prefix' diagnostics.
264-
if (DiagEngine.isIgnored(diag::warn_pp_undef_identifier,
265-
PeekTok.getLocation())) {
267+
if (DiagEngine.isIgnored(DiagID, PeekTok.getLocation())) {
266268
const std::vector<std::string> UndefPrefixes =
267269
DiagEngine.getDiagnosticOptions().UndefPrefixes;
268270
const StringRef IdentifierName = II->getName();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %clang_cc1 %s -Eonly -std=c89 -verify=undef-true
2+
// RUN: %clang_cc1 %s -Eonly -std=c99 -verify=undef-true
3+
// RUN: %clang_cc1 %s -Eonly -std=c11 -verify=undef-true
4+
// RUN: %clang_cc1 %s -Eonly -std=c17 -verify=undef-true
5+
// RUN: %clang_cc1 %s -Eonly -std=c23 -verify=undef-true
6+
7+
#if __STDC_VERSION__ >= 202311L
8+
/* undef-true-no-diagnostics */
9+
#endif
10+
11+
#define FOO true
12+
#if FOO /* #1 */
13+
#endif
14+
#if __STDC_VERSION__ < 202311L
15+
/* undef-true-warning@#1 {{'true' is not defined, evaluates to 0}} */
16+
#endif
17+
18+
#if true /* #2 */
19+
#endif
20+
#if __STDC_VERSION__ < 202311L
21+
/* undef-true-warning@#2 {{'true' is not defined, evaluates to 0}} */
22+
#endif
23+
24+
#if false || true /* #3 */
25+
#endif
26+
#if __STDC_VERSION__ < 202311L
27+
/* undef-true-warning@#3 {{'true' is not defined, evaluates to 0}} */
28+
#endif
29+
30+
#define true 1
31+
32+
#define FOO true
33+
#if FOO
34+
#endif
35+
36+
#if true
37+
#endif
38+
39+
#if false || true
40+
#endif
41+
42+
#undef true
43+
44+
#define FOO true
45+
#if FOO /* #4 */
46+
#endif
47+
#if __STDC_VERSION__ < 202311L
48+
/* undef-true-warning@#4 {{'true' is not defined, evaluates to 0}} */
49+
#endif
50+
51+
#if true /* #5 */
52+
#endif
53+
#if __STDC_VERSION__ < 202311L
54+
/* undef-true-warning@#5 {{'true' is not defined, evaluates to 0}} */
55+
#endif
56+
57+
#if false || true /* #6 */
58+
#endif
59+
#if __STDC_VERSION__ < 202311L
60+
/* undef-true-warning@#6 {{'true' is not defined, evaluates to 0}} */
61+
#endif
62+
63+
#define true true
64+
#if true /* #7 */
65+
#endif
66+
#if __STDC_VERSION__ < 202311L
67+
/* undef-true-warning@#7 {{'true' is not defined, evaluates to 0}} */
68+
#endif
69+
#undef true
70+
71+
/* Test that #pragma-enabled 'Wundef' can override 'Wundef-true' */
72+
#pragma clang diagnostic warning "-Wundef"
73+
#if true /* #8 */
74+
#endif
75+
#pragma clang diagnostic ignored "-Wundef"
76+
#if __STDC_VERSION__ < 202311L
77+
/* undef-true-warning@#8 {{'true' is not defined, evaluates to 0}} */
78+
#endif

0 commit comments

Comments
 (0)