Author: pfg
Date: Wed Nov 13 04:31:27 2013
New Revision: 258081
URL: http://svnweb.freebsd.org/changeset/base/258081

Log:
  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

Modified:
  head/contrib/gcc/ChangeLog.gcc43
  head/contrib/gcc/c-common.c
  head/contrib/gcc/c-common.h
  head/contrib/gcc/c-typeck.c
  head/contrib/gcc/cp/cp-tree.h
  head/contrib/gcc/cp/parser.c
  head/contrib/gcc/cp/pt.c
  head/contrib/gcc/cp/semantics.c
  head/contrib/gcc/cp/typeck.c
  head/contrib/gcc/doc/invoke.texi

Modified: head/contrib/gcc/ChangeLog.gcc43
==============================================================================
--- head/contrib/gcc/ChangeLog.gcc43    Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/ChangeLog.gcc43    Wed Nov 13 04:31:27 2013        
(r258081)
@@ -232,6 +232,17 @@
 
        * config.gcc: Support core2 processor.
 
+2006-12-13  Ian Lance Taylor  <i...@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...@intel.com> (r119454 - partial)
 
        PR target/30040

Modified: head/contrib/gcc/c-common.c
==============================================================================
--- head/contrib/gcc/c-common.c Wed Nov 13 03:50:31 2013        (r258080)
+++ head/contrib/gcc/c-common.c Wed Nov 13 04:31:27 2013        (r258081)
@@ -2585,9 +2585,13 @@ c_common_truthvalue_conversion (tree exp
       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 (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"

Modified: head/contrib/gcc/c-common.h
==============================================================================
--- head/contrib/gcc/c-common.h Wed Nov 13 03:50:31 2013        (r258080)
+++ head/contrib/gcc/c-common.h Wed Nov 13 04:31:27 2013        (r258081)
@@ -850,6 +850,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);

Modified: head/contrib/gcc/c-typeck.c
==============================================================================
--- head/contrib/gcc/c-typeck.c Wed Nov 13 03:50:31 2013        (r258080)
+++ head/contrib/gcc/c-typeck.c Wed Nov 13 04:31:27 2013        (r258081)
@@ -2631,73 +2631,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.  */

Modified: head/contrib/gcc/cp/cp-tree.h
==============================================================================
--- head/contrib/gcc/cp/cp-tree.h       Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/cp/cp-tree.h       Wed Nov 13 04:31:27 2013        
(r258081)
@@ -4460,8 +4460,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);

Modified: head/contrib/gcc/cp/parser.c
==============================================================================
--- head/contrib/gcc/cp/parser.c        Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/cp/parser.c        Wed Nov 13 04:31:27 2013        
(r258081)
@@ -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_statem
   (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* 
   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* 
       /* 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* 
          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* 
          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 *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.  */
@@ -6257,7 +6278,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:
@@ -6522,7 +6543,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);
     }
 }
 
@@ -6533,14 +6554,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");
 
@@ -6576,11 +6605,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.  */
@@ -6591,8 +6622,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.  */
@@ -6611,7 +6662,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;
 
@@ -6789,7 +6840,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.  */
@@ -7031,13 +7082,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))
     {
@@ -7053,7 +7112,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);
     }
@@ -7072,7 +7131,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
@@ -18645,7 +18704,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);
@@ -18890,7 +18949,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);
@@ -18983,7 +19042,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)

Modified: head/contrib/gcc/cp/pt.c
==============================================================================
--- head/contrib/gcc/cp/pt.c    Wed Nov 13 03:50:31 2013        (r258080)
+++ head/contrib/gcc/cp/pt.c    Wed Nov 13 04:31:27 2013        (r258081)
@@ -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:

Modified: head/contrib/gcc/cp/semantics.c
==============================================================================
--- head/contrib/gcc/cp/semantics.c     Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/cp/semantics.c     Wed Nov 13 04:31:27 2013        
(r258081)
@@ -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);
 }
 

Modified: head/contrib/gcc/cp/typeck.c
==============================================================================
--- head/contrib/gcc/cp/typeck.c        Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/cp/typeck.c        Wed Nov 13 04:31:27 2013        
(r258081)
@@ -1690,17 +1690,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
@@ -2908,8 +2911,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;
@@ -2933,6 +2936,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);
 
@@ -6280,6 +6294,19 @@ convert_for_assignment (tree type, tree 
                 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);
 }
 

Modified: head/contrib/gcc/doc/invoke.texi
==============================================================================
--- head/contrib/gcc/doc/invoke.texi    Wed Nov 13 03:50:31 2013        
(r258080)
+++ head/contrib/gcc/doc/invoke.texi    Wed Nov 13 04:31:27 2013        
(r258081)
@@ -2212,9 +2212,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
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to