1 /* Implementation of -Wmisleading-indentation
2 Copyright (C) 2015 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"
27 #include "stringpool.h"
28 #include "stor-layout.h"
31 extern cpp_options
*cpp_opts
;
33 /* Convert libcpp's notion of a column (a 1-based char count) to
34 the "visual column" (0-based column, respecting tabs), by reading the
36 Returns true if a conversion was possible, writing the result to OUT,
37 otherwise returns false. */
40 get_visual_column (expanded_location exploc
, unsigned int *out
)
43 const char *line
= location_get_source_line (exploc
, &line_len
);
46 unsigned int vis_column
= 0;
47 for (int i
= 1; i
< exploc
.column
; i
++)
49 unsigned char ch
= line
[i
- 1];
52 /* Round up to nearest tab stop. */
53 const unsigned int tab_width
= cpp_opts
->tabstop
;
54 vis_column
= ((vis_column
+ tab_width
) / tab_width
) * tab_width
;
64 /* Is the token at LOC the first non-whitespace on its line?
65 Helper function for should_warn_for_misleading_indentation. */
68 is_first_nonwhitespace_on_line (expanded_location exploc
)
71 const char *line
= location_get_source_line (exploc
, &line_len
);
73 /* If we can't determine it, return false so that we don't issue a
74 warning. This is sometimes the case for input files
75 containing #line directives, and these are often for autogenerated
76 sources (e.g. from .md files), where it's not clear that it's
77 meaningful to look at indentation. */
81 for (int i
= 1; i
< exploc
.column
; i
++)
83 unsigned char ch
= line
[i
- 1];
90 /* Does the given source line appear to contain a #if directive?
91 (or #ifdef/#ifndef). Ignore the possibility of it being inside a
92 comment, for simplicity.
93 Helper function for detect_preprocessor_logic. */
96 line_contains_hash_if (const char *file
, int line_num
)
98 expanded_location exploc
;
100 exploc
.line
= line_num
;
104 const char *line
= location_get_source_line (exploc
, &line_len
);
110 /* Skip leading whitespace. */
111 for (idx
= 0; idx
< line_len
; idx
++)
112 if (!ISSPACE (line
[idx
]))
117 /* Require a '#' character. */
118 if (line
[idx
] != '#')
122 /* Skip whitespace. */
123 while (idx
< line_len
)
125 if (!ISSPACE (line
[idx
]))
130 /* Match #if/#ifdef/#ifndef. */
131 if (idx
+ 2 <= line_len
)
132 if (line
[idx
] == 'i')
133 if (line
[idx
+ 1] == 'f')
140 /* Determine if there is preprocessor logic between
141 BODY_EXPLOC and NEXT_STMT_EXPLOC, to ensure that we don't
142 issue a warning for cases like this:
147 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
153 despite "bar ();" being visually aligned below "foo ();" and
154 being (as far as the parser sees) the next token.
156 Return true if such logic is detected. */
159 detect_preprocessor_logic (expanded_location body_exploc
,
160 expanded_location next_stmt_exploc
)
162 gcc_assert (next_stmt_exploc
.file
== body_exploc
.file
);
163 gcc_assert (next_stmt_exploc
.line
> body_exploc
.line
);
165 if (next_stmt_exploc
.line
- body_exploc
.line
< 4)
168 /* Is there a #if/#ifdef/#ifndef directive somewhere in the lines
169 between the given locations?
171 This is something of a layering violation, but by necessity,
172 given the nature of what we're testing for. For example,
173 in theory we could be fooled by a #if within a comment, but
174 it's unlikely to matter. */
175 for (int line
= body_exploc
.line
+ 1; line
< next_stmt_exploc
.line
; line
++)
176 if (line_contains_hash_if (body_exploc
.file
, line
))
184 /* Helper function for warn_for_misleading_indentation; see
185 description of that function below. */
188 should_warn_for_misleading_indentation (location_t guard_loc
,
190 location_t next_stmt_loc
,
191 enum cpp_ttype next_tok_type
)
193 /* Don't attempt to compare the indentation of BODY_LOC and NEXT_STMT_LOC
194 if either are within macros. */
195 if (linemap_location_from_macro_expansion_p (line_table
, body_loc
)
196 || linemap_location_from_macro_expansion_p (line_table
, next_stmt_loc
))
199 /* Don't attempt to compare indentation if #line or # 44 "file"-style
200 directives are present, suggesting generated code.
202 All bets are off if these are present: the file that the #line
203 directive could have an entirely different coding layout to C/C++
206 To determine if a #line is present, in theory we could look for a
207 map with reason == LC_RENAME_VERBATIM. However, if there has
208 subsequently been a long line requiring a column number larger than
209 that representable by the original LC_RENAME_VERBATIM map, then
210 we'll have a map with reason LC_RENAME.
211 Rather than attempting to search all of the maps for a
212 LC_RENAME_VERBATIM, instead we have libcpp set a flag whenever one
213 is seen, and we check for the flag here.
215 if (line_table
->seen_line_directive
)
218 if (next_tok_type
== CPP_CLOSE_BRACE
)
221 /* Don't warn here about spurious semicolons. */
222 if (next_tok_type
== CPP_SEMICOLON
)
225 expanded_location body_exploc
= expand_location (body_loc
);
226 expanded_location next_stmt_exploc
= expand_location (next_stmt_loc
);
228 /* They must be in the same file. */
229 if (next_stmt_exploc
.file
!= body_exploc
.file
)
232 /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
233 the location of the guard.
235 Cases where we want to issue a warning:
241 if (flag) foo (); bar ();
244 Cases where we don't want to issue a warning:
246 various_code (); if (flag) foo (); bar (); more_code ();
247 ^ DON'T WARN HERE. */
248 if (next_stmt_exploc
.line
== body_exploc
.line
)
250 expanded_location guard_exploc
= expand_location (guard_loc
);
251 if (guard_exploc
.file
!= body_exploc
.file
)
253 if (guard_exploc
.line
< body_exploc
.line
)
254 /* The guard is on a line before a line that contains both
255 the body and the next stmt. */
257 else if (guard_exploc
.line
== body_exploc
.line
)
259 /* They're all on the same line. */
260 gcc_assert (guard_exploc
.file
== next_stmt_exploc
.file
);
261 gcc_assert (guard_exploc
.line
== next_stmt_exploc
.line
);
262 /* Heuristic: only warn if the guard is the first thing
264 if (is_first_nonwhitespace_on_line (guard_exploc
))
269 /* If NEXT_STMT_LOC is on a line after BODY_LOC, consider
270 their relative locations, and of the guard.
272 Cases where we want to issue a warning:
278 Cases where we don't want to issue a warning:
282 ^ DON'T WARN HERE (autogenerated code?)
286 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
301 if (next_stmt_exploc
.line
> body_exploc
.line
)
303 /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same
304 "visual column"... */
305 unsigned int next_stmt_vis_column
;
306 unsigned int body_vis_column
;
307 /* If we can't determine it, don't issue a warning. This is sometimes
308 the case for input files containing #line directives, and these
309 are often for autogenerated sources (e.g. from .md files), where
310 it's not clear that it's meaningful to look at indentation. */
311 if (!get_visual_column (next_stmt_exploc
, &next_stmt_vis_column
))
313 if (!get_visual_column (body_exploc
, &body_vis_column
))
315 if (next_stmt_vis_column
== body_vis_column
)
317 /* Don't warn if they aren't aligned on the same column
318 as the guard itself (suggesting autogenerated code that
319 doesn't bother indenting at all). */
320 expanded_location guard_exploc
= expand_location (guard_loc
);
321 unsigned int guard_vis_column
;
322 if (!get_visual_column (guard_exploc
, &guard_vis_column
))
324 if (guard_vis_column
== body_vis_column
)
327 /* PR 66220: Don't warn if the guarding statement is more
328 indented than the next/body stmts. */
329 if (guard_vis_column
> body_vis_column
)
332 /* Don't warn if there is multiline preprocessor logic between
333 the two statements. */
334 if (detect_preprocessor_logic (body_exploc
, next_stmt_exploc
))
337 /* Otherwise, they are visually aligned: issue a warning. */
345 /* Called by the C/C++ frontends when we have a guarding statement at
346 GUARD_LOC containing a statement at BODY_LOC, where the block wasn't
347 written using braces, like this:
352 along with the location of the next token, at NEXT_STMT_LOC,
353 so that we can detect followup statements that are within
354 the same "visual block" as the guarded statement, but which
355 aren't logically grouped within the guarding statement, such
363 bar (); <- NEXT_STMT_LOC
365 In the above, "bar ();" isn't guarded by the "if", but
366 is indented to misleadingly suggest that it is in the same
369 GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */
372 warn_for_misleading_indentation (location_t guard_loc
,
374 location_t next_stmt_loc
,
375 enum cpp_ttype next_tok_type
,
376 const char *guard_kind
)
378 /* Early reject for the case where -Wmisleading-indentation is disabled,
379 to avoid doing work only to have the warning suppressed inside the
380 diagnostic machinery. */
381 if (!warn_misleading_indentation
)
384 if (should_warn_for_misleading_indentation (guard_loc
,
388 if (warning_at (next_stmt_loc
, OPT_Wmisleading_indentation
,
389 "statement is indented as if it were guarded by..."))
391 "...this %qs clause, but it is not", guard_kind
);