]>
Commit | Line | Data |
---|---|---|
c3388e62 | 1 | /* Implementation of -Wmisleading-indentation |
83ffe9cd | 2 | Copyright (C) 2015-2023 Free Software Foundation, Inc. |
c3388e62 DM |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tm.h" | |
2adfab87 | 24 | #include "c-common.h" |
992118a1 | 25 | #include "c-indentation.h" |
10fcc142 | 26 | #include "selftest.h" |
004bb936 | 27 | #include "diagnostic.h" |
c3388e62 | 28 | |
64b23c13 DM |
29 | /* Round up VIS_COLUMN to nearest tab stop. */ |
30 | ||
31 | static unsigned int | |
10fcc142 | 32 | next_tab_stop (unsigned int vis_column, unsigned int tab_width) |
64b23c13 | 33 | { |
64b23c13 DM |
34 | vis_column = ((vis_column + tab_width) / tab_width) * tab_width; |
35 | return vis_column; | |
36 | } | |
37 | ||
c3388e62 DM |
38 | /* Convert libcpp's notion of a column (a 1-based char count) to |
39 | the "visual column" (0-based column, respecting tabs), by reading the | |
40 | relevant line. | |
1a1e101f | 41 | |
c3388e62 | 42 | Returns true if a conversion was possible, writing the result to OUT, |
1a1e101f PP |
43 | otherwise returns false. If FIRST_NWS is not NULL, then write to it |
44 | the visual column corresponding to the first non-whitespace character | |
10fcc142 | 45 | on the line (up to or before EXPLOC). */ |
c3388e62 DM |
46 | |
47 | static bool | |
4394b1ce | 48 | get_visual_column (expanded_location exploc, |
1a1e101f | 49 | unsigned int *out, |
10fcc142 DM |
50 | unsigned int *first_nws, |
51 | unsigned int tab_width) | |
c3388e62 | 52 | { |
7761dfbe | 53 | char_span line = location_get_source_line (exploc.file, exploc.line); |
c3388e62 DM |
54 | if (!line) |
55 | return false; | |
10fcc142 DM |
56 | if ((size_t)exploc.column > line.length ()) |
57 | return false; | |
c3388e62 DM |
58 | unsigned int vis_column = 0; |
59 | for (int i = 1; i < exploc.column; i++) | |
60 | { | |
61 | unsigned char ch = line[i - 1]; | |
1a1e101f PP |
62 | |
63 | if (first_nws != NULL && !ISSPACE (ch)) | |
64 | { | |
65 | *first_nws = vis_column; | |
66 | first_nws = NULL; | |
67 | } | |
68 | ||
c3388e62 | 69 | if (ch == '\t') |
10fcc142 | 70 | vis_column = next_tab_stop (vis_column, tab_width); |
c3388e62 DM |
71 | else |
72 | vis_column++; | |
73 | } | |
74 | ||
1a1e101f PP |
75 | if (first_nws != NULL) |
76 | *first_nws = vis_column; | |
c3388e62 | 77 | |
1a1e101f | 78 | *out = vis_column; |
c3388e62 DM |
79 | return true; |
80 | } | |
81 | ||
64b23c13 DM |
82 | /* Attempt to determine the first non-whitespace character in line LINE_NUM |
83 | of source line FILE. | |
84 | ||
85 | If this is possible, return true and write its "visual column" to | |
86 | *FIRST_NWS. | |
87 | Otherwise, return false, leaving *FIRST_NWS untouched. */ | |
c3388e62 DM |
88 | |
89 | static bool | |
64b23c13 | 90 | get_first_nws_vis_column (const char *file, int line_num, |
10fcc142 DM |
91 | unsigned int *first_nws, |
92 | unsigned int tab_width) | |
c3388e62 | 93 | { |
64b23c13 DM |
94 | gcc_assert (first_nws); |
95 | ||
7761dfbe | 96 | char_span line = location_get_source_line (file, line_num); |
c3388e62 DM |
97 | if (!line) |
98 | return false; | |
64b23c13 | 99 | unsigned int vis_column = 0; |
7761dfbe | 100 | for (size_t i = 1; i < line.length (); i++) |
64b23c13 DM |
101 | { |
102 | unsigned char ch = line[i - 1]; | |
c3388e62 | 103 | |
64b23c13 DM |
104 | if (!ISSPACE (ch)) |
105 | { | |
106 | *first_nws = vis_column; | |
107 | return true; | |
108 | } | |
c3388e62 | 109 | |
64b23c13 | 110 | if (ch == '\t') |
10fcc142 | 111 | vis_column = next_tab_stop (vis_column, tab_width); |
64b23c13 DM |
112 | else |
113 | vis_column++; | |
c3388e62 DM |
114 | } |
115 | ||
64b23c13 | 116 | /* No non-whitespace characters found. */ |
c3388e62 DM |
117 | return false; |
118 | } | |
119 | ||
64b23c13 | 120 | /* Determine if there is an unindent/outdent between |
c3388e62 | 121 | BODY_EXPLOC and NEXT_STMT_EXPLOC, to ensure that we don't |
64b23c13 DM |
122 | issue a warning for cases like the following: |
123 | ||
124 | (1) Preprocessor logic | |
c3388e62 DM |
125 | |
126 | if (flagA) | |
127 | foo (); | |
128 | ^ BODY_EXPLOC | |
129 | #if SOME_CONDITION_THAT_DOES_NOT_HOLD | |
130 | if (flagB) | |
131 | #endif | |
132 | bar (); | |
133 | ^ NEXT_STMT_EXPLOC | |
134 | ||
64b23c13 DM |
135 | "bar ();" is visually aligned below "foo ();" and |
136 | is (as far as the parser sees) the next token, but | |
137 | this isn't misleading to a human reader. | |
c3388e62 | 138 | |
64b23c13 | 139 | (2) Empty macro with bad indentation |
c3388e62 | 140 | |
64b23c13 DM |
141 | In the following, the |
142 | "if (i > 0)" | |
143 | is poorly indented, and ought to be on the same column as | |
144 | "engine_ref_debug(e, 0, -1)" | |
145 | However, it is not misleadingly indented, due to the presence | |
146 | of that macro. | |
c3388e62 | 147 | |
64b23c13 DM |
148 | #define engine_ref_debug(X, Y, Z) |
149 | ||
150 | if (locked) | |
151 | i = foo (0); | |
152 | else | |
153 | i = foo (1); | |
154 | engine_ref_debug(e, 0, -1) | |
155 | if (i > 0) | |
156 | return 1; | |
c3388e62 | 157 | |
64b23c13 | 158 | Return true if such an unindent/outdent is detected. */ |
c3388e62 | 159 | |
64b23c13 DM |
160 | static bool |
161 | detect_intervening_unindent (const char *file, | |
162 | int body_line, | |
163 | int next_stmt_line, | |
10fcc142 DM |
164 | unsigned int vis_column, |
165 | unsigned int tab_width) | |
64b23c13 DM |
166 | { |
167 | gcc_assert (file); | |
168 | gcc_assert (next_stmt_line > body_line); | |
169 | ||
170 | for (int line = body_line + 1; line < next_stmt_line; line++) | |
171 | { | |
172 | unsigned int line_vis_column; | |
10fcc142 | 173 | if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width)) |
64b23c13 DM |
174 | if (line_vis_column < vis_column) |
175 | return true; | |
176 | } | |
c3388e62 DM |
177 | |
178 | /* Not found. */ | |
179 | return false; | |
180 | } | |
181 | ||
182 | ||
183 | /* Helper function for warn_for_misleading_indentation; see | |
184 | description of that function below. */ | |
185 | ||
186 | static bool | |
992118a1 PP |
187 | should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo, |
188 | const token_indent_info &body_tinfo, | |
189 | const token_indent_info &next_tinfo) | |
c3388e62 | 190 | { |
c3388e62 DM |
191 | /* Don't attempt to compare indentation if #line or # 44 "file"-style |
192 | directives are present, suggesting generated code. | |
193 | ||
194 | All bets are off if these are present: the file that the #line | |
195 | directive could have an entirely different coding layout to C/C++ | |
196 | (e.g. .md files). | |
197 | ||
198 | To determine if a #line is present, in theory we could look for a | |
199 | map with reason == LC_RENAME_VERBATIM. However, if there has | |
200 | subsequently been a long line requiring a column number larger than | |
201 | that representable by the original LC_RENAME_VERBATIM map, then | |
202 | we'll have a map with reason LC_RENAME. | |
203 | Rather than attempting to search all of the maps for a | |
204 | LC_RENAME_VERBATIM, instead we have libcpp set a flag whenever one | |
205 | is seen, and we check for the flag here. | |
206 | */ | |
207 | if (line_table->seen_line_directive) | |
208 | return false; | |
209 | ||
b3a77f21 MP |
210 | /* We can't usefully warn about do-while and switch statements since the |
211 | bodies of these statements are always explicitly delimited at both ends, | |
212 | so control flow is quite obvious. */ | |
213 | if (guard_tinfo.keyword == RID_DO | |
214 | || guard_tinfo.keyword == RID_SWITCH) | |
21efdd80 PP |
215 | return false; |
216 | ||
992118a1 PP |
217 | /* If the token following the body is a close brace or an "else" |
218 | then while indentation may be sloppy, there is not much ambiguity | |
219 | about control flow, e.g. | |
220 | ||
221 | if (foo) <- GUARD | |
222 | bar (); <- BODY | |
223 | else baz (); <- NEXT | |
224 | ||
225 | { | |
226 | while (foo) <- GUARD | |
227 | bar (); <- BODY | |
228 | } <- NEXT | |
229 | baz (); | |
230 | */ | |
4839de55 | 231 | enum cpp_ttype next_tok_type = next_tinfo.type; |
992118a1 PP |
232 | if (next_tok_type == CPP_CLOSE_BRACE |
233 | || next_tinfo.keyword == RID_ELSE) | |
c3388e62 DM |
234 | return false; |
235 | ||
8ebca419 PP |
236 | /* Likewise, if the body of the guard is a compound statement then control |
237 | flow is quite visually explicit regardless of the code's possibly poor | |
238 | indentation, e.g. | |
239 | ||
240 | while (foo) <- GUARD | |
241 | { <- BODY | |
242 | bar (); | |
243 | } | |
244 | baz (); <- NEXT | |
245 | ||
246 | Things only get muddy when the body of the guard does not have | |
247 | braces, e.g. | |
248 | ||
249 | if (foo) <- GUARD | |
250 | bar (); <- BODY | |
251 | baz (); <- NEXT | |
252 | */ | |
4839de55 | 253 | enum cpp_ttype body_type = body_tinfo.type; |
8ebca419 PP |
254 | if (body_type == CPP_OPEN_BRACE) |
255 | return false; | |
256 | ||
c3388e62 DM |
257 | /* Don't warn here about spurious semicolons. */ |
258 | if (next_tok_type == CPP_SEMICOLON) | |
259 | return false; | |
260 | ||
4839de55 PP |
261 | location_t guard_loc = guard_tinfo.location; |
262 | location_t body_loc = body_tinfo.location; | |
263 | location_t next_stmt_loc = next_tinfo.location; | |
264 | ||
265 | /* Resolve each token location to the respective macro expansion | |
266 | point that produced the token. */ | |
267 | if (linemap_location_from_macro_expansion_p (line_table, guard_loc)) | |
268 | guard_loc = linemap_resolve_location (line_table, guard_loc, | |
269 | LRK_MACRO_EXPANSION_POINT, NULL); | |
270 | if (linemap_location_from_macro_expansion_p (line_table, body_loc)) | |
271 | body_loc = linemap_resolve_location (line_table, body_loc, | |
272 | LRK_MACRO_EXPANSION_POINT, NULL); | |
273 | if (linemap_location_from_macro_expansion_p (line_table, next_stmt_loc)) | |
274 | next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc, | |
275 | LRK_MACRO_EXPANSION_POINT, NULL); | |
276 | ||
277 | /* When all three tokens are produced from a single macro expansion, we | |
278 | instead consider their loci inside that macro's definition. */ | |
279 | if (guard_loc == body_loc && body_loc == next_stmt_loc) | |
280 | { | |
281 | const line_map *guard_body_common_map | |
282 | = first_map_in_common (line_table, | |
283 | guard_tinfo.location, body_tinfo.location, | |
284 | &guard_loc, &body_loc); | |
285 | const line_map *body_next_common_map | |
286 | = first_map_in_common (line_table, | |
287 | body_tinfo.location, next_tinfo.location, | |
288 | &body_loc, &next_stmt_loc); | |
289 | ||
290 | /* Punt on complicated nesting of macros. */ | |
291 | if (guard_body_common_map != body_next_common_map) | |
292 | return false; | |
293 | ||
294 | guard_loc = linemap_resolve_location (line_table, guard_loc, | |
295 | LRK_MACRO_DEFINITION_LOCATION, NULL); | |
296 | body_loc = linemap_resolve_location (line_table, body_loc, | |
297 | LRK_MACRO_DEFINITION_LOCATION, NULL); | |
298 | next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc, | |
299 | LRK_MACRO_DEFINITION_LOCATION, | |
300 | NULL); | |
301 | } | |
302 | ||
6ac48155 DM |
303 | expanded_location body_exploc = expand_location (body_loc); |
304 | expanded_location next_stmt_exploc = expand_location (next_stmt_loc); | |
8ebca419 | 305 | expanded_location guard_exploc = expand_location (guard_loc); |
c3388e62 | 306 | |
4394b1ce PP |
307 | /* PR c++/68819: if the column number is zero, we presumably |
308 | had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so | |
309 | we have no column information. */ | |
310 | if (!guard_exploc.column || !body_exploc.column || !next_stmt_exploc.column) | |
311 | { | |
312 | static bool issued_note = false; | |
313 | if (!issued_note) | |
314 | { | |
315 | /* Notify the user the first time this happens. */ | |
316 | issued_note = true; | |
317 | inform (guard_loc, | |
318 | "%<-Wmisleading-indentation%> is disabled from this point" | |
319 | " onwards, since column-tracking was disabled due to" | |
320 | " the size of the code/headers"); | |
321 | if (!flag_large_source_files) | |
322 | inform (guard_loc, | |
323 | "adding %<-flarge-source-files%> will allow for more" | |
324 | " column-tracking support, at the expense of compilation" | |
325 | " time and memory"); | |
326 | } | |
327 | return false; | |
328 | } | |
329 | ||
330 | /* Give up if the loci are not all distinct. */ | |
331 | if (guard_loc == body_loc || body_loc == next_stmt_loc) | |
332 | return false; | |
333 | ||
004bb936 | 334 | const unsigned int tab_width = global_dc->tabstop; |
10fcc142 | 335 | |
c3388e62 DM |
336 | /* They must be in the same file. */ |
337 | if (next_stmt_exploc.file != body_exploc.file) | |
338 | return false; | |
339 | ||
340 | /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider | |
341 | the location of the guard. | |
342 | ||
343 | Cases where we want to issue a warning: | |
344 | ||
345 | if (flag) | |
346 | foo (); bar (); | |
347 | ^ WARN HERE | |
348 | ||
349 | if (flag) foo (); bar (); | |
350 | ^ WARN HERE | |
351 | ||
8ebca419 PP |
352 | |
353 | if (flag) ; { | |
354 | ^ WARN HERE | |
355 | ||
356 | if (flag) | |
357 | ; { | |
358 | ^ WARN HERE | |
359 | ||
c3388e62 DM |
360 | Cases where we don't want to issue a warning: |
361 | ||
362 | various_code (); if (flag) foo (); bar (); more_code (); | |
363 | ^ DON'T WARN HERE. */ | |
364 | if (next_stmt_exploc.line == body_exploc.line) | |
365 | { | |
c3388e62 DM |
366 | if (guard_exploc.file != body_exploc.file) |
367 | return true; | |
368 | if (guard_exploc.line < body_exploc.line) | |
369 | /* The guard is on a line before a line that contains both | |
370 | the body and the next stmt. */ | |
371 | return true; | |
372 | else if (guard_exploc.line == body_exploc.line) | |
373 | { | |
374 | /* They're all on the same line. */ | |
375 | gcc_assert (guard_exploc.file == next_stmt_exploc.file); | |
376 | gcc_assert (guard_exploc.line == next_stmt_exploc.line); | |
1a1e101f PP |
377 | unsigned int guard_vis_column; |
378 | unsigned int guard_line_first_nws; | |
4394b1ce | 379 | if (!get_visual_column (guard_exploc, |
1a1e101f | 380 | &guard_vis_column, |
10fcc142 | 381 | &guard_line_first_nws, tab_width)) |
1a1e101f | 382 | return false; |
c3388e62 DM |
383 | /* Heuristic: only warn if the guard is the first thing |
384 | on its line. */ | |
1a1e101f | 385 | if (guard_vis_column == guard_line_first_nws) |
c3388e62 DM |
386 | return true; |
387 | } | |
388 | } | |
389 | ||
390 | /* If NEXT_STMT_LOC is on a line after BODY_LOC, consider | |
391 | their relative locations, and of the guard. | |
392 | ||
393 | Cases where we want to issue a warning: | |
394 | if (flag) | |
395 | foo (); | |
396 | bar (); | |
397 | ^ WARN HERE | |
398 | ||
399 | Cases where we don't want to issue a warning: | |
400 | if (flag) | |
401 | foo (); | |
402 | bar (); | |
403 | ^ DON'T WARN HERE (autogenerated code?) | |
404 | ||
405 | if (flagA) | |
406 | foo (); | |
407 | #if SOME_CONDITION_THAT_DOES_NOT_HOLD | |
408 | if (flagB) | |
409 | #endif | |
410 | bar (); | |
411 | ^ DON'T WARN HERE | |
6ac48155 | 412 | |
8ebca419 PP |
413 | if (flag) |
414 | ; | |
415 | foo (); | |
416 | ^ DON'T WARN HERE | |
c589e975 DM |
417 | |
418 | #define emit | |
419 | if (flag) | |
420 | foo (); | |
421 | emit bar (); | |
422 | ^ DON'T WARN HERE | |
423 | ||
c3388e62 DM |
424 | */ |
425 | if (next_stmt_exploc.line > body_exploc.line) | |
426 | { | |
427 | /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same | |
428 | "visual column"... */ | |
429 | unsigned int next_stmt_vis_column; | |
c589e975 | 430 | unsigned int next_stmt_line_first_nws; |
c3388e62 | 431 | unsigned int body_vis_column; |
8ebca419 | 432 | unsigned int body_line_first_nws; |
d5398058 PP |
433 | unsigned int guard_vis_column; |
434 | unsigned int guard_line_first_nws; | |
c3388e62 DM |
435 | /* If we can't determine it, don't issue a warning. This is sometimes |
436 | the case for input files containing #line directives, and these | |
437 | are often for autogenerated sources (e.g. from .md files), where | |
438 | it's not clear that it's meaningful to look at indentation. */ | |
4394b1ce | 439 | if (!get_visual_column (next_stmt_exploc, |
c7df95d8 | 440 | &next_stmt_vis_column, |
10fcc142 | 441 | &next_stmt_line_first_nws, tab_width)) |
c3388e62 | 442 | return false; |
4394b1ce | 443 | if (!get_visual_column (body_exploc, |
8ebca419 | 444 | &body_vis_column, |
10fcc142 | 445 | &body_line_first_nws, tab_width)) |
c3388e62 | 446 | return false; |
4394b1ce | 447 | if (!get_visual_column (guard_exploc, |
d5398058 | 448 | &guard_vis_column, |
10fcc142 | 449 | &guard_line_first_nws, tab_width)) |
d5398058 PP |
450 | return false; |
451 | ||
c589e975 DM |
452 | /* If the line where the next stmt starts has non-whitespace |
453 | on it before the stmt, then don't warn: | |
454 | #define emit | |
455 | if (flag) | |
456 | foo (); | |
457 | emit bar (); | |
458 | ^ DON'T WARN HERE | |
459 | (PR c/69122). */ | |
460 | if (next_stmt_line_first_nws < next_stmt_vis_column) | |
461 | return false; | |
462 | ||
8ebca419 PP |
463 | if ((body_type != CPP_SEMICOLON |
464 | && next_stmt_vis_column == body_vis_column) | |
465 | /* As a special case handle the case where the body is a semicolon | |
466 | that may be hidden by a preceding comment, e.g. */ | |
467 | ||
468 | // if (p) | |
469 | // /* blah */; | |
470 | // foo (1); | |
471 | ||
472 | /* by looking instead at the column of the first non-whitespace | |
473 | character on the body line. */ | |
474 | || (body_type == CPP_SEMICOLON | |
475 | && body_exploc.line > guard_exploc.line | |
476 | && body_line_first_nws != body_vis_column | |
d5398058 | 477 | && next_stmt_vis_column > guard_line_first_nws)) |
c3388e62 | 478 | { |
8ebca419 PP |
479 | /* Don't warn if they are aligned on the same column |
480 | as the guard itself (suggesting autogenerated code that doesn't | |
729526f5 DM |
481 | bother indenting at all). |
482 | For "else" clauses, we consider the column of the first | |
8ebca419 PP |
483 | non-whitespace character on the guard line instead of the column |
484 | of the actual guard token itself because it is more sensible. | |
485 | Consider: | |
486 | ||
487 | if (p) { | |
488 | foo (1); | |
489 | } else // GUARD | |
490 | foo (2); // BODY | |
491 | foo (3); // NEXT | |
492 | ||
493 | and: | |
494 | ||
495 | if (p) | |
496 | foo (1); | |
497 | } else // GUARD | |
498 | foo (2); // BODY | |
499 | foo (3); // NEXT | |
500 | ||
729526f5 | 501 | If we just used the column of the "else" token, we would warn on |
8ebca419 PP |
502 | the first example and not warn on the second. But we want the |
503 | exact opposite to happen: to not warn on the first example (which | |
504 | is probably autogenerated) and to warn on the second (whose | |
505 | indentation is misleading). Using the column of the first | |
506 | non-whitespace character on the guard line makes that | |
507 | happen. */ | |
729526f5 DM |
508 | unsigned int guard_column = (guard_tinfo.keyword == RID_ELSE |
509 | ? guard_line_first_nws | |
510 | : guard_vis_column); | |
511 | if (guard_column == body_vis_column) | |
c3388e62 DM |
512 | return false; |
513 | ||
8ebca419 PP |
514 | /* We may have something like: |
515 | ||
516 | if (p) | |
517 | { | |
518 | foo (1); | |
519 | } else // GUARD | |
520 | foo (2); // BODY | |
521 | foo (3); // NEXT | |
522 | ||
523 | in which case the columns are not aligned but the code is not | |
729526f5 DM |
524 | misleadingly indented. If the column of the body isn't indented |
525 | more than the guard line then don't warn. */ | |
526 | if (body_vis_column <= guard_line_first_nws) | |
6ac48155 DM |
527 | return false; |
528 | ||
64b23c13 DM |
529 | /* Don't warn if there is an unindent between the two statements. */ |
530 | int vis_column = MIN (next_stmt_vis_column, body_vis_column); | |
531 | if (detect_intervening_unindent (body_exploc.file, body_exploc.line, | |
532 | next_stmt_exploc.line, | |
10fcc142 | 533 | vis_column, tab_width)) |
c3388e62 DM |
534 | return false; |
535 | ||
536 | /* Otherwise, they are visually aligned: issue a warning. */ | |
537 | return true; | |
538 | } | |
8ebca419 PP |
539 | |
540 | /* Also issue a warning for code having the form: | |
541 | ||
542 | if (flag); | |
543 | foo (); | |
544 | ||
545 | while (flag); | |
546 | { | |
547 | ... | |
548 | } | |
549 | ||
550 | for (...); | |
551 | { | |
552 | ... | |
553 | } | |
554 | ||
555 | if (flag) | |
556 | ; | |
557 | else if (flag); | |
558 | foo (); | |
559 | ||
560 | where the semicolon at the end of each guard is most likely spurious. | |
561 | ||
562 | But do not warn on: | |
563 | ||
564 | for (..); | |
565 | foo (); | |
566 | ||
567 | where the next statement is aligned with the guard. | |
568 | */ | |
569 | if (body_type == CPP_SEMICOLON) | |
570 | { | |
571 | if (body_exploc.line == guard_exploc.line) | |
572 | { | |
8ebca419 PP |
573 | if (next_stmt_vis_column > guard_line_first_nws |
574 | || (next_tok_type == CPP_OPEN_BRACE | |
6b95d7cc | 575 | && next_stmt_vis_column == guard_line_first_nws)) |
8ebca419 PP |
576 | return true; |
577 | } | |
578 | } | |
c3388e62 DM |
579 | } |
580 | ||
581 | return false; | |
582 | } | |
583 | ||
992118a1 PP |
584 | /* Return the string identifier corresponding to the given guard token. */ |
585 | ||
3e2becc4 MP |
586 | const char * |
587 | guard_tinfo_to_string (enum rid keyword) | |
992118a1 | 588 | { |
3e2becc4 | 589 | switch (keyword) |
992118a1 PP |
590 | { |
591 | case RID_FOR: | |
592 | return "for"; | |
593 | case RID_ELSE: | |
594 | return "else"; | |
595 | case RID_IF: | |
596 | return "if"; | |
597 | case RID_WHILE: | |
598 | return "while"; | |
599 | case RID_DO: | |
600 | return "do"; | |
3e2becc4 MP |
601 | case RID_SWITCH: |
602 | return "switch"; | |
992118a1 PP |
603 | default: |
604 | gcc_unreachable (); | |
605 | } | |
606 | } | |
607 | ||
c3388e62 DM |
608 | /* Called by the C/C++ frontends when we have a guarding statement at |
609 | GUARD_LOC containing a statement at BODY_LOC, where the block wasn't | |
610 | written using braces, like this: | |
611 | ||
612 | if (flag) | |
613 | foo (); | |
614 | ||
615 | along with the location of the next token, at NEXT_STMT_LOC, | |
616 | so that we can detect followup statements that are within | |
617 | the same "visual block" as the guarded statement, but which | |
618 | aren't logically grouped within the guarding statement, such | |
619 | as: | |
620 | ||
621 | GUARD_LOC | |
622 | | | |
623 | V | |
624 | if (flag) | |
625 | foo (); <- BODY_LOC | |
626 | bar (); <- NEXT_STMT_LOC | |
627 | ||
628 | In the above, "bar ();" isn't guarded by the "if", but | |
629 | is indented to misleadingly suggest that it is in the same | |
630 | block as "foo ();". | |
631 | ||
632 | GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */ | |
633 | ||
634 | void | |
992118a1 PP |
635 | warn_for_misleading_indentation (const token_indent_info &guard_tinfo, |
636 | const token_indent_info &body_tinfo, | |
637 | const token_indent_info &next_tinfo) | |
c3388e62 | 638 | { |
773ce42e DM |
639 | /* Early reject for the case where -Wmisleading-indentation is disabled, |
640 | to avoid doing work only to have the warning suppressed inside the | |
641 | diagnostic machinery. */ | |
642 | if (!warn_misleading_indentation) | |
643 | return; | |
644 | ||
992118a1 PP |
645 | if (should_warn_for_misleading_indentation (guard_tinfo, |
646 | body_tinfo, | |
647 | next_tinfo)) | |
648 | { | |
097f82ec | 649 | auto_diagnostic_group d; |
5c240f4d DM |
650 | if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation, |
651 | "this %qs clause does not guard...", | |
3e2becc4 | 652 | guard_tinfo_to_string (guard_tinfo.keyword))) |
5c240f4d | 653 | inform (next_tinfo.location, |
a02fa805 DM |
654 | "...this statement, but the latter is misleadingly indented" |
655 | " as if it were guarded by the %qs", | |
3e2becc4 | 656 | guard_tinfo_to_string (guard_tinfo.keyword)); |
992118a1 | 657 | } |
c3388e62 | 658 | } |
10fcc142 DM |
659 | |
660 | #if CHECKING_P | |
661 | ||
662 | namespace selftest { | |
663 | ||
664 | /* Verify that next_tab_stop works as expected. */ | |
665 | ||
666 | static void | |
667 | test_next_tab_stop () | |
668 | { | |
669 | const unsigned int tab_width = 8; | |
670 | ||
671 | ASSERT_EQ (next_tab_stop (0, tab_width), 8); | |
672 | ASSERT_EQ (next_tab_stop (1, tab_width), 8); | |
673 | ASSERT_EQ (next_tab_stop (7, tab_width), 8); | |
674 | ||
675 | ASSERT_EQ (next_tab_stop (8, tab_width), 16); | |
676 | ASSERT_EQ (next_tab_stop (9, tab_width), 16); | |
677 | ASSERT_EQ (next_tab_stop (15, tab_width), 16); | |
678 | ||
679 | ASSERT_EQ (next_tab_stop (16, tab_width), 24); | |
680 | ASSERT_EQ (next_tab_stop (17, tab_width), 24); | |
681 | ASSERT_EQ (next_tab_stop (23, tab_width), 24); | |
682 | } | |
683 | ||
684 | /* Verify that the given call to get_visual_column succeeds, with | |
685 | the given results. */ | |
686 | ||
687 | static void | |
688 | assert_get_visual_column_succeeds (const location &loc, | |
689 | const char *file, int line, int column, | |
690 | const unsigned int tab_width, | |
691 | unsigned int expected_visual_column, | |
692 | unsigned int expected_first_nws) | |
693 | { | |
694 | expanded_location exploc; | |
695 | exploc.file = file; | |
696 | exploc.line = line; | |
697 | exploc.column = column; | |
698 | exploc.data = NULL; | |
699 | exploc.sysp = false; | |
700 | unsigned int actual_visual_column; | |
701 | unsigned int actual_first_nws; | |
4394b1ce | 702 | bool result = get_visual_column (exploc, |
10fcc142 DM |
703 | &actual_visual_column, |
704 | &actual_first_nws, tab_width); | |
705 | ASSERT_TRUE_AT (loc, result); | |
706 | ASSERT_EQ_AT (loc, actual_visual_column, expected_visual_column); | |
707 | ASSERT_EQ_AT (loc, actual_first_nws, expected_first_nws); | |
708 | } | |
709 | ||
710 | /* Verify that the given call to get_visual_column succeeds, with | |
711 | the given results. */ | |
712 | ||
713 | #define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \ | |
714 | TAB_WIDTH, \ | |
715 | EXPECTED_VISUAL_COLUMN, \ | |
716 | EXPECTED_FIRST_NWS) \ | |
717 | SELFTEST_BEGIN_STMT \ | |
718 | assert_get_visual_column_succeeds (SELFTEST_LOCATION, \ | |
719 | FILENAME, LINE, COLUMN, \ | |
720 | TAB_WIDTH, \ | |
721 | EXPECTED_VISUAL_COLUMN, \ | |
722 | EXPECTED_FIRST_NWS); \ | |
723 | SELFTEST_END_STMT | |
724 | ||
725 | /* Verify that the given call to get_visual_column fails gracefully. */ | |
726 | ||
727 | static void | |
728 | assert_get_visual_column_fails (const location &loc, | |
729 | const char *file, int line, int column, | |
730 | const unsigned int tab_width) | |
731 | { | |
732 | expanded_location exploc; | |
733 | exploc.file = file; | |
734 | exploc.line = line; | |
735 | exploc.column = column; | |
736 | exploc.data = NULL; | |
737 | exploc.sysp = false; | |
738 | unsigned int actual_visual_column; | |
739 | unsigned int actual_first_nws; | |
4394b1ce | 740 | bool result = get_visual_column (exploc, |
10fcc142 DM |
741 | &actual_visual_column, |
742 | &actual_first_nws, tab_width); | |
743 | ASSERT_FALSE_AT (loc, result); | |
744 | } | |
745 | ||
746 | /* Verify that the given call to get_visual_column fails gracefully. */ | |
747 | ||
748 | #define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \ | |
749 | TAB_WIDTH) \ | |
750 | SELFTEST_BEGIN_STMT \ | |
751 | assert_get_visual_column_fails (SELFTEST_LOCATION, \ | |
752 | FILENAME, LINE, COLUMN, \ | |
753 | TAB_WIDTH); \ | |
754 | SELFTEST_END_STMT | |
755 | ||
756 | /* Verify that get_visual_column works as expected. */ | |
757 | ||
758 | static void | |
759 | test_get_visual_column () | |
760 | { | |
761 | /* Create a tempfile with a mixture of tabs and spaces. | |
762 | ||
763 | Both lines have either a space or a tab, then " line N", | |
764 | for 8 characters in total. | |
765 | ||
766 | 1-based "columns" (w.r.t. to line 1): | |
767 | .....................0000000001111. | |
768 | .....................1234567890123. */ | |
769 | const char *content = (" line 1\n" | |
770 | "\t line 2\n"); | |
771 | line_table_test ltt; | |
772 | temp_source_file tmp (SELFTEST_LOCATION, ".txt", content); | |
773 | ||
774 | const unsigned int tab_width = 8; | |
775 | const char *file = tmp.get_filename (); | |
776 | ||
777 | /* Line 1 (space-based indentation). */ | |
778 | { | |
779 | const int line = 1; | |
780 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0); | |
781 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1); | |
782 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2); | |
783 | /* first_nws should have stopped increasing. */ | |
784 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2); | |
785 | /* Verify the end-of-line boundary. */ | |
786 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2); | |
787 | ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width); | |
788 | } | |
789 | ||
790 | /* Line 2 (tab-based indentation). */ | |
791 | { | |
792 | const int line = 2; | |
793 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0); | |
794 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8); | |
795 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9); | |
796 | /* first_nws should have stopped increasing. */ | |
797 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9); | |
798 | /* Verify the end-of-line boundary. */ | |
799 | ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9); | |
800 | ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width); | |
801 | } | |
802 | } | |
803 | ||
804 | /* Run all of the selftests within this file. */ | |
805 | ||
806 | void | |
d5148d4f | 807 | c_indentation_cc_tests () |
10fcc142 DM |
808 | { |
809 | test_next_tab_stop (); | |
810 | test_get_visual_column (); | |
811 | } | |
812 | ||
813 | } // namespace selftest | |
814 | ||
815 | #endif /* CHECKING_P */ |