gcc: Backport fixes for -W parentheses in C++
This fixes GCC 19564: http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00868.html http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01772.html http://gcc.gnu.org/ml/gcc-patches/2007-01/msg00545.html The patch and its fixes are used by Google in their enhanced gcc-4.2.1 port and predates the license switch in GCC so they are still under GPLv2. MFC after: 3 weeks
This commit is contained in:
parent
e2838b315a
commit
3b5bdcdf37
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=258081
@ -232,6 +232,17 @@
|
||||
|
||||
* config.gcc: Support core2 processor.
|
||||
|
||||
2006-12-13 Ian Lance Taylor <iant@google.com> (r119855)
|
||||
|
||||
PR c++/19564
|
||||
PR c++/19756
|
||||
* c-typeck.c (parser_build_binary_op): Move parentheses warnings
|
||||
to warn_about_parentheses in c-common.c.
|
||||
* c-common.c (warn_about_parentheses): New function.
|
||||
* c-common.h (warn_about_parentheses): Declare.
|
||||
* doc/invoke.texi (Warning Options): Update -Wparentheses
|
||||
description.
|
||||
|
||||
2006-12-02 H.J. Lu <hongjiu.lu@intel.com> (r119454 - partial)
|
||||
|
||||
PR target/30040
|
||||
|
@ -2585,9 +2585,13 @@ c_common_truthvalue_conversion (tree expr)
|
||||
break;
|
||||
|
||||
case MODIFY_EXPR:
|
||||
if (!TREE_NO_WARNING (expr))
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around assignment used as truth value");
|
||||
if (!TREE_NO_WARNING (expr)
|
||||
&& warn_parentheses)
|
||||
{
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around assignment used as truth value");
|
||||
TREE_NO_WARNING (expr) = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -6471,5 +6475,87 @@ warn_array_subscript_with_type_char (tree index)
|
||||
warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
|
||||
}
|
||||
|
||||
/* Implement -Wparentheses for the unexpected C precedence rules, to
|
||||
cover cases like x + y << z which readers are likely to
|
||||
misinterpret. We have seen an expression in which CODE is a binary
|
||||
operator used to combine expressions headed by CODE_LEFT and
|
||||
CODE_RIGHT. CODE_LEFT and CODE_RIGHT may be ERROR_MARK, which
|
||||
means that that side of the expression was not formed using a
|
||||
binary operator, or it was enclosed in parentheses. */
|
||||
|
||||
void
|
||||
warn_about_parentheses (enum tree_code code, enum tree_code code_left,
|
||||
enum tree_code code_right)
|
||||
{
|
||||
if (!warn_parentheses)
|
||||
return;
|
||||
|
||||
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
|
||||
{
|
||||
if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
|
||||
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around + or - inside shift");
|
||||
}
|
||||
|
||||
if (code == TRUTH_ORIF_EXPR)
|
||||
{
|
||||
if (code_left == TRUTH_ANDIF_EXPR
|
||||
|| code_right == TRUTH_ANDIF_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around && within ||");
|
||||
}
|
||||
|
||||
if (code == BIT_IOR_EXPR)
|
||||
{
|
||||
if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
|
||||
|| code_left == PLUS_EXPR || code_left == MINUS_EXPR
|
||||
|| code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
|
||||
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around arithmetic in operand of |");
|
||||
/* Check cases like x|y==z */
|
||||
if (TREE_CODE_CLASS (code_left) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code_right) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of |");
|
||||
}
|
||||
|
||||
if (code == BIT_XOR_EXPR)
|
||||
{
|
||||
if (code_left == BIT_AND_EXPR
|
||||
|| code_left == PLUS_EXPR || code_left == MINUS_EXPR
|
||||
|| code_right == BIT_AND_EXPR
|
||||
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around arithmetic in operand of ^");
|
||||
/* Check cases like x^y==z */
|
||||
if (TREE_CODE_CLASS (code_left) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code_right) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of ^");
|
||||
}
|
||||
|
||||
if (code == BIT_AND_EXPR)
|
||||
{
|
||||
if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
|
||||
|| code_right == PLUS_EXPR || code_right == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around + or - in operand of &");
|
||||
/* Check cases like x&y==z */
|
||||
if (TREE_CODE_CLASS (code_left) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code_right) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of &");
|
||||
}
|
||||
|
||||
/* Similarly, check for cases like 1<=i<=10 that are probably errors. */
|
||||
if (TREE_CODE_CLASS (code) == tcc_comparison
|
||||
&& (TREE_CODE_CLASS (code_left) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code_right) == tcc_comparison))
|
||||
warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
|
||||
"have their mathematical meaning");
|
||||
}
|
||||
|
||||
|
||||
#include "gt-c-common.h"
|
||||
|
@ -850,6 +850,9 @@ extern int complete_array_type (tree *, tree, bool);
|
||||
extern tree builtin_type_for_size (int, bool);
|
||||
|
||||
extern void warn_array_subscript_with_type_char (tree);
|
||||
extern void warn_about_parentheses (enum tree_code, enum tree_code,
|
||||
enum tree_code);
|
||||
|
||||
|
||||
/* In c-gimplify.c */
|
||||
extern void c_genericize (tree);
|
||||
|
@ -2631,73 +2631,7 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
|
||||
/* Check for cases such as x+y<<z which users are likely
|
||||
to misinterpret. */
|
||||
if (warn_parentheses)
|
||||
{
|
||||
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
|
||||
{
|
||||
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|
||||
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around + or - inside shift");
|
||||
}
|
||||
|
||||
if (code == TRUTH_ORIF_EXPR)
|
||||
{
|
||||
if (code1 == TRUTH_ANDIF_EXPR
|
||||
|| code2 == TRUTH_ANDIF_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around && within ||");
|
||||
}
|
||||
|
||||
if (code == BIT_IOR_EXPR)
|
||||
{
|
||||
if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR
|
||||
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|
||||
|| code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
|
||||
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around arithmetic in operand of |");
|
||||
/* Check cases like x|y==z */
|
||||
if (TREE_CODE_CLASS (code1) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code2) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of |");
|
||||
}
|
||||
|
||||
if (code == BIT_XOR_EXPR)
|
||||
{
|
||||
if (code1 == BIT_AND_EXPR
|
||||
|| code1 == PLUS_EXPR || code1 == MINUS_EXPR
|
||||
|| code2 == BIT_AND_EXPR
|
||||
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around arithmetic in operand of ^");
|
||||
/* Check cases like x^y==z */
|
||||
if (TREE_CODE_CLASS (code1) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code2) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of ^");
|
||||
}
|
||||
|
||||
if (code == BIT_AND_EXPR)
|
||||
{
|
||||
if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
|
||||
|| code2 == PLUS_EXPR || code2 == MINUS_EXPR)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around + or - in operand of &");
|
||||
/* Check cases like x&y==z */
|
||||
if (TREE_CODE_CLASS (code1) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code2) == tcc_comparison)
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around comparison in operand of &");
|
||||
}
|
||||
/* Similarly, check for cases like 1<=i<=10 that are probably errors. */
|
||||
if (TREE_CODE_CLASS (code) == tcc_comparison
|
||||
&& (TREE_CODE_CLASS (code1) == tcc_comparison
|
||||
|| TREE_CODE_CLASS (code2) == tcc_comparison))
|
||||
warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
|
||||
"have their mathematical meaning");
|
||||
|
||||
}
|
||||
warn_about_parentheses (code, code1, code2);
|
||||
|
||||
/* Warn about comparisons against string literals, with the exception
|
||||
of testing for equality or inequality of a string literal with NULL. */
|
||||
|
@ -4460,8 +4460,9 @@ extern tree build_x_indirect_ref (tree, const char *);
|
||||
extern tree build_indirect_ref (tree, const char *);
|
||||
extern tree build_array_ref (tree, tree);
|
||||
extern tree get_member_function_from_ptrfunc (tree *, tree);
|
||||
extern tree build_x_binary_op (enum tree_code, tree, tree,
|
||||
bool *);
|
||||
extern tree build_x_binary_op (enum tree_code, tree,
|
||||
enum tree_code, tree,
|
||||
enum tree_code, bool *);
|
||||
extern tree build_x_unary_op (enum tree_code, tree);
|
||||
extern tree unary_complex_lvalue (enum tree_code, tree);
|
||||
extern tree build_x_conditional_expr (tree, tree, tree);
|
||||
|
@ -1177,8 +1177,15 @@ typedef enum cp_parser_status_kind
|
||||
|
||||
typedef struct cp_parser_expression_stack_entry
|
||||
{
|
||||
/* Left hand side of the binary operation we are currently
|
||||
parsing. */
|
||||
tree lhs;
|
||||
/* Original tree code for left hand side, if it was a binary
|
||||
expression itself (used for -Wparentheses). */
|
||||
enum tree_code lhs_type;
|
||||
/* Tree code for the binary operation we are parsing. */
|
||||
enum tree_code tree_type;
|
||||
/* Precedence of the binary operation we are parsing. */
|
||||
int prec;
|
||||
} cp_parser_expression_stack_entry;
|
||||
|
||||
@ -1536,7 +1543,7 @@ static tree cp_parser_builtin_offsetof
|
||||
/* Statements [gram.stmt.stmt] */
|
||||
|
||||
static void cp_parser_statement
|
||||
(cp_parser *, tree, bool);
|
||||
(cp_parser *, tree, bool, bool *);
|
||||
static void cp_parser_label_for_labeled_statement
|
||||
(cp_parser *);
|
||||
static tree cp_parser_expression_statement
|
||||
@ -1546,7 +1553,7 @@ static tree cp_parser_compound_statement
|
||||
static void cp_parser_statement_seq_opt
|
||||
(cp_parser *, tree);
|
||||
static tree cp_parser_selection_statement
|
||||
(cp_parser *);
|
||||
(cp_parser *, bool *);
|
||||
static tree cp_parser_condition
|
||||
(cp_parser *);
|
||||
static tree cp_parser_iteration_statement
|
||||
@ -1559,7 +1566,7 @@ static void cp_parser_declaration_statement
|
||||
(cp_parser *);
|
||||
|
||||
static tree cp_parser_implicitly_scoped_statement
|
||||
(cp_parser *);
|
||||
(cp_parser *, bool *);
|
||||
static void cp_parser_already_scoped_statement
|
||||
(cp_parser *);
|
||||
|
||||
@ -5730,12 +5737,13 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
cp_parser_expression_stack_entry *sp = &stack[0];
|
||||
tree lhs, rhs;
|
||||
cp_token *token;
|
||||
enum tree_code tree_type;
|
||||
enum tree_code tree_type, lhs_type, rhs_type;
|
||||
enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
|
||||
bool overloaded_p;
|
||||
|
||||
/* Parse the first expression. */
|
||||
lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
|
||||
lhs_type = ERROR_MARK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -5768,6 +5776,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
/* Extract another operand. It may be the RHS of this expression
|
||||
or the LHS of a new, higher priority expression. */
|
||||
rhs = cp_parser_simple_cast_expression (parser);
|
||||
rhs_type = ERROR_MARK;
|
||||
|
||||
/* Get another operator token. Look up its precedence to avoid
|
||||
building a useless (immediately popped) stack entry for common
|
||||
@ -5783,8 +5792,10 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
sp->prec = prec;
|
||||
sp->tree_type = tree_type;
|
||||
sp->lhs = lhs;
|
||||
sp->lhs_type = lhs_type;
|
||||
sp++;
|
||||
lhs = rhs;
|
||||
lhs_type = rhs_type;
|
||||
prec = new_prec;
|
||||
new_prec = lookahead_prec;
|
||||
goto get_rhs;
|
||||
@ -5801,11 +5812,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
|
||||
prec = sp->prec;
|
||||
tree_type = sp->tree_type;
|
||||
rhs = lhs;
|
||||
rhs_type = lhs_type;
|
||||
lhs = sp->lhs;
|
||||
lhs_type = sp->lhs_type;
|
||||
}
|
||||
|
||||
overloaded_p = false;
|
||||
lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
|
||||
lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
|
||||
&overloaded_p);
|
||||
lhs_type = tree_type;
|
||||
|
||||
/* If the binary operator required the use of an overloaded operator,
|
||||
then this expression cannot be an integral constant-expression.
|
||||
@ -6222,17 +6237,23 @@ cp_parser_builtin_offsetof (cp_parser *parser)
|
||||
try-block
|
||||
|
||||
IN_COMPOUND is true when the statement is nested inside a
|
||||
cp_parser_compound_statement; this matters for certain pragmas. */
|
||||
cp_parser_compound_statement; this matters for certain pragmas.
|
||||
|
||||
If IF_P is not NULL, *IF_P is set to indicate whether the statement
|
||||
is a (possibly labeled) if statement which is not enclosed in braces
|
||||
and has an else clause. This is used to implement -Wparentheses. */
|
||||
|
||||
static void
|
||||
cp_parser_statement (cp_parser* parser, tree in_statement_expr,
|
||||
bool in_compound)
|
||||
bool in_compound, bool *if_p)
|
||||
{
|
||||
tree statement;
|
||||
cp_token *token;
|
||||
location_t statement_location;
|
||||
|
||||
restart:
|
||||
if (if_p != NULL)
|
||||
*if_p = false;
|
||||
/* There is no statement yet. */
|
||||
statement = NULL_TREE;
|
||||
/* Peek at the next token. */
|
||||
@ -6257,7 +6278,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
|
||||
|
||||
case RID_IF:
|
||||
case RID_SWITCH:
|
||||
statement = cp_parser_selection_statement (parser);
|
||||
statement = cp_parser_selection_statement (parser, if_p);
|
||||
break;
|
||||
|
||||
case RID_WHILE:
|
||||
@ -6522,7 +6543,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
|
||||
break;
|
||||
|
||||
/* Parse the statement. */
|
||||
cp_parser_statement (parser, in_statement_expr, true);
|
||||
cp_parser_statement (parser, in_statement_expr, true, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6533,14 +6554,22 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
|
||||
if ( condition ) statement else statement
|
||||
switch ( condition ) statement
|
||||
|
||||
Returns the new IF_STMT or SWITCH_STMT. */
|
||||
Returns the new IF_STMT or SWITCH_STMT.
|
||||
|
||||
If IF_P is not NULL, *IF_P is set to indicate whether the statement
|
||||
is a (possibly labeled) if statement which is not enclosed in
|
||||
braces and has an else clause. This is used to implement
|
||||
-Wparentheses. */
|
||||
|
||||
static tree
|
||||
cp_parser_selection_statement (cp_parser* parser)
|
||||
cp_parser_selection_statement (cp_parser* parser, bool *if_p)
|
||||
{
|
||||
cp_token *token;
|
||||
enum rid keyword;
|
||||
|
||||
if (if_p != NULL)
|
||||
*if_p = false;
|
||||
|
||||
/* Peek at the next token. */
|
||||
token = cp_parser_require (parser, CPP_KEYWORD, "selection-statement");
|
||||
|
||||
@ -6576,11 +6605,13 @@ cp_parser_selection_statement (cp_parser* parser)
|
||||
|
||||
if (keyword == RID_IF)
|
||||
{
|
||||
bool nested_if;
|
||||
|
||||
/* Add the condition. */
|
||||
finish_if_stmt_cond (condition, statement);
|
||||
|
||||
/* Parse the then-clause. */
|
||||
cp_parser_implicitly_scoped_statement (parser);
|
||||
cp_parser_implicitly_scoped_statement (parser, &nested_if);
|
||||
finish_then_clause (statement);
|
||||
|
||||
/* If the next token is `else', parse the else-clause. */
|
||||
@ -6591,8 +6622,28 @@ cp_parser_selection_statement (cp_parser* parser)
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
begin_else_clause (statement);
|
||||
/* Parse the else-clause. */
|
||||
cp_parser_implicitly_scoped_statement (parser);
|
||||
cp_parser_implicitly_scoped_statement (parser, NULL);
|
||||
finish_else_clause (statement);
|
||||
|
||||
/* If we are currently parsing a then-clause, then
|
||||
IF_P will not be NULL. We set it to true to
|
||||
indicate that this if statement has an else clause.
|
||||
This may trigger the Wparentheses warning below
|
||||
when we get back up to the parent if statement. */
|
||||
if (if_p != NULL)
|
||||
*if_p = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This if statement does not have an else clause. If
|
||||
NESTED_IF is true, then the then-clause is an if
|
||||
statement which does have an else clause. We warn
|
||||
about the potential ambiguity. */
|
||||
if (nested_if)
|
||||
warning (OPT_Wparentheses,
|
||||
("%Hsuggest explicit braces "
|
||||
"to avoid ambiguous %<else%>"),
|
||||
EXPR_LOCUS (statement));
|
||||
}
|
||||
|
||||
/* Now we're all done with the if-statement. */
|
||||
@ -6611,7 +6662,7 @@ cp_parser_selection_statement (cp_parser* parser)
|
||||
in_statement = parser->in_statement;
|
||||
parser->in_switch_statement_p = true;
|
||||
parser->in_statement |= IN_SWITCH_STMT;
|
||||
cp_parser_implicitly_scoped_statement (parser);
|
||||
cp_parser_implicitly_scoped_statement (parser, NULL);
|
||||
parser->in_switch_statement_p = in_switch_statement_p;
|
||||
parser->in_statement = in_statement;
|
||||
|
||||
@ -6789,7 +6840,7 @@ cp_parser_iteration_statement (cp_parser* parser)
|
||||
statement = begin_do_stmt ();
|
||||
/* Parse the body of the do-statement. */
|
||||
parser->in_statement = IN_ITERATION_STMT;
|
||||
cp_parser_implicitly_scoped_statement (parser);
|
||||
cp_parser_implicitly_scoped_statement (parser, NULL);
|
||||
parser->in_statement = in_statement;
|
||||
finish_do_body (statement);
|
||||
/* Look for the `while' keyword. */
|
||||
@ -7031,13 +7082,21 @@ cp_parser_declaration_statement (cp_parser* parser)
|
||||
but ensures that is in its own scope, even if it is not a
|
||||
compound-statement.
|
||||
|
||||
If IF_P is not NULL, *IF_P is set to indicate whether the statement
|
||||
is a (possibly labeled) if statement which is not enclosed in
|
||||
braces and has an else clause. This is used to implement
|
||||
-Wparentheses.
|
||||
|
||||
Returns the new statement. */
|
||||
|
||||
static tree
|
||||
cp_parser_implicitly_scoped_statement (cp_parser* parser)
|
||||
cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
|
||||
{
|
||||
tree statement;
|
||||
|
||||
if (if_p != NULL)
|
||||
*if_p = false;
|
||||
|
||||
/* Mark if () ; with a special NOP_EXPR. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
|
||||
{
|
||||
@ -7053,7 +7112,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
|
||||
/* Create a compound-statement. */
|
||||
statement = begin_compound_stmt (0);
|
||||
/* Parse the dependent-statement. */
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false, if_p);
|
||||
/* Finish the dummy compound-statement. */
|
||||
finish_compound_stmt (statement);
|
||||
}
|
||||
@ -7072,7 +7131,7 @@ cp_parser_already_scoped_statement (cp_parser* parser)
|
||||
{
|
||||
/* If the token is a `{', then we must take special action. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
else
|
||||
{
|
||||
/* Avoid calling cp_parser_compound_statement, so that we
|
||||
@ -18645,7 +18704,7 @@ cp_parser_omp_structured_block (cp_parser *parser)
|
||||
tree stmt = begin_omp_structured_block ();
|
||||
unsigned int save = cp_parser_begin_omp_structured_block (parser);
|
||||
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
|
||||
cp_parser_end_omp_structured_block (parser, save);
|
||||
return finish_omp_structured_block (stmt);
|
||||
@ -18890,7 +18949,7 @@ cp_parser_omp_for_loop (cp_parser *parser)
|
||||
/* Note that the grammar doesn't call for a structured block here,
|
||||
though the loop as a whole is a structured block. */
|
||||
body = push_stmt_list ();
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
body = pop_stmt_list (body);
|
||||
|
||||
return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
|
||||
@ -18983,7 +19042,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
|
||||
|
||||
while (1)
|
||||
{
|
||||
cp_parser_statement (parser, NULL_TREE, false);
|
||||
cp_parser_statement (parser, NULL_TREE, false, NULL);
|
||||
|
||||
tok = cp_lexer_peek_token (parser->lexer);
|
||||
if (tok->pragma_kind == PRAGMA_OMP_SECTION)
|
||||
|
@ -9078,7 +9078,13 @@ tsubst_copy_and_build (tree t,
|
||||
return build_x_binary_op
|
||||
(TREE_CODE (t),
|
||||
RECUR (TREE_OPERAND (t, 0)),
|
||||
(TREE_NO_WARNING (TREE_OPERAND (t, 0))
|
||||
? ERROR_MARK
|
||||
: TREE_CODE (TREE_OPERAND (t, 0))),
|
||||
RECUR (TREE_OPERAND (t, 1)),
|
||||
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
|
||||
? ERROR_MARK
|
||||
: TREE_CODE (TREE_OPERAND (t, 1))),
|
||||
/*overloaded_p=*/NULL);
|
||||
|
||||
case SCOPE_REF:
|
||||
@ -9087,7 +9093,14 @@ tsubst_copy_and_build (tree t,
|
||||
case ARRAY_REF:
|
||||
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
|
||||
args, complain, in_decl);
|
||||
return build_x_binary_op (ARRAY_REF, op1, RECUR (TREE_OPERAND (t, 1)),
|
||||
return build_x_binary_op (ARRAY_REF, op1,
|
||||
(TREE_NO_WARNING (TREE_OPERAND (t, 0))
|
||||
? ERROR_MARK
|
||||
: TREE_CODE (TREE_OPERAND (t, 0))),
|
||||
RECUR (TREE_OPERAND (t, 1)),
|
||||
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
|
||||
? ERROR_MARK
|
||||
: TREE_CODE (TREE_OPERAND (t, 1))),
|
||||
/*overloaded_p=*/NULL);
|
||||
|
||||
case SIZEOF_EXPR:
|
||||
|
@ -587,6 +587,16 @@ maybe_convert_cond (tree cond)
|
||||
|
||||
/* Do the conversion. */
|
||||
cond = convert_from_reference (cond);
|
||||
|
||||
if (TREE_CODE (cond) == MODIFY_EXPR
|
||||
&& !TREE_NO_WARNING (cond)
|
||||
&& warn_parentheses)
|
||||
{
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around assignment used as truth value");
|
||||
TREE_NO_WARNING (cond) = 1;
|
||||
}
|
||||
|
||||
return condition_conversion (cond);
|
||||
}
|
||||
|
||||
|
@ -1690,17 +1690,20 @@ rationalize_conditional_expr (enum tree_code code, tree t)
|
||||
are equal, so we know what conditional expression this used to be. */
|
||||
if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
|
||||
{
|
||||
tree op0 = TREE_OPERAND (t, 0);
|
||||
tree op1 = TREE_OPERAND (t, 1);
|
||||
|
||||
/* The following code is incorrect if either operand side-effects. */
|
||||
gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
|
||||
&& !TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)));
|
||||
gcc_assert (!TREE_SIDE_EFFECTS (op0)
|
||||
&& !TREE_SIDE_EFFECTS (op1));
|
||||
return
|
||||
build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
|
||||
? LE_EXPR : GE_EXPR),
|
||||
TREE_OPERAND (t, 0),
|
||||
TREE_OPERAND (t, 1),
|
||||
op0, TREE_CODE (op0),
|
||||
op1, TREE_CODE (op1),
|
||||
/*overloaded_p=*/NULL),
|
||||
build_unary_op (code, TREE_OPERAND (t, 0), 0),
|
||||
build_unary_op (code, TREE_OPERAND (t, 1), 0));
|
||||
build_unary_op (code, op0, 0),
|
||||
build_unary_op (code, op1, 0));
|
||||
}
|
||||
|
||||
return
|
||||
@ -2908,8 +2911,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
|
||||
conversions on the operands. CODE is the kind of expression to build. */
|
||||
|
||||
tree
|
||||
build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
|
||||
bool *overloaded_p)
|
||||
build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
|
||||
tree arg2, enum tree_code arg2_code, bool *overloaded_p)
|
||||
{
|
||||
tree orig_arg1;
|
||||
tree orig_arg2;
|
||||
@ -2933,6 +2936,17 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
|
||||
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
|
||||
overloaded_p);
|
||||
|
||||
/* Check for cases such as x+y<<z which users are likely to
|
||||
misinterpret. But don't warn about obj << x + y, since that is a
|
||||
common idiom for I/O. */
|
||||
if (warn_parentheses
|
||||
&& !processing_template_decl
|
||||
&& !error_operand_p (arg1)
|
||||
&& !error_operand_p (arg2)
|
||||
&& (code != LSHIFT_EXPR
|
||||
|| !IS_AGGR_TYPE (TREE_TYPE (arg1))))
|
||||
warn_about_parentheses (code, arg1_code, arg2_code);
|
||||
|
||||
if (processing_template_decl && expr != error_mark_node)
|
||||
return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
|
||||
|
||||
@ -6280,6 +6294,19 @@ convert_for_assignment (tree type, tree rhs,
|
||||
errtype);
|
||||
}
|
||||
|
||||
/* If -Wparentheses, warn about a = b = c when a has type bool and b
|
||||
does not. */
|
||||
if (warn_parentheses
|
||||
&& type == boolean_type_node
|
||||
&& TREE_CODE (rhs) == MODIFY_EXPR
|
||||
&& !TREE_NO_WARNING (rhs)
|
||||
&& TREE_TYPE (rhs) != boolean_type_node)
|
||||
{
|
||||
warning (OPT_Wparentheses,
|
||||
"suggest parentheses around assignment used as truth value");
|
||||
TREE_NO_WARNING (rhs) = 1;
|
||||
}
|
||||
|
||||
return perform_implicit_conversion (strip_top_quals (type), rhs);
|
||||
}
|
||||
|
||||
|
@ -2212,9 +2212,7 @@ Warn if a user-supplied include directory does not exist.
|
||||
Warn if parentheses are omitted in certain contexts, such
|
||||
as when there is an assignment in a context where a truth value
|
||||
is expected, or when operators are nested whose precedence people
|
||||
often get confused about. Only the warning for an assignment used as
|
||||
a truth value is supported when compiling C++; the other warnings are
|
||||
only supported when compiling C@.
|
||||
often get confused about.
|
||||
|
||||
Also warn if a comparison like @samp{x<=y<=z} appears; this is
|
||||
equivalent to @samp{(x<=y ? 1 : 0) <= z}, which is a different
|
||||
@ -2236,14 +2234,15 @@ such a case:
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
In C, every @code{else} branch belongs to the innermost possible @code{if}
|
||||
statement, which in this example is @code{if (b)}. This is often not
|
||||
what the programmer expected, as illustrated in the above example by
|
||||
indentation the programmer chose. When there is the potential for this
|
||||
confusion, GCC will issue a warning when this flag is specified.
|
||||
To eliminate the warning, add explicit braces around the innermost
|
||||
@code{if} statement so there is no way the @code{else} could belong to
|
||||
the enclosing @code{if}. The resulting code would look like this:
|
||||
In C/C++, every @code{else} branch belongs to the innermost possible
|
||||
@code{if} statement, which in this example is @code{if (b)}. This is
|
||||
often not what the programmer expected, as illustrated in the above
|
||||
example by indentation the programmer chose. When there is the
|
||||
potential for this confusion, GCC will issue a warning when this flag
|
||||
is specified. To eliminate the warning, add explicit braces around
|
||||
the innermost @code{if} statement so there is no way the @code{else}
|
||||
could belong to the enclosing @code{if}. The resulting code would
|
||||
look like this:
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
|
Loading…
Reference in New Issue
Block a user