1 /* Implementation of -Wmisleading-indentation
2 Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
22 #include "coretypes.h"
25 #include "c-indentation.h"
26 // sdcpp #include "selftest.h"
27 #include "diagnostic.h"
29 /* Round up VIS_COLUMN to nearest tab stop. */
32 next_tab_stop (unsigned int vis_column
, unsigned int tab_width
)
34 vis_column
= ((vis_column
+ tab_width
) / tab_width
) * tab_width
;
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
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). */
48 get_visual_column (expanded_location exploc
,
50 unsigned int *first_nws
,
51 unsigned int tab_width
)
53 char_span line
= location_get_source_line (exploc
.file
, exploc
.line
);
56 if ((size_t)exploc
.column
> line
.length ())
58 unsigned int vis_column
= 0;
59 for (int i
= 1; i
< exploc
.column
; i
++)
61 unsigned char ch
= line
[i
- 1];
63 if (first_nws
!= NULL
&& !ISSPACE (ch
))
65 *first_nws
= vis_column
;
70 vis_column
= next_tab_stop (vis_column
, tab_width
);
75 if (first_nws
!= NULL
)
76 *first_nws
= vis_column
;
82 /* Attempt to determine the first non-whitespace character in line LINE_NUM
85 If this is possible, return true and write its "visual column" to
87 Otherwise, return false, leaving *FIRST_NWS untouched. */
90 get_first_nws_vis_column (const char *file
, int line_num
,
91 unsigned int *first_nws
,
92 unsigned int tab_width
)
94 gcc_assert (first_nws
);
96 char_span line
= location_get_source_line (file
, line_num
);
99 unsigned int vis_column
= 0;
100 for (size_t i
= 1; i
< line
.length (); i
++)
102 unsigned char ch
= line
[i
- 1];
106 *first_nws
= vis_column
;
111 vis_column
= next_tab_stop (vis_column
, tab_width
);
116 /* No non-whitespace characters found. */
120 /* Determine if there is an unindent/outdent between
121 BODY_EXPLOC and NEXT_STMT_EXPLOC, to ensure that we don't
122 issue a warning for cases like the following:
124 (1) Preprocessor logic
129 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
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.
139 (2) Empty macro with bad indentation
141 In the following, the
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
148 #define engine_ref_debug(X, Y, Z)
154 engine_ref_debug(e, 0, -1)
158 Return true if such an unindent/outdent is detected. */
161 detect_intervening_unindent (const char *file
,
164 unsigned int vis_column
,
165 unsigned int tab_width
)
168 gcc_assert (next_stmt_line
> body_line
);
170 for (int line
= body_line
+ 1; line
< next_stmt_line
; line
++)
172 unsigned int line_vis_column
;
173 if (get_first_nws_vis_column (file
, line
, &line_vis_column
, tab_width
))
174 if (line_vis_column
< vis_column
)
183 /* Helper function for warn_for_misleading_indentation; see
184 description of that function below. */
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
)
191 /* Don't attempt to compare indentation if #line or # 44 "file"-style
192 directives are present, suggesting generated code.
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++
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.
207 if (line_table
->seen_line_directive
)
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
)
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.
231 enum cpp_ttype next_tok_type
= next_tinfo
.type
;
232 if (next_tok_type
== CPP_CLOSE_BRACE
233 || next_tinfo
.keyword
== RID_ELSE
)
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
246 Things only get muddy when the body of the guard does not have
253 enum cpp_ttype body_type
= body_tinfo
.type
;
254 if (body_type
== CPP_OPEN_BRACE
)
257 /* Don't warn here about spurious semicolons. */
258 if (next_tok_type
== CPP_SEMICOLON
)
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
;
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
);
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
)
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
);
290 /* Punt on complicated nesting of macros. */
291 if (guard_body_common_map
!= body_next_common_map
)
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
,
303 expanded_location body_exploc
= expand_location (body_loc
);
304 expanded_location next_stmt_exploc
= expand_location (next_stmt_loc
);
305 expanded_location guard_exploc
= expand_location (guard_loc
);
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
)
312 static bool issued_note
= false;
315 /* Notify the user the first time this happens. */
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
)
323 "adding %<-flarge-source-files%> will allow for more"
324 " column-tracking support, at the expense of compilation"
330 /* Give up if the loci are not all distinct. */
331 if (guard_loc
== body_loc
|| body_loc
== next_stmt_loc
)
334 const unsigned int tab_width
= global_dc
->tabstop
;
336 /* They must be in the same file. */
337 if (next_stmt_exploc
.file
!= body_exploc
.file
)
340 /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
341 the location of the guard.
343 Cases where we want to issue a warning:
349 if (flag) foo (); bar ();
360 Cases where we don't want to issue a warning:
362 various_code (); if (flag) foo (); bar (); more_code ();
363 ^ DON'T WARN HERE. */
364 if (next_stmt_exploc
.line
== body_exploc
.line
)
366 if (guard_exploc
.file
!= body_exploc
.file
)
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. */
372 else if (guard_exploc
.line
== body_exploc
.line
)
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
);
377 unsigned int guard_vis_column
;
378 unsigned int guard_line_first_nws
;
379 if (!get_visual_column (guard_exploc
,
381 &guard_line_first_nws
, tab_width
))
383 /* Heuristic: only warn if the guard is the first thing
385 if (guard_vis_column
== guard_line_first_nws
)
390 /* If NEXT_STMT_LOC is on a line after BODY_LOC, consider
391 their relative locations, and of the guard.
393 Cases where we want to issue a warning:
399 Cases where we don't want to issue a warning:
403 ^ DON'T WARN HERE (autogenerated code?)
407 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
425 if (next_stmt_exploc
.line
> body_exploc
.line
)
427 /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same
428 "visual column"... */
429 unsigned int next_stmt_vis_column
;
430 unsigned int next_stmt_line_first_nws
;
431 unsigned int body_vis_column
;
432 unsigned int body_line_first_nws
;
433 unsigned int guard_vis_column
;
434 unsigned int guard_line_first_nws
;
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. */
439 if (!get_visual_column (next_stmt_exploc
,
440 &next_stmt_vis_column
,
441 &next_stmt_line_first_nws
, tab_width
))
443 if (!get_visual_column (body_exploc
,
445 &body_line_first_nws
, tab_width
))
447 if (!get_visual_column (guard_exploc
,
449 &guard_line_first_nws
, tab_width
))
452 /* If the line where the next stmt starts has non-whitespace
453 on it before the stmt, then don't warn:
460 if (next_stmt_line_first_nws
< next_stmt_vis_column
)
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. */
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
477 && next_stmt_vis_column
> guard_line_first_nws
))
479 /* Don't warn if they are aligned on the same column
480 as the guard itself (suggesting autogenerated code that doesn't
481 bother indenting at all).
482 For "else" clauses, we consider the column of the first
483 non-whitespace character on the guard line instead of the column
484 of the actual guard token itself because it is more sensible.
501 If we just used the column of the "else" token, we would warn on
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
508 unsigned int guard_column
= (guard_tinfo
.keyword
== RID_ELSE
509 ? guard_line_first_nws
511 if (guard_column
== body_vis_column
)
514 /* We may have something like:
523 in which case the columns are not aligned but the code is not
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
)
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
,
533 vis_column
, tab_width
))
536 /* Otherwise, they are visually aligned: issue a warning. */
540 /* Also issue a warning for code having the form:
560 where the semicolon at the end of each guard is most likely spurious.
567 where the next statement is aligned with the guard.
569 if (body_type
== CPP_SEMICOLON
)
571 if (body_exploc
.line
== guard_exploc
.line
)
573 if (next_stmt_vis_column
> guard_line_first_nws
574 || (next_tok_type
== CPP_OPEN_BRACE
575 && next_stmt_vis_column
== guard_line_first_nws
))
584 /* Return the string identifier corresponding to the given guard token. */
587 guard_tinfo_to_string (enum rid keyword
)
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:
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
626 bar (); <- NEXT_STMT_LOC
628 In the above, "bar ();" isn't guarded by the "if", but
629 is indented to misleadingly suggest that it is in the same
632 GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */
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
)
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
)
645 if (should_warn_for_misleading_indentation (guard_tinfo
,
649 auto_diagnostic_group d
;
650 if (warning_at (guard_tinfo
.location
, OPT_Wmisleading_indentation
,
651 "this %qs clause does not guard...",
652 guard_tinfo_to_string (guard_tinfo
.keyword
)))
653 inform (next_tinfo
.location
,
654 "...this statement, but the latter is misleadingly indented"
655 " as if it were guarded by the %qs",
656 guard_tinfo_to_string (guard_tinfo
.keyword
));
664 /* Verify that next_tab_stop works as expected. */
667 test_next_tab_stop ()
669 const unsigned int tab_width
= 8;
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);
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);
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);
684 /* Verify that the given call to get_visual_column succeeds, with
685 the given results. */
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
)
694 expanded_location exploc
;
697 exploc
.column
= column
;
700 unsigned int actual_visual_column
;
701 unsigned int actual_first_nws
;
702 bool result
= get_visual_column (exploc
,
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
);
710 /* Verify that the given call to get_visual_column succeeds, with
711 the given results. */
713 #define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \
715 EXPECTED_VISUAL_COLUMN, \
716 EXPECTED_FIRST_NWS) \
717 SELFTEST_BEGIN_STMT \
718 assert_get_visual_column_succeeds (SELFTEST_LOCATION, \
719 FILENAME, LINE, COLUMN, \
721 EXPECTED_VISUAL_COLUMN, \
722 EXPECTED_FIRST_NWS); \
725 /* Verify that the given call to get_visual_column fails gracefully. */
728 assert_get_visual_column_fails (const location
&loc
,
729 const char *file
, int line
, int column
,
730 const unsigned int tab_width
)
732 expanded_location exploc
;
735 exploc
.column
= column
;
738 unsigned int actual_visual_column
;
739 unsigned int actual_first_nws
;
740 bool result
= get_visual_column (exploc
,
741 &actual_visual_column
,
742 &actual_first_nws
, tab_width
);
743 ASSERT_FALSE_AT (loc
, result
);
746 /* Verify that the given call to get_visual_column fails gracefully. */
748 #define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \
750 SELFTEST_BEGIN_STMT \
751 assert_get_visual_column_fails (SELFTEST_LOCATION, \
752 FILENAME, LINE, COLUMN, \
756 /* Verify that get_visual_column works as expected. */
759 test_get_visual_column ()
761 /* Create a tempfile with a mixture of tabs and spaces.
763 Both lines have either a space or a tab, then " line N",
764 for 8 characters in total.
766 1-based "columns" (w.r.t. to line 1):
767 .....................0000000001111.
768 .....................1234567890123. */
769 const char *content
= (" line 1\n"
772 temp_source_file
tmp (SELFTEST_LOCATION
, ".txt", content
);
774 const unsigned int tab_width
= 8;
775 const char *file
= tmp
.get_filename ();
777 /* Line 1 (space-based indentation). */
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
);
790 /* Line 2 (tab-based indentation). */
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
);
804 /* Run all of the selftests within this file. */
807 c_indentation_cc_tests ()
809 test_next_tab_stop ();
810 test_get_visual_column ();
813 } // namespace selftest
815 #endif /* CHECKING_P */