1 /* Test warnings for common punctuation, quoting, and spelling issues
2 in GCC diagnostics.
3 { dg-do compile }
4 { dg-options "-Wformat -Wformat-diag" } */
5
6 /* Magic identifiers must be set before the attribute is used. */
7
8 typedef long long __gcc_host_wide_int__;
9
10 typedef struct location_s
11 {
12 const char *file;
13 int line;
14 } location_t;
15
16 union tree_node;
17 typedef union tree_node *tree;
18
19 /* Define gimple as a dummy type. The typedef must be provided for
20 the C test to find the symbol. */
21 typedef struct gimple gimple;
22
23 /* Likewise for cgraph_node. */
24 typedef struct cgraph_node cgraph_node;
25
26 #define ATTR(...) __attribute__ ((__VA_ARGS__))
27 #define FORMAT(kind) ATTR (format (__gcc_## kind ##__, 1, 2))
28
29 /* Raw formatting function like pp_format. */
30 void diag_raw (const char*, ...) ATTR (format (__gcc_diag_raw__, 1, 2));
31 void cdiag_raw (const char*, ...) ATTR (format (__gcc_cdiag_raw__, 1, 2));
32 void tdiag_raw (const char*, ...) ATTR (format (gcc_tdiag_raw, 1, 2));
33 void cxxdiag_raw (const char*, ...) ATTR (format (gcc_cxxdiag_raw, 1, 2));
34
35 /* Basic formatting function_format. */
36 void diag (const char*, ...) FORMAT (diag);
37
38 /* Diagnostic formatting function like error or warning declared
39 by the C front end. */
40 void cdiag (const char*, ...) FORMAT (cdiag);
41
42 /* Diagnostic formatting function like error or warning declared
43 by the middle-end or back-end. */
44 void tdiag (const char*, ...) FORMAT (tdiag);
45
46 /* Diagnostic formatting function like error or warning declared
47 by the C++ front-end. */
48 void cxxdiag (const char*, ...) FORMAT (cxxdiag);
49
50
51 /* Verify that functions declared with __gcc_diag_raw__ attribute
52 are not subject to -Wformat-diag. */
53
test_diag_raw(tree t,gimple * gc)54 void test_diag_raw (tree t, gimple *gc)
55 {
56 diag_raw ("a b");
57 diag_raw ("newline\n");
58 diag_raw ("lone period.");
59 diag_raw ("multiple punctuators: !!!");
60 diag_raw ("unbalanced paren (");
61 diag_raw ("keyword alignas and identifier_with_underscores");
62 diag_raw ("disable __builtin_abs with the -fno-builtin-abs option");
63 diag_raw ("who says I can't have no stinkin' contractions? ");
64
65 cdiag_raw ("__atomic_sync (%qE) == 7???", t);
66 tdiag_raw ("__builtin_abs (%E) < 0!?!", t);
67 cxxdiag_raw ("template <> int f (%E", t);
68 }
69
70 /* Verify that functions declared with the C front-end __gcc_cdiag__
71 attribute detect invalid whitespace in format strings. */
72
test_cdiag_whitespace(tree t,gimple * gc)73 void test_cdiag_whitespace (tree t, gimple *gc)
74 {
75 (void)&t; (void)&gc;
76
77 /* Verify that strings of leading spaces don't trigger a warning. */
78 cdiag (" a");
79 cdiag (" b");
80 cdiag (" c");
81 cdiag ("%< %>a");
82 cdiag ("%< %>a");
83 cdiag ("a b");
84 cdiag ("a b"); /* { dg-warning "unquoted sequence of 2 consecutive space characters" } */
85 cdiag ("a "); /* { dg-warning "spurious trailing space" } */
86 cdiag ("a "); /* { dg-warning "spurious trailing space" } */
87 cdiag ("a%< %>");
88 cdiag ("a%< %>%< %>");
89 cdiag ("a%< %> "); /* { dg-warning "spurious trailing space" } */
90 cdiag ("a%< %> %< %>"); /* { dg-warning "unquoted sequence of 2 consecutive space characters" } */
91
92 /* It's debatable whether the following two formst strings should
93 be diagnosed. They aren't only because it's simpler that way. */
94 cdiag ("a %< %>");
95 cdiag ("a%< %> %< %>");
96
97 /* Exercise other whitespace characters. */
98 cdiag ("a\fb"); /* { dg-warning "unquoted whitespace character '\\\\x0c'" } */
99 cdiag ("a\nb"); /* { dg-warning "unquoted whitespace character '\\\\x0a'" } */
100 cdiag ("a\rb"); /* { dg-warning "unquoted whitespace character '\\\\x0d'" } */
101 cdiag ("a\vb"); /* { dg-warning "unquoted whitespace character '\\\\x0b'" } */
102
103 cdiag ("First sentence. And a next.");
104 cdiag ("First sentence. not capitalized sentence"); /* { dg-warning "inconsistent capitalization" } */
105
106 #pragma GCC diagnostic push
107 #pragma GCC diagnostic ignored "-Wformat-diag"
108
109 /* Verify that the warning can be suppressed. */
110 cdiag ("\ta\b c\vb\n");
111
112 #pragma GCC diagnostic pop
113 }
114
115
test_cdiag_control(tree t,gimple * gc)116 void test_cdiag_control (tree t, gimple *gc)
117 {
118 (void)&t; (void)&gc;
119
120 cdiag ("\1"); /* { dg-warning "unquoted control character '\\\\x01'" } */
121 cdiag ("a\ab"); /* { dg-warning "unquoted control character '\\\\x07'" } */
122 cdiag ("a\bb"); /* { dg-warning "unquoted control character '\\\\x08'" } */
123 }
124
125
test_cdiag_punct(tree t,gimple * gc,int i)126 void test_cdiag_punct (tree t, gimple *gc, int i)
127 {
128 (void)&t; (void)&gc;
129
130 /* Exercise the period. */
131 cdiag (".abc"); /* { dg-warning "spurious leading punctuation sequence .\.." } */
132 cdiag ("abc;"); /* { dg-warning "spurious trailing punctuation sequence .;." } */
133 /* Verify that sentences that start with an uppercase letter and end
134 in a period are not diagnosed. */
135 cdiag ("This is a full sentence.");
136 cdiag ("Capitalized sentence (with a parethetical note).");
137 cdiag ("Not a full sentence;"); /* { dg-warning "spurious trailing punctuation sequence .;." } */
138 cdiag ("Neither is this one,"); /* { dg-warning "spurious trailing punctuation sequence .,." } */
139
140 /* Exercise the ellipsis. */
141 cdiag ("this message...");
142 cdiag ("...continues here");
143 cdiag ("but...not here"); /* { dg-warning "unquoted sequence of 3 consecutive punctuation characters" } */
144
145 /* Verify that parenthesized sentences are accepted, even the whole
146 meesage (done in the C++ front end). */
147 cdiag ("null argument where non-null required (argument %i)", i);
148 cdiag ("null (argument %i) where non-null required", i);
149 cdiag ("(see what comes next)");
150
151 /* Verify that only a single trailing colon is accepted. */
152 cdiag ("candidates are:");
153 cdiag ("candidates are::"); /* { dg-warning "spurious trailing punctuation sequence .::." } */
154
155 /* Exercise C++. */
156 cdiag ("C++ is cool");
157 cdiag ("this is c++");
158 cdiag ("you can do this in C++ but not in C");
159
160 /* Also verify that G++ is accepted. */
161 cdiag ("G++ rocks");
162 cdiag ("this is accepted by g++");
163 cdiag ("valid in G++ (or g++) but not in gcc");
164
165 /* Exercise parenthetical note followed by a colon, semicolon,
166 or a comma. */
167 cdiag ("found a bug (here):");
168 cdiag ("because of another bug (over there); fix it");
169
170 cdiag ("found foo (123): go look at it");
171 cdiag ("missed bar (abc); will try harder next time");
172
173 cdiag ("expected this (or that), got something else (or who knows what)");
174
175 /* Exercise parenthetical note with a question mark. */
176 cdiag ("hmmm (did you really mean that?)");
177 cdiag ("error (did you mean %<foo()%>?)");
178 /* And a question mark after a parenthetical note. */
179 cdiag ("did you mean this (or that)?");
180
181 /* But make sure unbalanced parenthese are diagnosed. */
182 cdiag ("or this or the other)?"); /* { dg-warning "unbalanced punctuation character '\\\)'" } */
183
184 cdiag ("## Heading"); /* { dg-warning "spurious leading punctuation sequence .##." } */
185 cdiag ("## %s ##", "1"); /* { dg-warning "spurious (leading|trailing) punctuation sequence .##." } */
186
187 cdiag ("#1 priority"); /* { dg-warning "spurious leading punctuation sequence .#." } */
188 cdiag ("priority #2");
189
190 /* Quoting. */
191 cdiag ("\"quoted\"");
192 cdiag ("\"quoted\" string");
193 cdiag ("this is a \"string in quotes\"");
194 cdiag ("\"missing closing quote"); /* { dg-warning "unterminated quote character '\"'" } */
195
196 /* PR translation/90121 - punctuation character after a space. */
197 cdiag ("bad version : 1"); /* { dg-warning "space followed by punctuation character ':'" } */
198 cdiag ("problem ; fix it"); /* { dg-warning "space followed by punctuation character ';'" } */
199 cdiag ("End . not."); /* { dg-warning "space followed by punctuation character '.'" } */
200 cdiag ("it is bad , very bad"); /* { dg-warning "space followed by punctuation character ','" } */
201 cdiag ("say what ?"); /* { dg-warning "space followed by punctuation character '?'" } */
202
203 /* But these are okay after a space. But should they be? */
204 cdiag ("1 / 2");
205 cdiag ("2 + 3");
206 cdiag ("2 - 3");
207 }
208
test_cdiag_punct_balance(tree t,gimple * gc)209 void test_cdiag_punct_balance (tree t, gimple *gc)
210 {
211 (void)&t; (void)&gc;
212
213 /* Less-than and greater than. */
214 cdiag ("a < b"); /* { dg-warning "unbalanced punctuation character '<' in format" } */
215 cdiag ("must be > 0"); /* { dg-warning "unbalanced punctuation character '>' in format" } */
216
217 cdiag ("f()"); /* { dg-warning "spurious trailing punctuation sequence .\\\(\\\)." } */
218 cdiag ("g(1)");
219 cdiag ("("); /* { dg-warning "spurious leading punctuation character|unbalanced" } */
220 cdiag ("()"); /* { dg-warning "spurious leading punctuation sequence" } */
221 cdiag (")"); /* { dg-warning "unbalanced punctuation character '\\\)'" } */
222 cdiag ("f()g"); /* { dg-warning "unquoted sequence of 2 consecutive punctuation characters" } */
223 cdiag ("illegal operand (1)");
224 }
225
226
test_cdiag_nongraph(tree t,gimple * gc)227 void test_cdiag_nongraph (tree t, gimple *gc)
228 {
229 (void)&t; (void)&gc;
230
231 cdiag ("a\376b"); /* { dg-warning "unquoted non-graph character '\\\\xfe'" } */
232 cdiag ("a\377b"); /* { dg-warning "unquoted non-graph character '\\\\xff'" } */
233 }
234
235
test_cdiag_attribute(tree t,gimple * gc)236 void test_cdiag_attribute (tree t, gimple *gc)
237 {
238 (void)&t; (void)&gc;
239
240 cdiag ("attribute foo");
241 cdiag ("this is attribute bar");
242 cdiag ("bad __attribute bar"); /* { dg-warning "unquoted attribute" } */
243 cdiag ("__attribute__ (foobar) bad"); /* { dg-warning "unquoted attribute" } */
244 cdiag ("__attribute__ ((foobar))"); /* { dg-warning "unquoted attribute" } */
245 cdiag ("__attribute__ (xxx))"); /* { dg-warning "unquoted attribute" } */
246 /* { dg-warning "unbalanced punctuation character '\\\)'" "xxx" { target *-*-* } .-1 } */
247 cdiag ("__attribute__ ((yyy)))"); /* { dg-warning "unquoted attribute" } */
248 /* { dg-warning "unbalanced punctuation character '\\\)'" "yyy" { target *-*-* } .-1 } */
249 cdiag ("__attribute__ ((zzz)"); /* { dg-warning "unquoted attribute" } */
250 /* { dg-warning "unbalanced punctuation character '\\\('" "zzz" { target *-*-* } .-1 } */
251
252 #pragma GCC diagnostic push
253 #pragma GCC diagnostic ignored "-Wformat-diag"
254
255 /* Verify that the warning can be suppressed. */
256 cdiag ("__attribute__ (((");
257
258 #pragma GCC diagnostic pop
259 }
260
test_cdiag_builtin(tree t,gimple * gc)261 void test_cdiag_builtin (tree t, gimple *gc)
262 {
263 (void)&t; (void)&gc;
264
265 cdiag ("__builtin_abort"); /* { dg-warning "unquoted name of built-in function '__builtin_abort'" } */
266 cdiag ("in __builtin_trap"); /* { dg-warning "unquoted name of built-in function '__builtin_trap'" } */
267 cdiag ("__builtin_xyz bites");/* { dg-warning "unquoted name of built-in function '__builtin_xyz'" } */
268
269 #pragma GCC diagnostic push
270 #pragma GCC diagnostic ignored "-Wformat-diag"
271
272 /* Verify that the warning can be suppressed. */
273 cdiag ("__builtin____with____lots__of__underscores");
274
275 #pragma GCC diagnostic pop
276 }
277
278
test_cdiag_option(tree t,gimple * gc)279 void test_cdiag_option (tree t, gimple *gc)
280 {
281 (void)&t; (void)&gc;
282
283 cdiag ("%<-Wall%>");
284 cdiag ("use option %<-Wextra%> to enable additinal warnings");
285
286 cdiag ("-O2 is fast"); /* { dg-warning "unquoted option name '-O2'" } */
287 cdiag ("but -O3 is faster"); /* { dg-warning "unquoted option name '-O3'" } */
288
289 cdiag ("get --help"); /* { dg-warning "unquoted option name '--help'" } */
290 cdiag ("enable -m32"); /* { dg-warning "unquoted option name '-m32'" } */
291 cdiag ("value is -12");
292 cdiag ("foo-O2");
293 cdiag ("a-W");
294 }
295
296
test_cdiag_keyword(tree t,gimple * gc)297 void test_cdiag_keyword (tree t, gimple *gc)
298 {
299 cdiag ("alignasi");
300 cdiag ("malignofer or alignofus");
301 cdiag ("use alignof"); /* { dg-warning "unquoted keyword 'alignof'" } */
302 cdiag ("or _Alignof"); /* { dg-warning " keyword '_Alignof'" } */
303 cdiag ("_Pragma too"); /* { dg-warning " keyword '_Pragma'" } */
304
305 cdiag ("a #error directive"); /* { dg-warning "unquoted preprocessing directive '#error'" } */
306 cdiag ("#include file"); /* { dg-warning "unquoted preprocessing directive '#include'" } */
307 cdiag ("but #pragma foobar"); /* { dg-warning "unquoted preprocessing directive '#pragma'" } */
308 cdiag ("pragma foobar is okay");
309 cdiag ("or even # pragma is fine");
310
311 /* Exercise qualifiers. */
312 cdiag ("const function");
313 cdiag ("const-qualified variable"); /* { dg-warning "unquoted keyword 'const-qualified'" } */
314 /* { dg-message "use '%<const%>-qualified' instead" "const-qualified" { target *-*-* } .-1 } */
315 cdiag ("a const %qD", t); /* { dg-warning "unquoted keyword 'const'" } */
316 cdiag ("restrict %qE", t); /* { dg-warning "unquoted keyword 'restrict'" } */
317 cdiag ("volatile %qT", t); /* { dg-warning "unquoted keyword 'volatile'" } */
318 cdiag ("const %qD and restrict %qE or volatile %qT", t, t, t);
319 /* { dg-warning "unquoted keyword 'const'" "" { target *-*-* } .-1 } */
320 /* { dg-warning "unquoted keyword 'restrict'" "" { target *-*-* } .-2 } */
321 /* { dg-warning "unquoted keyword 'volatile'" "" { target *-*-* } .-3 } */
322
323 cdiag ("an offsetof here"); /* { dg-warning "unquoted keyword 'offsetof" } */
324 cdiag ("sizeof x"); /* { dg-warning "unquoted keyword 'sizeof" } */
325 cdiag ("have typeof"); /* { dg-warning "unquoted keyword 'typeof" } */
326
327 /* Words that are not keywords are so are not expected to be quoted. */
328 cdiag ("break rules");
329 cdiag ("if we continue by default for a short while else do nothing");
330 cdiag ("register a function for unsigned extern to void const reads");
331 cdiag ("or volatile access");
332 }
333
334
test_cdiag_operator(tree t,gimple * gc)335 void test_cdiag_operator (tree t, gimple *gc)
336 {
337 cdiag ("x != 0"); /* { dg-warning "unquoted operator '!='" } */
338 cdiag ("logical &&"); /* { dg-warning "unquoted operator '&&" } */
339 cdiag ("+= operator"); /* { dg-warning "unquoted operator '\\\+=" } */
340 cdiag ("a == b"); /* { dg-warning "unquoted operator '=='" } */
341 cdiag ("++a"); /* { dg-warning "unquoted operator '\\\+\\\+'" } */
342 cdiag ("b--"); /* { dg-warning "unquoted operator '--'" } */
343 cdiag ("1 << 2"); /* { dg-warning "unquoted operator '<<'" } */
344 cdiag (">> here <<"); /* { dg-warning "unquoted operator '>>|<<'" } */
345 }
346
347
test_cdiag_type_name(tree t,gimple * gc)348 void test_cdiag_type_name (tree t, gimple *gc)
349 {
350 cdiag ("the word character should not be quoted");
351 cdiag ("but char should be"); /* { dg-warning "unquoted keyword 'char'" } */
352
353 cdiag ("unsigned char should be quoted"); /* { dg-warning "unquoted type name 'unsigned char'" } */
354 cdiag ("but unsigned character is fine");
355
356 cdiag ("as should int"); /* { dg-warning "unquoted keyword 'int'" } */
357 cdiag ("and signed int"); /* { dg-warning "unquoted type name 'signed int'" } */
358 cdiag ("and also unsigned int"); /* { dg-warning "unquoted type name 'unsigned int'" } */
359 cdiag ("very long thing");
360 cdiag ("use long long here"); /* { dg-warning "unquoted type name 'long long'" } */
361
362 cdiag ("have a floating type");
363 cdiag ("found float type"); /* { dg-warning "unquoted keyword 'float'" } */
364
365 cdiag ("wchar_t is wide"); /* { dg-warning "unquoted identifier or keyword 'wchar_t'" } */
366 }
367
368
test_cdiag_identifier(tree t,gimple * gc)369 void test_cdiag_identifier (tree t, gimple *gc)
370 {
371 (void)&t; (void)&gc;
372
373 cdiag ("private _x ident"); /* { dg-warning "unquoted identifier or keyword '_x'" } */
374 cdiag ("and another __y"); /* { dg-warning "unquoted identifier or keyword '__y'" } */
375 cdiag ("ident z_ with trailing underscore"); /* { dg-warning "unquoted identifier or keyword 'z_'" } */
376 cdiag ("v_ variable"); /* { dg-warning "unquoted identifier or keyword 'v_'" } */
377 cdiag ("call foo_bar"); /* { dg-warning "unquoted identifier or keyword 'foo_bar'" } */
378 cdiag ("unqoted x_y ident"); /* { dg-warning "unquoted identifier or keyword 'x_y'" } */
379
380 cdiag ("size_t type"); /* { dg-warning "unquoted identifier or keyword 'size_t'" } */
381 cdiag ("bigger than INT_MAX");/* { dg-warning "unquoted identifier or keyword 'INT_MAX'" } */
382
383 cdiag ("quoted ident %<a_b%>");
384 cdiag ("another quoted identifier %<x_%> here");
385 }
386
387
test_cdiag_bad_words(tree t,gimple * gc)388 void test_cdiag_bad_words (tree t, gimple *gc)
389 {
390 (void)&t; (void)&gc;
391
392 cdiag ("aren't you dumb?"); /* { dg-warning "bare apostrophe ''' in format" } */
393 cdiag ("bitfields suck"); /* { dg-warning "misspelled term 'bitfields' in format; use 'bit-fields' instead" } */
394 cdiag ("invalid bitfield"); /* { dg-warning "misspelled term 'bitfield' in format; use 'bit-field' instead" } */
395 cdiag ("bad builtin function"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
396 cdiag ("bad builtin function"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
397 cdiag ("builtin function x"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
398 cdiag ("builtin functions disabled"); /* { dg-warning "misspelled term 'builtin functions' in format; use 'built-in functions' instead" } */
399 cdiag ("enable builtin functions"); /* { dg-warning "misspelled term 'builtin functions' in format; use 'built-in functions' instead" } */
400 cdiag ("you can't do that"); /* { dg-warning "contraction 'can't' in format" } */
401 cdiag ("you can%'t do that");/* { dg-warning "contraction 'can%'t' in format" } */
402 cdiag ("Can%'t touch this.");/* { dg-warning "contraction 'Can%'t' in format" } */
403 cdiag ("can%'");
404 cdiag ("can%' whatever");
405 cdiag ("on the commandline");/* { dg-warning "misspelled term 'commandline' in format; use 'command line' instead" } */
406 cdiag ("command line option");/* { dg-warning "misspelled term 'command line option' in format; use 'command-line option' instead" } */
407 cdiag ("it mustn't be"); /* { dg-warning "contraction 'mustn't' in format" } */
408 cdiag ("isn't that silly?"); /* { dg-warning "bare apostrophe ''' in format" } */
409
410 cdiag ("can not do this"); /* { dg-warning "misspelled term 'can not' in format; use 'cannot' instead" } */
411 cdiag ("you can not"); /* { dg-warning "misspelled term 'can not' in format; use 'cannot' instead" } */
412
413 /* See PR target/90157 - aarch64: unnecessary abbreviation in diagnostic */
414 cdiag ("Mising arg."); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
415 cdiag ("2 args: a and b"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
416 cdiag ("arg 1"); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
417 cdiag ("Args are wrong."); /* { dg-warning "misspelled term 'Args' in format; use 'arguments' instead" } */
418 cdiag ("bad arg"); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
419 cdiag ("two args"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
420 cdiag ("args 1 and 2"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
421
422 cdiag ("Reg A"); /* { dg-warning "misspelled term 'Reg' in format; use 'register' instead" } */
423 cdiag ("regs A and B"); /* { dg-warning "misspelled term 'regs' in format; use 'registers' instead" } */
424 cdiag ("no regs"); /* { dg-warning "misspelled term 'regs' in format; use 'registers' instead" } */
425
426 /* Verify words that end in "arg" and "args" or "reg" and "regs" are
427 not diagnosed. */
428 cdiag ("gulmarg and balfarg");
429 cdiag ("ademargs or toshargs");
430 cdiag ("talk to Greg");
431 cdiag ("prepreg is a fabric");
432 cdiag ("there are dregs in my wine");
433 }
434
435
test_cdiag_directive(tree t,gimple * gc)436 void test_cdiag_directive (tree t, gimple *gc)
437 {
438 (void)&t; (void)&gc;
439
440 cxxdiag ("%<%s%>", ""); /* { dg-warning "quoted '%s' directive in format" } */
441 /* This was asked to be diagnosed in PR #90158 but there, the \"%s\"
442 is in parenheses which ends up getting diagnosed because of
443 the two consecutive punctuation characters, ( and ". */
444 cdiag ("\"%s\"", ""); /* { dg-warning "quoted '%s' directive in format" } */
445
446 /* Make sure quoted paired tokens are not diagnosed. */
447 cdiag ("%<'%>");
448 cdiag ("%<\"%>");
449 cdiag ("%<<%>");
450 cdiag ("%<>%>");
451 cdiag ("%<(%>");
452 cdiag ("%<)%>");
453 cdiag ("%<[%>");
454 cdiag ("%<]%>");
455
456 cdiag ("%<'%> %<\"%> %<>%> %<<%> %<)%> %<(%> %<]%> %<[%>");
457 }
458