This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 2/2] Fix C++ side of PR c/70436 (missing -Wparentheses warnings)
- From: Patrick Palka <patrick at parcs dot ath dot cx>
- To: gcc-patches at gcc dot gnu dot org
- Cc: jason at redhat dot com, Patrick Palka <patrick at parcs dot ath dot cx>
- Date: Thu, 31 Mar 2016 16:54:04 -0400
- Subject: [PATCH 2/2] Fix C++ side of PR c/70436 (missing -Wparentheses warnings)
- Authentication-results: sourceware.org; auth=none
-Wparentheses currently warns about an ambiguous "else" in this code
if (a)
if (b)
bar ();
else
baz ();
but it fails to warn if there is an iteration statement between the
inner and outer ifs:
if (a)
for (;;)
if (b)
bar ();
else
baz ();
To fix this it's sufficient to just thread the IF_P parameter in
cp_parser_statement() through to cp_parser_iteration_statement() and
then to cp_parser_already_scoped_statement() and finally back to
cp_parser_statement(). In cp_parser_iteration_statement(), avoid
passing IF_P through a do-while statement, and in
cp_parser_already_scoped_statement() avoid passing IF_P through a
compound statement.
I think that covers all the vanilla C++ constructs that this warning has
to consider. As for C++ extensions, we still fail to warn for
if (a)
#pragma GCC ivdep
while (1)
if (b)
bar ();
else
baz ();
and
if (a)
_Cilk_for (int i = 0; i < 10; i++)
if (b)
bar ();
else
baz ();
and probably other constructs. I suppose support for this can be
implemented in a subsequent patch if deemed appropriate at this stage.
It would probably just involve more threading of the parameter IF_P.
Is this OK to commit after bootstrap + regtesting?
gcc/cp/ChangeLog:
PR c/70436
* parser.c (cp_parser_iteration_statement): New parameter IF_P.
Pass it through to cp_parser_already_scoped_statement.
(cp_parser_already_scoped_statement): New parameter IF_P. Pass
it through to cp_parser_statement.
(cp_parser_statement): Pass IF_P through to
cp_parser_iteration_statement.
(cp_parser_pragma): Adjust call to
cp_parser_iteration_statement.
gcc/testsuite/ChangeLog:
PR c/70436
* g++.dg/warn/Wparentheses-29.C: New test.
---
gcc/cp/parser.c | 20 +++---
gcc/testsuite/g++.dg/warn/Wparentheses-29.C | 97 +++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-29.C
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2f80856..af2a8f2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2104,7 +2104,7 @@ static tree cp_parser_selection_statement
static tree cp_parser_condition
(cp_parser *);
static tree cp_parser_iteration_statement
- (cp_parser *, bool);
+ (cp_parser *, bool *if_p, bool);
static bool cp_parser_for_init_statement
(cp_parser *, tree *decl);
static tree cp_parser_for
@@ -2127,7 +2127,7 @@ static void cp_parser_declaration_statement
static tree cp_parser_implicitly_scoped_statement
(cp_parser *, bool *, const token_indent_info &, vec<tree> * = NULL);
static void cp_parser_already_scoped_statement
- (cp_parser *, const token_indent_info &);
+ (cp_parser *, bool *if_p, const token_indent_info &);
/* Declarations [gram.dcl.dcl] */
@@ -10392,7 +10392,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
case RID_WHILE:
case RID_DO:
case RID_FOR:
- statement = cp_parser_iteration_statement (parser, false);
+ statement = cp_parser_iteration_statement (parser, if_p, false);
break;
case RID_CILK_FOR:
@@ -10947,7 +10947,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
else
{
/* This if statement does not have an else clause. If
- NESTED_IF is true, then the then-clause is an if
+ NESTED_IF is true, then the then-clause has an if
statement which does have an else clause. We warn
about the potential ambiguity. */
if (nested_if)
@@ -11544,7 +11544,7 @@ cp_parser_range_for_member_function (tree range, tree identifier)
Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */
static tree
-cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
+cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
{
cp_token *token;
enum rid keyword;
@@ -11582,7 +11582,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
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, guard_tinfo);
+ cp_parser_already_scoped_statement (parser, if_p, guard_tinfo);
parser->in_statement = in_statement;
/* We're done with the while-statement. */
finish_while_stmt (statement);
@@ -11627,7 +11627,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
/* Parse the body of the for-statement. */
parser->in_statement = IN_ITERATION_STMT;
- cp_parser_already_scoped_statement (parser, guard_tinfo);
+ cp_parser_already_scoped_statement (parser, if_p, guard_tinfo);
parser->in_statement = in_statement;
/* We're done with the for-statement. */
@@ -11937,7 +11937,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p,
scope. */
static void
-cp_parser_already_scoped_statement (cp_parser* parser,
+cp_parser_already_scoped_statement (cp_parser* parser, bool *if_p,
const token_indent_info &guard_tinfo)
{
/* If the token is a `{', then we must take special action. */
@@ -11946,7 +11946,7 @@ cp_parser_already_scoped_statement (cp_parser* parser,
token_indent_info body_tinfo
= get_token_indent_info (cp_lexer_peek_token (parser->lexer));
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
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);
@@ -37312,7 +37312,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
cp_parser_error (parser, "for, while or do statement expected");
return false;
}
- cp_parser_iteration_statement (parser, true);
+ cp_parser_iteration_statement (parser, NULL, true);
return true;
}
diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-29.C b/gcc/testsuite/g++.dg/warn/Wparentheses-29.C
new file mode 100644
index 0000000..125e6b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wparentheses-29.C
@@ -0,0 +1,97 @@
+/* PR c/70436 */
+/* { dg-options "-Wparentheses" } */
+
+int a, b;
+void bar (void);
+void baz (void);
+
+void
+foo (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ while (1)
+ if (a)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (;;)
+ if (b)
+ while (1)
+ {
+ if (a) { bar (); } else { baz (); }
+ }
+ else
+ bar ();
+
+ if (a)
+ for (;;)
+ if (b)
+ bar ();
+ else
+ baz ();
+ else bar ();
+
+ if (a)
+ while (1)
+ if (b)
+ bar ();
+ else
+ baz ();
+ else bar ();
+
+ if (a)
+ for (;;)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ for (;;)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ do
+ if (b) bar (); else baz ();
+ while (b);
+
+ if (a)
+ do
+ if (b) bar ();
+ while (b);
+ else baz ();
+}
--
2.8.0.rc3.27.gade0865