+2015-08-02 Patrick Palka <ppalka@gcc.gnu.org>
+
+ * c-indentation.h (struct token_indent_info): Define.
+ (get_token_indent_info): Define.
+ (warn_for_misleading_information): Declare.
+ * c-common.h (warn_for_misleading_information): Remove.
+ * c-identation.c (warn_for_misleading_indentation):
+ Change declaration to take three token_indent_infos. Adjust
+ accordingly.
+ * c-identation.c (should_warn_for_misleading_indentation):
+ Likewise. Bail out early if the body is a compound statement.
+ (guard_tinfo_to_string): Define.
+
2015-07-30 Jason Merrill <jason@redhat.com>
* c-pretty-print.c (unary_expression) [INDIRECT_REF]: Don't print
extern tree cilk_for_number_of_iterations (tree);
extern bool check_no_cilk (tree, const char *, const char *,
location_t loc = UNKNOWN_LOCATION);
-/* In c-indentation.c. */
-extern void
-warn_for_misleading_indentation (location_t guard_loc,
- location_t body_loc,
- location_t next_stmt_loc,
- enum cpp_ttype next_tok_type,
- const char *guard_kind);
#endif /* ! GCC_C_COMMON_H */
#include "stringpool.h"
#include "stor-layout.h"
#include "c-common.h"
+#include "c-indentation.h"
extern cpp_options *cpp_opts;
description of that function below. */
static bool
-should_warn_for_misleading_indentation (location_t guard_loc,
- location_t body_loc,
- location_t next_stmt_loc,
- enum cpp_ttype next_tok_type)
+should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo)
{
+ location_t guard_loc = guard_tinfo.location;
+ location_t body_loc = body_tinfo.location;
+ location_t next_stmt_loc = next_tinfo.location;
+
+ enum cpp_ttype next_tok_type = next_tinfo.type;
+
/* Don't attempt to compare the indentation of BODY_LOC and NEXT_STMT_LOC
if either are within macros. */
if (linemap_location_from_macro_expansion_p (line_table, body_loc)
if (line_table->seen_line_directive)
return false;
- if (next_tok_type == CPP_CLOSE_BRACE)
+ /* If the token following the body is a close brace or an "else"
+ then while indentation may be sloppy, there is not much ambiguity
+ about control flow, e.g.
+
+ if (foo) <- GUARD
+ bar (); <- BODY
+ else baz (); <- NEXT
+
+ {
+ while (foo) <- GUARD
+ bar (); <- BODY
+ } <- NEXT
+ baz ();
+ */
+ if (next_tok_type == CPP_CLOSE_BRACE
+ || next_tinfo.keyword == RID_ELSE)
return false;
/* Don't warn here about spurious semicolons. */
return false;
}
+/* Return the string identifier corresponding to the given guard token. */
+
+static const char *
+guard_tinfo_to_string (const token_indent_info &guard_tinfo)
+{
+ switch (guard_tinfo.keyword)
+ {
+ case RID_FOR:
+ return "for";
+ case RID_ELSE:
+ return "else";
+ case RID_IF:
+ return "if";
+ case RID_WHILE:
+ return "while";
+ case RID_DO:
+ return "do";
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Called by the C/C++ frontends when we have a guarding statement at
GUARD_LOC containing a statement at BODY_LOC, where the block wasn't
written using braces, like this:
GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */
void
-warn_for_misleading_indentation (location_t guard_loc,
- location_t body_loc,
- location_t next_stmt_loc,
- enum cpp_ttype next_tok_type,
- const char *guard_kind)
+warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo)
{
/* Early reject for the case where -Wmisleading-indentation is disabled,
to avoid doing work only to have the warning suppressed inside the
if (!warn_misleading_indentation)
return;
- if (should_warn_for_misleading_indentation (guard_loc,
- body_loc,
- next_stmt_loc,
- next_tok_type))
- if (warning_at (next_stmt_loc, OPT_Wmisleading_indentation,
- "statement is indented as if it were guarded by..."))
- inform (guard_loc,
- "...this %qs clause, but it is not", guard_kind);
+ if (should_warn_for_misleading_indentation (guard_tinfo,
+ body_tinfo,
+ next_tinfo))
+ {
+ if (warning_at (next_tinfo.location, OPT_Wmisleading_indentation,
+ "statement is indented as if it were guarded by..."))
+ inform (guard_tinfo.location,
+ "...this %qs clause, but it is not",
+ guard_tinfo_to_string (guard_tinfo));
+ }
}
--- /dev/null
+/* Definitions for c-indentation.c.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_C_INDENTATION_H
+#define GCC_C_INDENTATION_H
+
+/* Token information used by the -Wmisleading-indentation implementation. */
+
+struct token_indent_info
+{
+ location_t location;
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ ENUM_BITFIELD (rid) keyword : 8;
+};
+
+/* Extract token information from TOKEN, which ought to either be a
+ cp_token * or a c_token *. */
+
+template <typename T>
+inline token_indent_info
+get_token_indent_info (const T *token)
+{
+ token_indent_info info;
+ info.location = token->location;
+ info.type = token->type;
+ info.keyword = token->keyword;
+
+ return info;
+}
+
+extern void
+warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo);
+
+#endif /* ! GCC_C_INDENTATION_H */
+2015-08-02 Patrick Palka <ppalka@gcc.gnu.org>
+
+ * c-parser.c (c_parser_if_body): Take token_indent_info
+ argument. Call warn_for_misleading_indentation even when the
+ body is a semicolon. Extract token_indent_infos corresponding
+ to the guard, body and next tokens. Adjust call to
+ warn_for_misleading_indentation accordingly.
+ (c_parser_else_body): Likewise.
+ (c_parser_if_statement): Likewise.
+ (c_parser_while_statement): Likewise.
+ (c_parser_for_statement): Likewise.
+
2015-07-28 Luis Felipe Strano Moraes <luis.strano@gmail.com>
Manuel López-Ibáñez <manu@gcc.gnu.org>
#include "omp-low.h"
#include "builtins.h"
#include "gomp-constants.h"
+#include "c-family/c-indentation.h"
\f
/* Initialization routine for this file. */
parser->in_if_block. */
static tree
-c_parser_if_body (c_parser *parser, bool *if_p, location_t if_loc)
+c_parser_if_body (c_parser *parser, bool *if_p,
+ const token_indent_info &if_tinfo)
{
tree block = c_begin_compound_stmt (flag_isoc99);
location_t body_loc = c_parser_peek_token (parser)->location;
+ token_indent_info body_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+
c_parser_all_labels (parser);
*if_p = c_parser_next_token_is_keyword (parser, RID_IF);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
add_stmt (c_parser_compound_statement (parser));
else
- {
- c_parser_statement_after_labels (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
- warn_for_misleading_indentation (if_loc, body_loc,
- c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->type,
- "if");
- }
+ c_parser_statement_after_labels (parser);
+
+ token_indent_info next_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+ warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
specially for the sake of -Wempty-body warnings. */
static tree
-c_parser_else_body (c_parser *parser, location_t else_loc)
+c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo)
{
location_t body_loc = c_parser_peek_token (parser)->location;
tree block = c_begin_compound_stmt (flag_isoc99);
+ token_indent_info body_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+
c_parser_all_labels (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
c_parser_consume_token (parser);
}
else
- {
- c_parser_statement_after_labels (parser);
- warn_for_misleading_indentation (else_loc, body_loc,
- c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->type,
- "else");
- }
+ c_parser_statement_after_labels (parser);
+
+ token_indent_info next_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+ warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
+
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
tree if_stmt;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
- location_t if_loc = c_parser_peek_token (parser)->location;
+ token_indent_info if_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
}
in_if_block = parser->in_if_block;
parser->in_if_block = true;
- first_body = c_parser_if_body (parser, &first_if, if_loc);
+ first_body = c_parser_if_body (parser, &first_if, if_tinfo);
parser->in_if_block = in_if_block;
if (c_parser_next_token_is_keyword (parser, RID_ELSE))
{
- location_t else_loc = c_parser_peek_token (parser)->location;
+ token_indent_info else_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
c_parser_consume_token (parser);
- second_body = c_parser_else_body (parser, else_loc);
+ second_body = c_parser_else_body (parser, else_tinfo);
}
else
second_body = NULL_TREE;
tree block, cond, body, save_break, save_cont;
location_t loc;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
- location_t while_loc = c_parser_peek_token (parser)->location;
+ token_indent_info while_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
c_parser_consume_token (parser);
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
- location_t body_loc = UNKNOWN_LOCATION;
- if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
- body_loc = c_parser_peek_token (parser)->location;
+ token_indent_info body_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+
body = c_parser_c99_block_statement (parser);
- warn_for_misleading_indentation (while_loc, body_loc,
- c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->type,
- "while");
+
+ token_indent_info next_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+ warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
location_t for_loc = c_parser_peek_token (parser)->location;
bool is_foreach_statement = false;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
+ token_indent_info for_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
c_parser_consume_token (parser);
/* Open a compound statement in Objective-C as well, just in case this is
as foreach expression. */
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
- location_t body_loc = UNKNOWN_LOCATION;
- if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
- body_loc = c_parser_peek_token (parser)->location;
+ token_indent_info body_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+
body = c_parser_c99_block_statement (parser);
- warn_for_misleading_indentation (for_loc, body_loc,
- c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->type,
- "for");
+
+ token_indent_info next_tinfo
+ = get_token_indent_info (c_parser_peek_token (parser));
+ warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
if (is_foreach_statement)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
+2015-08-02 Patrick Palka <ppalka@gcc.gnu.org>
+
+ * parser.c (cp_parser_selection_statement): Move handling of
+ semicolon body to ...
+ (cp_parser_implicitly_scoped_statement): .. here. Call
+ warn_for_misleading_indentation even when the body is a
+ semicolon. Extract token_indent_infos corresponding to the
+ guard, body and next tokens. Adjust call to
+ warn_for_misleading_indentation accordingly. Take
+ token_indent_info argument.
+ (cp_parser_already_scoped_statement): Likewise.
+ (cp_parser_selection_statement, cp_parser_iteration_statement):
+ Extract a token_indent_info corresponding to the guard token.
+
2015-08-01 Caroline Tice <cmtice@google.com>
PR 66521
#include "type-utils.h"
#include "omp-low.h"
#include "gomp-constants.h"
+#include "c-family/c-indentation.h"
\f
/* The lexer. */
(cp_parser *);
static tree cp_parser_implicitly_scoped_statement
- (cp_parser *, bool *, location_t, const char *);
+ (cp_parser *, bool *, const token_indent_info &);
static void cp_parser_already_scoped_statement
- (cp_parser *, location_t, const char *);
+ (cp_parser *, const token_indent_info &);
/* Declarations [gram.dcl.dcl] */
{
cp_token *token;
enum rid keyword;
+ token_indent_info guard_tinfo;
if (if_p != NULL)
*if_p = false;
/* Peek at the next token. */
token = cp_parser_require (parser, CPP_KEYWORD, RT_SELECT);
+ guard_tinfo = get_token_indent_info (token);
/* See what kind of keyword it is. */
keyword = token->keyword;
/* Parse the then-clause. */
in_statement = parser->in_statement;
parser->in_statement |= IN_IF_STMT;
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- {
- location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- add_stmt (build_empty_stmt (loc));
- cp_lexer_consume_token (parser->lexer);
- if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
- warning_at (loc, OPT_Wempty_body, "suggest braces around "
- "empty body in an %<if%> statement");
- nested_if = false;
- }
- else
- cp_parser_implicitly_scoped_statement (parser, &nested_if,
- token->location, "if");
+ cp_parser_implicitly_scoped_statement (parser, &nested_if,
+ guard_tinfo);
parser->in_statement = in_statement;
finish_then_clause (statement);
if (cp_lexer_next_token_is_keyword (parser->lexer,
RID_ELSE))
{
+ guard_tinfo
+ = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
/* Consume the `else' keyword. */
- location_t else_tok_loc
- = cp_lexer_consume_token (parser->lexer)->location;
+ cp_lexer_consume_token (parser->lexer);
begin_else_clause (statement);
/* Parse the else-clause. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- {
- location_t loc;
- loc = cp_lexer_peek_token (parser->lexer)->location;
- warning_at (loc,
- OPT_Wempty_body, "suggest braces around "
- "empty body in an %<else%> statement");
- add_stmt (build_empty_stmt (loc));
- cp_lexer_consume_token (parser->lexer);
- }
- else
- cp_parser_implicitly_scoped_statement (parser, NULL,
- else_tok_loc, "else");
+ cp_parser_implicitly_scoped_statement (parser, NULL,
+ guard_tinfo);
finish_else_clause (statement);
parser->in_switch_statement_p = true;
parser->in_statement |= IN_SWITCH_STMT;
cp_parser_implicitly_scoped_statement (parser, NULL,
- 0, "switch");
+ guard_tinfo);
parser->in_switch_statement_p = in_switch_statement_p;
parser->in_statement = in_statement;
cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
{
cp_token *token;
- location_t tok_loc;
enum rid keyword;
tree statement;
unsigned char in_statement;
+ token_indent_info guard_tinfo;
/* Peek at the next token. */
token = cp_parser_require (parser, CPP_KEYWORD, RT_INTERATION);
if (!token)
return error_mark_node;
- tok_loc = token->location;
+ guard_tinfo = get_token_indent_info (token);
/* Remember whether or not we are already within an iteration
statement. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
/* Parse the dependent statement. */
parser->in_statement = IN_ITERATION_STMT;
- cp_parser_already_scoped_statement (parser, tok_loc, "while");
+ cp_parser_already_scoped_statement (parser, guard_tinfo);
parser->in_statement = in_statement;
/* We're done with the while-statement. */
finish_while_stmt (statement);
statement = begin_do_stmt ();
/* Parse the body of the do-statement. */
parser->in_statement = IN_ITERATION_STMT;
- cp_parser_implicitly_scoped_statement (parser, NULL, 0, "do");
+ cp_parser_implicitly_scoped_statement (parser, NULL, guard_tinfo);
parser->in_statement = in_statement;
finish_do_body (statement);
/* Look for the `while' keyword. */
/* Parse the body of the for-statement. */
parser->in_statement = IN_ITERATION_STMT;
- cp_parser_already_scoped_statement (parser, tok_loc, "for");
+ cp_parser_already_scoped_statement (parser, guard_tinfo);
parser->in_statement = in_statement;
/* We're done with the for-statement. */
static tree
cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
- location_t guard_loc,
- const char *guard_kind)
+ const token_indent_info &guard_tinfo)
{
tree statement;
+ location_t body_loc = cp_lexer_peek_token (parser->lexer)->location;
+ token_indent_info body_tinfo
+ = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
if (if_p != NULL)
*if_p = false;
/* Mark if () ; with a special NOP_EXPR. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
{
- location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer);
- statement = add_stmt (build_empty_stmt (loc));
+ statement = add_stmt (build_empty_stmt (body_loc));
+
+ if (guard_tinfo.keyword == RID_IF
+ && !cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+ warning_at (body_loc, OPT_Wempty_body,
+ "suggest braces around empty body in an %<if%> statement");
+ else if (guard_tinfo.keyword == RID_ELSE)
+ warning_at (body_loc, OPT_Wempty_body,
+ "suggest braces around empty body in an %<else%> statement");
}
/* if a compound is opened, we simply parse the statement directly. */
else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
/* Create a compound-statement. */
statement = begin_compound_stmt (0);
/* Parse the dependent-statement. */
- location_t body_loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_statement (parser, NULL_TREE, false, if_p);
/* Finish the dummy compound-statement. */
finish_compound_stmt (statement);
- cp_token *next_tok = cp_lexer_peek_token (parser->lexer);
- if (next_tok->keyword != RID_ELSE)
- {
- location_t next_stmt_loc = next_tok->location;
- warn_for_misleading_indentation (guard_loc, body_loc,
- next_stmt_loc, next_tok->type,
- guard_kind);
- }
}
+ token_indent_info next_tinfo
+ = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
+ warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo);
+
/* Return the statement. */
return statement;
}
scope. */
static void
-cp_parser_already_scoped_statement (cp_parser* parser, location_t guard_loc,
- const char *guard_kind)
+cp_parser_already_scoped_statement (cp_parser* parser,
+ const token_indent_info &guard_tinfo)
{
/* If the token is a `{', then we must take special action. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
{
- location_t body_loc = cp_lexer_peek_token (parser->lexer)->location;
+ token_indent_info body_tinfo
+ = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
+
cp_parser_statement (parser, NULL_TREE, false, NULL);
- cp_token *next_tok = cp_lexer_peek_token (parser->lexer);
- location_t next_stmt_loc = next_tok->location;
- warn_for_misleading_indentation (guard_loc, body_loc,
- next_stmt_loc, next_tok->type,
- guard_kind);
+ token_indent_info next_tinfo
+ = get_token_indent_info (cp_lexer_peek_token (parser->lexer));
+ warn_for_misleading_indentation (guard_tinfo, body_tinfo, next_tinfo);
}
else
{