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