This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: Add support for -Wparentheses to the C++ frontend (PR c++/19564)


The C++ frontend currently has very limited support for the
-Wparentheses option.  However, -Wparentheses is just as meaningful
for C++ as it is for C.  This patch adds support for -Wparentheses to
C++.  This is PR 19564.

To make the C++ warning more palatable, there is one case which is
handled differently from C: we don't warn about + or - on the right
hand side of << where the left hand side is an aggregate.  This avoids
parentheses warnings for "cout << a + b".

This patch includes the fixes to libstdc++ to avoid the new warnings.
These are logically separate.  I included them in this patch because
they are mechanical, but I can break them out if preferred.

This has been tested with a bootstrap and testsuite run (including
libstdc++ testsuite) on i686-pc-linux-gnu.

Ian

:ADDPATCH c++:


gcc/ChangeLog:

2006-12-12  Ian Lance Taylor  <iant@google.com>

	PR c++/19564
	* 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.

gcc/cp/ChangeLog:

2006-12-12  Ian Lance Taylor  <iant@google.com>

	PR c++/19564
	* parser.c (cp_parser_expression_stack_entry): Add field
	lhs_type.
	(cp_parser_binary_expression): Track tree code of left hand side
	of expression.  Use it when calling build_x_binary_op.
	(cp_parser_selection_statement): Add if_p parameter.  Change all
	callers.  Warn about ambiguous else.
	(cp_parser_statement): Add if_p parameter.  Change all callers.
	(cp_parser_implicitly_scoped_statement): Likewise.
	* typeck.c (build_x_binary_op): Add parameters arg1_code and
	arg2_code.  Change all callers.  Call warn_about_parentheses.
	* cp-tree.h (build_x_binary_op): Update declaration.

gcc/testsuite/ChangeLog:

2006-12-12  Ian Lance Taylor  <iant@google.com>

	PR c++/19564
	* g++.dg/warn/Wparentheses-5.C: New test.
	* g++.dg/warn/Wparentheses-6.C: New test.
	* g++.dg/warn/Wparentheses-7.C: New test.
	* g++.dg/warn/Wparentheses-8.C: New test.
	* g++.dg/warn/Wparentheses-9.C: New test.
	* g++.dg/warn/Wparentheses-10.C: New test.
	* g++.dg/warn/Wparentheses-11.C: New test.
	* g++.dg/warn/Wparentheses-12.C: New test.
	* g++.dg/warn/Wparentheses-13.C: New test.
	* g++.dg/warn/Wparentheses-14.C: New test.
	* g++.dg/warn/Wparentheses-15.C: New test.
	* g++.dg/warn/Wparentheses-16.C: New test.
	* g++.dg/warn/Wparentheses-17.C: New test.
	* g++.dg/warn/Wparentheses-18.C: New test.
	* g++.dg/warn/Wparentheses-19.C: New test.
	* g++.dg/warn/Wparentheses-20.C: New test.
	* g++.dg/warn/Wparentheses-21.C: New test.

libstdc++-v3/ChangeLog:

2006-12-12  Ian Lance Taylor  <iant@google.com>

	PR c++/19564
	* include/bits/locale_facets.tcc (num_get<>::_M_extract_float):
	Add parentheses around && within || to avoid warning.
	(num_get<>::_M_extract_int): Likewise.
	(money_get<>::_M_extract): Likewise.
	(num_get<>::do_get(iter_type, iter_type, ios_base&,
	ios_base::iostate&, void*&)): Add parentheses around & within | to
	avoid warning.
	(num_put<>::do_put(iter_type, ios_base&, char_type, const void*)):
	Likewise.
	* include/bits/streambuf_iterator.h (istreambuf_iterator::equal):
	Add parentheses around && within || to avoid warning.
	* libsupc++/tinfo.cc (__do_dyncast): Likewise.
	* src/locale.cc (locale::_S_normalize_category): Likewise.
	* include/bits/stl_tree.h (_Rb_tree<>::_M_insert_unique): Add
	braces to avoid ambiguous else warning.
	* src/strstream.cc (strstreambuf::_M_free): Likewise.
	* src/tree.cc (_Rb_tree_rebalance_for_erase): Likewise.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 119752)
+++ gcc/doc/invoke.texi	(working copy)
@@ -2530,9 +2530,7 @@ Warn if a user-supplied include director
 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
@@ -2554,14 +2552,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
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 119752)
+++ gcc/cp/typeck.c	(working copy)
@@ -1648,17 +1648,20 @@ rationalize_conditional_expr (enum tree_
      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
@@ -2868,8 +2871,8 @@ convert_arguments (tree typelist, tree v
    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;
@@ -2893,6 +2896,17 @@ build_x_binary_op (enum tree_code code, 
     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);
 
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 119752)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -4458,8 +4458,9 @@ extern tree build_x_indirect_ref		(tree,
 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);
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 119752)
+++ gcc/cp/pt.c	(working copy)
@@ -9105,7 +9105,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:
@@ -9114,7 +9120,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:
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 119752)
+++ gcc/cp/parser.c	(working copy)
@@ -1158,8 +1158,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;
 
@@ -1517,7 +1524,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
@@ -1527,7 +1534,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
@@ -1540,7 +1547,7 @@ static void cp_parser_declaration_statem
   (cp_parser *);
 
 static tree cp_parser_implicitly_scoped_statement
-  (cp_parser *);
+  (cp_parser *, bool *);
 static void cp_parser_already_scoped_statement
   (cp_parser *);
 
@@ -5685,12 +5692,13 @@ cp_parser_binary_expression (cp_parser* 
   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 (;;)
     {
@@ -5723,6 +5731,7 @@ cp_parser_binary_expression (cp_parser* 
       /* 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
@@ -5738,8 +5747,10 @@ cp_parser_binary_expression (cp_parser* 
 	  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;
@@ -5756,11 +5767,15 @@ cp_parser_binary_expression (cp_parser* 
 	  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.
@@ -6177,17 +6192,23 @@ cp_parser_builtin_offsetof (cp_parser *p
      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.  */
@@ -6212,7 +6233,7 @@ cp_parser_statement (cp_parser* parser, 
 
 	case RID_IF:
 	case RID_SWITCH:
-	  statement = cp_parser_selection_statement (parser);
+	  statement = cp_parser_selection_statement (parser, if_p);
 	  break;
 
 	case RID_WHILE:
@@ -6477,7 +6498,7 @@ cp_parser_statement_seq_opt (cp_parser* 
 	break;
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr, true);
+      cp_parser_statement (parser, in_statement_expr, true, NULL);
     }
 }
 
@@ -6488,14 +6509,22 @@ cp_parser_statement_seq_opt (cp_parser* 
      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");
 
@@ -6531,11 +6560,13 @@ cp_parser_selection_statement (cp_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.  */
@@ -6546,8 +6577,28 @@ cp_parser_selection_statement (cp_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.  */
@@ -6566,7 +6617,7 @@ cp_parser_selection_statement (cp_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;
 
@@ -6744,7 +6795,7 @@ cp_parser_iteration_statement (cp_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.  */
@@ -6986,13 +7037,21 @@ cp_parser_declaration_statement (cp_pars
    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))
     {
@@ -7008,7 +7067,7 @@ cp_parser_implicitly_scoped_statement (c
       /* 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);
     }
@@ -7027,7 +7086,7 @@ cp_parser_already_scoped_statement (cp_p
 {
   /* 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
@@ -18654,7 +18713,7 @@ cp_parser_omp_structured_block (cp_parse
   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);
@@ -18899,7 +18958,7 @@ cp_parser_omp_for_loop (cp_parser *parse
   /* 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);
@@ -18992,7 +19051,7 @@ cp_parser_omp_sections_scope (cp_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)
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 119752)
+++ gcc/c-typeck.c	(working copy)
@@ -2629,73 +2629,7 @@ parser_build_binary_op (enum tree_code c
   /* 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.  */
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 119752)
+++ gcc/c-common.c	(working copy)
@@ -6606,5 +6606,87 @@ warn_array_subscript_with_type_char (tre
     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"
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 119752)
+++ gcc/c-common.h	(working copy)
@@ -859,6 +859,9 @@ extern int complete_array_type (tree *, 
 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);
Index: libstdc++-v3/include/bits/locale_facets.tcc
===================================================================
--- libstdc++-v3/include/bits/locale_facets.tcc	(revision 119752)
+++ libstdc++-v3/include/bits/locale_facets.tcc	(working copy)
@@ -314,7 +314,7 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
       int __sep_pos = 0;
       while (!__testeof)
 	{
-	  if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
+	  if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 	      || __c == __lc->_M_decimal_point)
 	    break;
 	  else if (__c == __lit[__num_base::_S_izero])
@@ -556,7 +556,7 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
 	int __sep_pos = 0;
 	while (!__testeof)
 	  {
-	    if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
+	    if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
 		|| __c == __lc->_M_decimal_point)
 	      break;
 	    else if (__c == __lit[__num_base::_S_izero] 
@@ -883,7 +883,7 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
       // Prepare for hex formatted input.
       typedef ios_base::fmtflags        fmtflags;
       const fmtflags __fmt = __io.flags();
-      __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
+      __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex);
 
       unsigned long __ul;
       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
@@ -1305,7 +1305,7 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
       const ios_base::fmtflags __fmt = ~(ios_base::basefield
 					 | ios_base::uppercase
 					 | ios_base::internal);
-      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
+      __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase));
 
       __s = _M_insert_int(__s, __io, __fill,
 			  reinterpret_cast<unsigned long>(__v));
@@ -1377,9 +1377,9 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
 					 == money_base::space)))
 		    || (__i == 2 && ((static_cast<part>(__p.field[3])
 				      == money_base::value)
-				     || __mandatory_sign
-				     && (static_cast<part>(__p.field[3])
-					 == money_base::sign))))
+				     || (__mandatory_sign
+					 && (static_cast<part>(__p.field[3])
+					     == money_base::sign)))))
 		  {
 		    const size_type __len = __lc->_M_curr_symbol_size;
 		    size_type __j = 0;
Index: libstdc++-v3/include/bits/streambuf_iterator.h
===================================================================
--- libstdc++-v3/include/bits/streambuf_iterator.h	(revision 119752)
+++ libstdc++-v3/include/bits/streambuf_iterator.h	(working copy)
@@ -160,7 +160,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       {
 	const bool __thiseof = _M_at_eof();
 	const bool __beof = __b._M_at_eof();
-	return (__thiseof && __beof || (!__thiseof && !__beof));
+	return ((__thiseof && __beof) || (!__thiseof && !__beof));
       }
 
     private:
Index: libstdc++-v3/include/bits/stl_tree.h
===================================================================
--- libstdc++-v3/include/bits/stl_tree.h	(revision 119752)
+++ libstdc++-v3/include/bits/stl_tree.h	(working copy)
@@ -1055,10 +1055,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	}
       iterator __j = iterator(__y);
       if (__comp)
-	if (__j == begin())
-	  return pair<iterator, bool>(_M_insert_(__x, __y, __v), true);
-	else
-	  --__j;
+	{
+	  if (__j == begin())
+	    return pair<iterator, bool>(_M_insert_(__x, __y, __v), true);
+	  else
+	    --__j;
+	}
       if (_M_impl._M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v)))
 	return pair<iterator, bool>(_M_insert_(__x, __y, __v), true);
       return pair<iterator, bool>(__j, false);
Index: libstdc++-v3/libsupc++/tinfo.cc
===================================================================
--- libstdc++-v3/libsupc++/tinfo.cc	(revision 119752)
+++ libstdc++-v3/libsupc++/tinfo.cc	(working copy)
@@ -490,9 +490,9 @@ __do_dyncast (ptrdiff_t src2dst,
           result.whole2dst =
               __sub_kind (result.whole2dst | result2.whole2dst);
         }
-      else if ((result.dst_ptr != 0 & result2.dst_ptr != 0)
-	       || (result.dst_ptr != 0 & result2_ambig)
-	       || (result2.dst_ptr != 0 & result_ambig))
+      else if ((result.dst_ptr != 0 && result2.dst_ptr != 0)
+	       || (result.dst_ptr != 0 && result2_ambig)
+	       || (result2.dst_ptr != 0 && result_ambig))
         {
           // Found two different DST_TYPE bases, or a valid one and a set of
           // ambiguous ones, must disambiguate. See whether SRC_PTR is
Index: libstdc++-v3/src/strstream.cc
===================================================================
--- libstdc++-v3/src/strstream.cc	(revision 119752)
+++ libstdc++-v3/src/strstream.cc	(working copy)
@@ -311,10 +311,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   strstreambuf::_M_free(char* p)
   {
     if (p)
-      if (_M_free_fun)
-	_M_free_fun(p);
-      else
-	delete[] p;
+      {
+	if (_M_free_fun)
+	  _M_free_fun(p);
+	else
+	  delete[] p;
+      }
   }
 
   void 
Index: libstdc++-v3/src/locale.cc
===================================================================
--- libstdc++-v3/src/locale.cc	(revision 119752)
+++ libstdc++-v3/src/locale.cc	(working copy)
@@ -146,7 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   locale::_S_normalize_category(category __cat) 
   {
     int __ret = 0;
-    if (__cat == none || (__cat & all) && !(__cat & ~all))
+    if (__cat == none || ((__cat & all) && !(__cat & ~all)))
       __ret = __cat;
     else
       {
Index: libstdc++-v3/src/tree.cc
===================================================================
--- libstdc++-v3/src/tree.cc	(revision 119752)
+++ libstdc++-v3/src/tree.cc	(working copy)
@@ -316,17 +316,21 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	  else
 	    __z->_M_parent->_M_right = __x;
 	if (__leftmost == __z) 
-	  if (__z->_M_right == 0)        // __z->_M_left must be null also
-	    __leftmost = __z->_M_parent;
-	// makes __leftmost == _M_header if __z == __root
-	  else
-	    __leftmost = _Rb_tree_node_base::_S_minimum(__x);
+	  {
+	    if (__z->_M_right == 0)        // __z->_M_left must be null also
+	      __leftmost = __z->_M_parent;
+	    // makes __leftmost == _M_header if __z == __root
+	    else
+	      __leftmost = _Rb_tree_node_base::_S_minimum(__x);
+	  }
 	if (__rightmost == __z)  
-	  if (__z->_M_left == 0)         // __z->_M_right must be null also
-	    __rightmost = __z->_M_parent;  
-	// makes __rightmost == _M_header if __z == __root
-	  else                      // __x == __z->_M_left
-	    __rightmost = _Rb_tree_node_base::_S_maximum(__x);
+	  {
+	    if (__z->_M_left == 0)         // __z->_M_right must be null also
+	      __rightmost = __z->_M_parent;  
+	    // makes __rightmost == _M_header if __z == __root
+	    else                      // __x == __z->_M_left
+	      __rightmost = _Rb_tree_node_base::_S_maximum(__x);
+	  }
       }
     if (__y->_M_color != _S_red) 
       { 
Index: gcc/testsuite/g++.dg/warn/Wparentheses-5.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-5.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-5.C	(revision 0)
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options -Wparentheses }
+
+// C++ version of gcc.dg/Wparentheses-1.c.
+
+int foo (int a, int b)
+{
+  int c = (a && b) || 0;	// { dg-bogus "suggest parentheses" }
+  c = a && b || 0;		// { dg-warning "suggest parentheses" }
+
+  return (a && b && 1) || 0;	// { dg-bogus "suggest parentheses" }
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-6.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-6.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-6.C	(revision 0)
@@ -0,0 +1,65 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-2.c.
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a <= b <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) <= c);
+  foo (a <= (b <= c));
+  foo (1 <= 2 <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) <= c);
+  foo (1 <= (2 <= c));
+  foo (1 <= 2 <= 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) <= 3);
+  foo (1 <= (2 <= 3));
+  foo (a > b > c); // { dg-warning "comparison" "correct warning" }
+  foo ((a > b) > c);
+  foo (a > (b > c));
+  foo (1 > 2 > c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 > 2) > c);
+  foo (1 > (2 > c));
+  foo (1 > 2 > 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 > 2) > 3);
+  foo (1 > (2 > 3));
+  foo (a < b <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((a < b) <= c);
+  foo (a < (b <= c));
+  foo (1 < 2 <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 < 2) <= c);
+  foo (1 < (2 <= c));
+  foo (1 < 2 <= 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 < 2) <= 3);
+  foo (1 < (2 <= 3));
+  foo (a <= b > c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) > c);
+  foo (a <= (b > c));
+  foo (1 <= 2 > c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) > c);
+  foo (1 <= (2 > c));
+  foo (1 <= 2 > 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) > 3);
+  foo (1 <= (2 > 3));
+  foo (a <= b == c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) == c);
+  foo (a <= (b == c));
+  foo (1 <= 2 == c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) == c);
+  foo (1 <= (2 == c));
+  foo (1 <= 2 == 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) == 3);
+  foo (1 <= (2 == 3));
+  foo (a != b != c); // { dg-warning "comparison" "correct warning" }
+  foo ((a != b) != c);
+  foo (a != (b != c));
+  foo (1 != 2 != c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 != 2) != c);
+  foo (1 != (2 != c));
+  foo (1 != 2 != 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 != 2) != 3);
+  foo (1 != (2 != 3));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-7.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-7.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-7.C	(revision 0)
@@ -0,0 +1,83 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ copy of gcc.dg/Wparentheses-4.c
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a + b << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) << c);
+  foo (a + (b << c));
+  foo (1 + 2 << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) << c);
+  foo (1 + (2 << c));
+  foo (1 + 2 << 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) << 3);
+  foo (1 + (2 << 3));
+  foo (a << b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a << b) + c);
+  foo (a << (b + c));
+  foo (1 << 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 << 2) + c);
+  foo (1 << (2 + c));
+  foo (1 << 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 << 2) + 3);
+  foo (1 << (2 + 3));
+  foo (a + b >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) >> c);
+  foo (a + (b >> c));
+  foo (1 + 2 >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) >> c);
+  foo (1 + (2 >> c));
+  foo (1 + 2 >> 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) >> 3);
+  foo (1 + (2 >> 3));
+  foo (a >> b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >> b) + c);
+  foo (a >> (b + c));
+  foo (1 >> 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >> 2) + c);
+  foo (1 >> (2 + c));
+  foo (1 >> 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >> 2) + 3);
+  foo (1 >> (2 + 3));
+  foo (a - b << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) << c);
+  foo (a - (b << c));
+  foo (6 - 5 << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) << c);
+  foo (6 - (5 << c));
+  foo (6 - 5 << 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) << 4);
+  foo (6 - (5 << 4));
+  foo (a << b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a << b) - c);
+  foo (a << (b - c));
+  foo (6 << 5 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 << 5) - c);
+  foo (6 << (5 - c));
+  foo (6 << 5 - 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 << 5) - 4);
+  foo (6 << (5 - 4));
+  foo (a - b >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) >> c);
+  foo (a - (b >> c));
+  foo (6 - 5 >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) >> c);
+  foo (6 - (5 >> c));
+  foo (6 - 5 >> 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) >> 4);
+  foo (6 - (5 >> 4));
+  foo (a >> b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >> b) - c);
+  foo (a >> (b - c));
+  foo (6 >> 5 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 >> 5) - c);
+  foo (6 >> (5 - c));
+  foo (6 >> 5 - 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 >> 5) - 4);
+  foo (6 >> (5 - 4));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-8.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-8.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-8.C	(revision 0)
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-5.c
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a && b || c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a && b) || c);
+  foo (a && (b || c));
+  foo (1 && 2 || c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 && 2) || c);
+  foo (1 && (2 || c));
+  foo (1 && 2 || 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 && 2) || 3);
+  foo (1 && (2 || 3));
+  foo (a || b && c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a || b) && c);
+  foo (a || (b && c));
+  foo (1 || 2 && c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 || 2) && c);
+  foo (1 || (2 && c));
+  foo (1 || 2 && 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 || 2) && 3);
+  foo (1 || (2 && 3));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-9.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-9.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-9.C	(revision 0)
@@ -0,0 +1,119 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-6.c
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a & b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) | c);
+  foo (a & (b | c));
+  foo (1 & 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) | c);
+  foo (1 & (2 | c));
+  foo (1 & 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) | 3);
+  foo (1 & (2 | 3));
+  foo (a | b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) & c);
+  foo (a | (b & c));
+  foo (1 | 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) & c);
+  foo (1 | (2 & c));
+  foo (1 | 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) & 3);
+  foo (1 | (2 & 3));
+  foo (a ^ b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) | c);
+  foo (a ^ (b | c));
+  foo (1 ^ 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) | c);
+  foo (1 ^ (2 | c));
+  foo (1 ^ 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) | 3);
+  foo (1 ^ (2 | 3));
+  foo (a | b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) ^ c);
+  foo (a | (b ^ c));
+  foo (1 | 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) ^ c);
+  foo (1 | (2 ^ c));
+  foo (1 | 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) ^ 3);
+  foo (1 | (2 ^ 3));
+  foo (a + b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) | c);
+  foo (a + (b | c));
+  foo (1 + 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) | c);
+  foo (1 + (2 | c));
+  foo (1 + 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) | 3);
+  foo (1 + (2 | 3));
+  foo (a | b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) + c);
+  foo (a | (b + c));
+  foo (1 | 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) + c);
+  foo (1 | (2 + c));
+  foo (1 | 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) + 3);
+  foo (1 | (2 + 3));
+  foo (a - b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) | c);
+  foo (a - (b | c));
+  foo (1 - 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) | c);
+  foo (1 - (2 | c));
+  foo (1 - 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) | 3);
+  foo (1 - (2 | 3));
+  foo (a | b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) - c);
+  foo (a | (b - c));
+  foo (1 | 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) - c);
+  foo (1 | (2 - c));
+  foo (1 | 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) - 3);
+  foo (1 | (2 - 3));
+  foo (a > b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a > b) | c);
+  foo (a > (b | c));
+  foo (1 > 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 > 2) | c);
+  foo (1 > (2 | c));
+  foo (1 > 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 > 2) | 3);
+  foo (1 > (2 | 3));
+  foo (a | b > c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) > c);
+  foo (a | (b > c));
+  foo (1 | 2 > c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) > c);
+  foo (1 | (2 > c));
+  foo (1 | 2 > 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) > 3);
+  foo (1 | (2 > 3));
+  foo (a <= b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a <= b) | c);
+  foo (a <= (b | c));
+  foo (1 <= 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 <= 2) | c);
+  foo (1 <= (2 | c));
+  foo (1 <= 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 <= 2) | 3);
+  foo (1 <= (2 | 3));
+  foo (a | b <= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) <= c);
+  foo (a | (b <= c));
+  foo (1 | 2 <= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) <= c);
+  foo (1 | (2 <= c));
+  foo (1 | 2 <= 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) <= 3);
+  foo (1 | (2 <= 3));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-10.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-10.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-10.C	(revision 0)
@@ -0,0 +1,119 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-7.c
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a & b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) ^ c);
+  foo (a & (b ^ c));
+  foo (1 & 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) ^ c);
+  foo (1 & (2 ^ c));
+  foo (1 & 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) ^ 3);
+  foo (1 & (2 ^ 3));
+  foo (a ^ b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) & c);
+  foo (a ^ (b & c));
+  foo (1 ^ 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) & c);
+  foo (1 ^ (2 & c));
+  foo (1 ^ 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) & 3);
+  foo (1 ^ (2 & 3));
+  foo (a + b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) ^ c);
+  foo (a + (b ^ c));
+  foo (1 + 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) ^ c);
+  foo (1 + (2 ^ c));
+  foo (1 + 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) ^ 3);
+  foo (1 + (2 ^ 3));
+  foo (a ^ b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) + c);
+  foo (a ^ (b + c));
+  foo (1 ^ 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) + c);
+  foo (1 ^ (2 + c));
+  foo (1 ^ 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) + 3);
+  foo (1 ^ (2 + 3));
+  foo (a - b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) ^ c);
+  foo (a - (b ^ c));
+  foo (1 - 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) ^ c);
+  foo (1 - (2 ^ c));
+  foo (1 - 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) ^ 3);
+  foo (1 - (2 ^ 3));
+  foo (a ^ b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) - c);
+  foo (a ^ (b - c));
+  foo (1 ^ 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) - c);
+  foo (1 ^ (2 - c));
+  foo (1 ^ 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) - 3);
+  foo (1 ^ (2 - 3));
+  foo (a >= b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >= b) ^ c);
+  foo (a >= (b ^ c));
+  foo (1 >= 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >= 2) ^ c);
+  foo (1 >= (2 ^ c));
+  foo (1 >= 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >= 2) ^ 3);
+  foo (1 >= (2 ^ 3));
+  foo (a ^ b >= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) >= c);
+  foo (a ^ (b >= c));
+  foo (1 ^ 2 >= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) >= c);
+  foo (1 ^ (2 >= c));
+  foo (1 ^ 2 >= 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) >= 3);
+  foo (1 ^ (2 >= 3));
+  foo (a == b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a == b) ^ c);
+  foo (a == (b ^ c));
+  foo (1 == 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) ^ c);
+  foo (1 == (2 ^ c));
+  foo (1 == 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) ^ 3);
+  foo (1 == (2 ^ 3));
+  foo (a ^ b == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) == c);
+  foo (a ^ (b == c));
+  foo (1 ^ 2 == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) == c);
+  foo (1 ^ (2 == c));
+  foo (1 ^ 2 == 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) == 3);
+  foo (1 ^ (2 == 3));
+  foo (a < b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a < b) ^ c);
+  foo (a < (b ^ c));
+  foo (1 < 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) ^ c);
+  foo (1 < (2 ^ c));
+  foo (1 < 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) ^ 3);
+  foo (1 < (2 ^ 3));
+  foo (a ^ b < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) < c);
+  foo (a ^ (b < c));
+  foo (1 ^ 2 < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) < c);
+  foo (1 ^ (2 < c));
+  foo (1 ^ 2 < 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) < 3);
+  foo (1 ^ (2 < 3));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-11.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-11.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-11.C	(revision 0)
@@ -0,0 +1,101 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-8.c
+
+int foo (int);
+
+int
+bar (int a, int b, int c)
+{
+  foo (a + b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) & c);
+  foo (a + (b & c));
+  foo (1 + 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) & c);
+  foo (1 + (2 & c));
+  foo (1 + 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) & 3);
+  foo (1 + (2 & 3));
+  foo (a & b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) + c);
+  foo (a & (b + c));
+  foo (1 & 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) + c);
+  foo (1 & (2 + c));
+  foo (1 & 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) + 3);
+  foo (1 & (2 + 3));
+  foo (a - b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) & c);
+  foo (a - (b & c));
+  foo (1 - 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) & c);
+  foo (1 - (2 & c));
+  foo (1 - 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) & 3);
+  foo (1 - (2 & 3));
+  foo (a & b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) - c);
+  foo (a & (b - c));
+  foo (1 & 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) - c);
+  foo (1 & (2 - c));
+  foo (1 & 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) - 3);
+  foo (1 & (2 - 3));
+  foo (a < b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a < b) & c);
+  foo (a < (b & c));
+  foo (1 < 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) & c);
+  foo (1 < (2 & c));
+  foo (1 < 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) & 3);
+  foo (1 < (2 & 3));
+  foo (a & b < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) < c);
+  foo (a & (b < c));
+  foo (1 & 2 < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) < c);
+  foo (1 & (2 < c));
+  foo (1 & 2 < 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) < 3);
+  foo (1 & (2 < 3));
+  foo (a == b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a == b) & c);
+  foo (a == (b & c));
+  foo (1 == 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) & c);
+  foo (1 == (2 & c));
+  foo (1 == 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) & 3);
+  foo (1 == (2 & 3));
+  foo (a & b == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) == c);
+  foo (a & (b == c));
+  foo (1 & 2 == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) == c);
+  foo (1 & (2 == c));
+  foo (1 & 2 == 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) == 3);
+  foo (1 & (2 == 3));
+  foo (a != b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a != b) & c);
+  foo (a != (b & c));
+  foo (1 != 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 != 2) & c);
+  foo (1 != (2 & c));
+  foo (1 != 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 != 2) & 3);
+  foo (1 != (2 & 3));
+  foo (a & b != c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) != c);
+  foo (a & (b != c));
+  foo (1 & 2 != c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) != c);
+  foo (1 & (2 != c));
+  foo (1 & 2 != 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) != 3);
+  foo (1 & (2 != 3));
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-12.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-12.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-12.C	(revision 0)
@@ -0,0 +1,60 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// C++ version of gcc.dg/Wparentheses-9.c
+
+int foo (int);
+
+int a, b, c;
+
+int
+bar (void)
+{
+  if (a)
+    foo (0);
+  if (b)
+    foo (1);
+  else
+    foo (2);
+  if (c) // { dg-warning "ambiguous" "correct warning" }
+    if (a)
+      foo (3);
+    else
+      foo (4);
+  if (a)
+    if (c)
+      foo (5);
+  if (a)
+    if (b) // { dg-warning "ambiguous" "correct warning" }
+      if (c)
+	foo (6);
+      else
+	foo (7);
+  if (a) // { dg-warning "ambiguous" "correct warning" }
+    if (b)
+      if (c)
+	foo (8);
+      else
+	foo (9);
+    else
+      foo (10);
+  if (a)
+    if (b)
+      if (c)
+	foo (11);
+      else
+	foo (12);
+    else
+      foo (13);
+  else
+    foo (14);
+  if (a) {
+    if (b)
+      if (c)
+	foo (15);
+      else
+	foo (16);
+    else
+      foo (17);
+  }
+}
Index: gcc/testsuite/g++.dg/warn/Wparentheses-13.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-13.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-13.C	(revision 0)
@@ -0,0 +1,69 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-1.C.
+
+int foo (int);
+
+int a, b, c;
+bool d;
+
+template<class T>
+void
+bar (T)
+{
+  if (a = b) // { dg-warning "assignment" "correct warning" }
+    foo (0);
+  if ((a = b))
+    foo (1);
+  if (a = a) // { dg-warning "assignment" "correct warning" }
+    foo (2);
+  if ((a = a))
+    foo (3);
+  if (b = c) // { dg-warning "assignment" "correct warning" }
+    foo (4);
+  else
+    foo (5);
+  if ((b = c))
+    foo (6);
+  else
+    foo (7);
+  if (b = b) // { dg-warning "assignment" "correct warning" }
+    foo (8);
+  else
+    foo (9);
+  if ((b = b))
+    foo (10);
+  else
+    foo (11);
+  while (c = b) // { dg-warning "assignment" "correct warning" }
+    foo (12);
+  while ((c = b))
+    foo (13);
+  while (c = c) // { dg-warning "assignment" "correct warning" }
+    foo (14);
+  while ((c = c))
+    foo (15);
+  do foo (16); while (a = b); // { dg-warning "assignment" "correct warning" }
+  do foo (17); while ((a = b));
+  do foo (18); while (a = a); // { dg-warning "assignment" "correct warning" }
+  do foo (19); while ((a = a));
+  for (;c = b;) // { dg-warning "assignment" "correct warning" }
+    foo (20);
+  for (;(c = b);)
+    foo (21);
+  for (;c = c;) // { dg-warning "assignment" "correct warning" }
+    foo (22);
+  for (;(c = c);)
+    foo (23);
+  d = a = b; // { dg-warning "assignment" "correct warning" }
+  foo (24);
+  d = (a = b);
+  foo (25);
+  d = a = a; // { dg-warning "assignment" "correct warning" }
+  foo (26);
+  d = (a = a);
+  foo (27);
+}
+
+template void bar<int> (int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-14.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-14.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-14.C	(revision 0)
@@ -0,0 +1,43 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-2.C.
+
+int foo (int);
+
+int a, b, c;
+bool d;
+
+template<class T>
+void
+bar (T)
+{
+  if (a += b)
+    foo (0);
+  if (a -= a)
+    foo (1);
+  if (b *= c)
+    foo (2);
+  else
+    foo (3);
+  if (b /= b)
+    foo (4);
+  else
+    foo (5);
+  while (c %= b)
+    foo (6);
+  while (c <<= c)
+    foo (7);
+  do foo (8); while (a >>= b);
+  do foo (9); while (a &= a);
+  for (;c ^= b;)
+    foo (10);
+  for (;c |= c;)
+    foo (11);
+  d = a += b;
+  foo (12);
+  d = a -= a;
+  foo (13);
+}
+
+template void bar<int> (int);
Index: gcc/testsuite/g++.dg/warn/Wparentheses-15.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-15.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-15.C	(revision 0)
@@ -0,0 +1,68 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-6.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a <= b <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) <= c);
+  foo (a <= (b <= c));
+  foo (1 <= 2 <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) <= c);
+  foo (1 <= (2 <= c));
+  foo (1 <= 2 <= 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) <= 3);
+  foo (1 <= (2 <= 3));
+  foo (a > b > c); // { dg-warning "comparison" "correct warning" }
+  foo ((a > b) > c);
+  foo (a > (b > c));
+  foo (1 > 2 > c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 > 2) > c);
+  foo (1 > (2 > c));
+  foo (1 > 2 > 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 > 2) > 3);
+  foo (1 > (2 > 3));
+  foo (a < b <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((a < b) <= c);
+  foo (a < (b <= c));
+  foo (1 < 2 <= c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 < 2) <= c);
+  foo (1 < (2 <= c));
+  foo (1 < 2 <= 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 < 2) <= 3);
+  foo (1 < (2 <= 3));
+  foo (a <= b > c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) > c);
+  foo (a <= (b > c));
+  foo (1 <= 2 > c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) > c);
+  foo (1 <= (2 > c));
+  foo (1 <= 2 > 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) > 3);
+  foo (1 <= (2 > 3));
+  foo (a <= b == c); // { dg-warning "comparison" "correct warning" }
+  foo ((a <= b) == c);
+  foo (a <= (b == c));
+  foo (1 <= 2 == c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) == c);
+  foo (1 <= (2 == c));
+  foo (1 <= 2 == 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 <= 2) == 3);
+  foo (1 <= (2 == 3));
+  foo (a != b != c); // { dg-warning "comparison" "correct warning" }
+  foo ((a != b) != c);
+  foo (a != (b != c));
+  foo (1 != 2 != c); // { dg-warning "comparison" "correct warning" }
+  foo ((1 != 2) != c);
+  foo (1 != (2 != c));
+  foo (1 != 2 != 3); // { dg-warning "comparison" "correct warning" }
+  foo ((1 != 2) != 3);
+  foo (1 != (2 != 3));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-16.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-16.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-16.C	(revision 0)
@@ -0,0 +1,86 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-7.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a + b << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) << c);
+  foo (a + (b << c));
+  foo (1 + 2 << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) << c);
+  foo (1 + (2 << c));
+  foo (1 + 2 << 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) << 3);
+  foo (1 + (2 << 3));
+  foo (a << b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a << b) + c);
+  foo (a << (b + c));
+  foo (1 << 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 << 2) + c);
+  foo (1 << (2 + c));
+  foo (1 << 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 << 2) + 3);
+  foo (1 << (2 + 3));
+  foo (a + b >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) >> c);
+  foo (a + (b >> c));
+  foo (1 + 2 >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) >> c);
+  foo (1 + (2 >> c));
+  foo (1 + 2 >> 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) >> 3);
+  foo (1 + (2 >> 3));
+  foo (a >> b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >> b) + c);
+  foo (a >> (b + c));
+  foo (1 >> 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >> 2) + c);
+  foo (1 >> (2 + c));
+  foo (1 >> 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >> 2) + 3);
+  foo (1 >> (2 + 3));
+  foo (a - b << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) << c);
+  foo (a - (b << c));
+  foo (6 - 5 << c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) << c);
+  foo (6 - (5 << c));
+  foo (6 - 5 << 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) << 4);
+  foo (6 - (5 << 4));
+  foo (a << b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a << b) - c);
+  foo (a << (b - c));
+  foo (6 << 5 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 << 5) - c);
+  foo (6 << (5 - c));
+  foo (6 << 5 - 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 << 5) - 4);
+  foo (6 << (5 - 4));
+  foo (a - b >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) >> c);
+  foo (a - (b >> c));
+  foo (6 - 5 >> c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) >> c);
+  foo (6 - (5 >> c));
+  foo (6 - 5 >> 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 - 5) >> 4);
+  foo (6 - (5 >> 4));
+  foo (a >> b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >> b) - c);
+  foo (a >> (b - c));
+  foo (6 >> 5 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 >> 5) - c);
+  foo (6 >> (5 - c));
+  foo (6 >> 5 - 4); // { dg-warning "parentheses" "correct warning" }
+  foo ((6 >> 5) - 4);
+  foo (6 >> (5 - 4));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-17.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-17.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-17.C	(revision 0)
@@ -0,0 +1,32 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-8.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a && b || c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a && b) || c);
+  foo (a && (b || c));
+  foo (1 && 2 || c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 && 2) || c);
+  foo (1 && (2 || c));
+  foo (1 && 2 || 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 && 2) || 3);
+  foo (1 && (2 || 3));
+  foo (a || b && c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a || b) && c);
+  foo (a || (b && c));
+  foo (1 || 2 && c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 || 2) && c);
+  foo (1 || (2 && c));
+  foo (1 || 2 && 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 || 2) && 3);
+  foo (1 || (2 && 3));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-18.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-18.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-18.C	(revision 0)
@@ -0,0 +1,122 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-9.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a & b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) | c);
+  foo (a & (b | c));
+  foo (1 & 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) | c);
+  foo (1 & (2 | c));
+  foo (1 & 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) | 3);
+  foo (1 & (2 | 3));
+  foo (a | b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) & c);
+  foo (a | (b & c));
+  foo (1 | 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) & c);
+  foo (1 | (2 & c));
+  foo (1 | 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) & 3);
+  foo (1 | (2 & 3));
+  foo (a ^ b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) | c);
+  foo (a ^ (b | c));
+  foo (1 ^ 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) | c);
+  foo (1 ^ (2 | c));
+  foo (1 ^ 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) | 3);
+  foo (1 ^ (2 | 3));
+  foo (a | b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) ^ c);
+  foo (a | (b ^ c));
+  foo (1 | 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) ^ c);
+  foo (1 | (2 ^ c));
+  foo (1 | 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) ^ 3);
+  foo (1 | (2 ^ 3));
+  foo (a + b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) | c);
+  foo (a + (b | c));
+  foo (1 + 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) | c);
+  foo (1 + (2 | c));
+  foo (1 + 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) | 3);
+  foo (1 + (2 | 3));
+  foo (a | b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) + c);
+  foo (a | (b + c));
+  foo (1 | 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) + c);
+  foo (1 | (2 + c));
+  foo (1 | 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) + 3);
+  foo (1 | (2 + 3));
+  foo (a - b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) | c);
+  foo (a - (b | c));
+  foo (1 - 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) | c);
+  foo (1 - (2 | c));
+  foo (1 - 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) | 3);
+  foo (1 - (2 | 3));
+  foo (a | b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) - c);
+  foo (a | (b - c));
+  foo (1 | 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) - c);
+  foo (1 | (2 - c));
+  foo (1 | 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) - 3);
+  foo (1 | (2 - 3));
+  foo (a > b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a > b) | c);
+  foo (a > (b | c));
+  foo (1 > 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 > 2) | c);
+  foo (1 > (2 | c));
+  foo (1 > 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 > 2) | 3);
+  foo (1 > (2 | 3));
+  foo (a | b > c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) > c);
+  foo (a | (b > c));
+  foo (1 | 2 > c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) > c);
+  foo (1 | (2 > c));
+  foo (1 | 2 > 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) > 3);
+  foo (1 | (2 > 3));
+  foo (a <= b | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a <= b) | c);
+  foo (a <= (b | c));
+  foo (1 <= 2 | c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 <= 2) | c);
+  foo (1 <= (2 | c));
+  foo (1 <= 2 | 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 <= 2) | 3);
+  foo (1 <= (2 | 3));
+  foo (a | b <= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a | b) <= c);
+  foo (a | (b <= c));
+  foo (1 | 2 <= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) <= c);
+  foo (1 | (2 <= c));
+  foo (1 | 2 <= 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 | 2) <= 3);
+  foo (1 | (2 <= 3));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-19.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-19.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-19.C	(revision 0)
@@ -0,0 +1,122 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-10.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a & b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) ^ c);
+  foo (a & (b ^ c));
+  foo (1 & 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) ^ c);
+  foo (1 & (2 ^ c));
+  foo (1 & 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) ^ 3);
+  foo (1 & (2 ^ 3));
+  foo (a ^ b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) & c);
+  foo (a ^ (b & c));
+  foo (1 ^ 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) & c);
+  foo (1 ^ (2 & c));
+  foo (1 ^ 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) & 3);
+  foo (1 ^ (2 & 3));
+  foo (a + b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) ^ c);
+  foo (a + (b ^ c));
+  foo (1 + 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) ^ c);
+  foo (1 + (2 ^ c));
+  foo (1 + 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) ^ 3);
+  foo (1 + (2 ^ 3));
+  foo (a ^ b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) + c);
+  foo (a ^ (b + c));
+  foo (1 ^ 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) + c);
+  foo (1 ^ (2 + c));
+  foo (1 ^ 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) + 3);
+  foo (1 ^ (2 + 3));
+  foo (a - b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) ^ c);
+  foo (a - (b ^ c));
+  foo (1 - 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) ^ c);
+  foo (1 - (2 ^ c));
+  foo (1 - 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) ^ 3);
+  foo (1 - (2 ^ 3));
+  foo (a ^ b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) - c);
+  foo (a ^ (b - c));
+  foo (1 ^ 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) - c);
+  foo (1 ^ (2 - c));
+  foo (1 ^ 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) - 3);
+  foo (1 ^ (2 - 3));
+  foo (a >= b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a >= b) ^ c);
+  foo (a >= (b ^ c));
+  foo (1 >= 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >= 2) ^ c);
+  foo (1 >= (2 ^ c));
+  foo (1 >= 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 >= 2) ^ 3);
+  foo (1 >= (2 ^ 3));
+  foo (a ^ b >= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) >= c);
+  foo (a ^ (b >= c));
+  foo (1 ^ 2 >= c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) >= c);
+  foo (1 ^ (2 >= c));
+  foo (1 ^ 2 >= 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) >= 3);
+  foo (1 ^ (2 >= 3));
+  foo (a == b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a == b) ^ c);
+  foo (a == (b ^ c));
+  foo (1 == 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) ^ c);
+  foo (1 == (2 ^ c));
+  foo (1 == 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) ^ 3);
+  foo (1 == (2 ^ 3));
+  foo (a ^ b == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) == c);
+  foo (a ^ (b == c));
+  foo (1 ^ 2 == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) == c);
+  foo (1 ^ (2 == c));
+  foo (1 ^ 2 == 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) == 3);
+  foo (1 ^ (2 == 3));
+  foo (a < b ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a < b) ^ c);
+  foo (a < (b ^ c));
+  foo (1 < 2 ^ c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) ^ c);
+  foo (1 < (2 ^ c));
+  foo (1 < 2 ^ 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) ^ 3);
+  foo (1 < (2 ^ 3));
+  foo (a ^ b < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a ^ b) < c);
+  foo (a ^ (b < c));
+  foo (1 ^ 2 < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) < c);
+  foo (1 ^ (2 < c));
+  foo (1 ^ 2 < 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 ^ 2) < 3);
+  foo (1 ^ (2 < 3));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-20.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-20.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-20.C	(revision 0)
@@ -0,0 +1,104 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-11.C.
+
+int foo (int);
+
+template<class T>
+void
+bar (T a, T b, T c)
+{
+  foo (a + b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a + b) & c);
+  foo (a + (b & c));
+  foo (1 + 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) & c);
+  foo (1 + (2 & c));
+  foo (1 + 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 + 2) & 3);
+  foo (1 + (2 & 3));
+  foo (a & b + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) + c);
+  foo (a & (b + c));
+  foo (1 & 2 + c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) + c);
+  foo (1 & (2 + c));
+  foo (1 & 2 + 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) + 3);
+  foo (1 & (2 + 3));
+  foo (a - b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a - b) & c);
+  foo (a - (b & c));
+  foo (1 - 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) & c);
+  foo (1 - (2 & c));
+  foo (1 - 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 - 2) & 3);
+  foo (1 - (2 & 3));
+  foo (a & b - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) - c);
+  foo (a & (b - c));
+  foo (1 & 2 - c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) - c);
+  foo (1 & (2 - c));
+  foo (1 & 2 - 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) - 3);
+  foo (1 & (2 - 3));
+  foo (a < b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a < b) & c);
+  foo (a < (b & c));
+  foo (1 < 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) & c);
+  foo (1 < (2 & c));
+  foo (1 < 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 < 2) & 3);
+  foo (1 < (2 & 3));
+  foo (a & b < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) < c);
+  foo (a & (b < c));
+  foo (1 & 2 < c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) < c);
+  foo (1 & (2 < c));
+  foo (1 & 2 < 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) < 3);
+  foo (1 & (2 < 3));
+  foo (a == b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a == b) & c);
+  foo (a == (b & c));
+  foo (1 == 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) & c);
+  foo (1 == (2 & c));
+  foo (1 == 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 == 2) & 3);
+  foo (1 == (2 & 3));
+  foo (a & b == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) == c);
+  foo (a & (b == c));
+  foo (1 & 2 == c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) == c);
+  foo (1 & (2 == c));
+  foo (1 & 2 == 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) == 3);
+  foo (1 & (2 == 3));
+  foo (a != b & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a != b) & c);
+  foo (a != (b & c));
+  foo (1 != 2 & c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 != 2) & c);
+  foo (1 != (2 & c));
+  foo (1 != 2 & 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 != 2) & 3);
+  foo (1 != (2 & 3));
+  foo (a & b != c); // { dg-warning "parentheses" "correct warning" }
+  foo ((a & b) != c);
+  foo (a & (b != c));
+  foo (1 & 2 != c); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) != c);
+  foo (1 & (2 != c));
+  foo (1 & 2 != 3); // { dg-warning "parentheses" "correct warning" }
+  foo ((1 & 2) != 3);
+  foo (1 & (2 != 3));
+}
+
+template void bar<int> (int, int, int); // { dg-warning "instantiated" }
Index: gcc/testsuite/g++.dg/warn/Wparentheses-21.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wparentheses-21.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wparentheses-21.C	(revision 0)
@@ -0,0 +1,66 @@
+// { dg-do compile }
+// { dg-options "-Wparentheses" }
+
+// Template version of Wparentheses-12.C.  Note that we currently warn
+// when we initially parse the template, not when we are instantiating
+// it.  That seems reasonable since the template parameters can not
+// affect the syntax parsing.
+
+int foo (int);
+
+int a, b, c;
+
+template<class T>
+void
+bar (T)
+{
+  if (a)
+    foo (0);
+  if (b)
+    foo (1);
+  else
+    foo (2);
+  if (c) // { dg-warning "ambiguous" "correct warning" }
+    if (a)
+      foo (3);
+    else
+      foo (4);
+  if (a)
+    if (c)
+      foo (5);
+  if (a)
+    if (b) // { dg-warning "ambiguous" "correct warning" }
+      if (c)
+	foo (6);
+      else
+	foo (7);
+  if (a) // { dg-warning "ambiguous" "correct warning" }
+    if (b)
+      if (c)
+	foo (8);
+      else
+	foo (9);
+    else
+      foo (10);
+  if (a)
+    if (b)
+      if (c)
+	foo (11);
+      else
+	foo (12);
+    else
+      foo (13);
+  else
+    foo (14);
+  if (a) {
+    if (b)
+      if (c)
+	foo (15);
+      else
+	foo (16);
+    else
+      foo (17);
+  }
+}
+
+template void bar<int> (int);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]