OSDN Git Service

2008-10-30 Catherine Moore <clm@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 9302182..84dea11 100644 (file)
@@ -342,10 +342,6 @@ int flag_isoc99;
 
 int flag_hosted = 1;
 
-/* Warn if main is suspicious.  */
-
-int warn_main;
-
 
 /* ObjC language option variables.  */
 
@@ -575,7 +571,7 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
-static tree handle_option_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
@@ -860,8 +856,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_error_attribute },
   { "error",                 1, 1, true,  false, false,
                              handle_error_attribute },
-  { "option",                 1, -1, true, false, false,
-                             handle_option_attribute },
+  { "target",                 1, -1, true, false, false,
+                             handle_target_attribute },
   { "optimize",               1, -1, true, false, false,
                              handle_optimize_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
@@ -987,37 +983,16 @@ fname_as_string (int pretty_p)
   return namep;
 }
 
-/* Expand DECL if it declares an entity not handled by the
-   common code.  */
-
-int
-c_expand_decl (tree decl)
-{
-  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
-    {
-      /* Let the back-end know about this variable.  */
-      if (!anon_aggr_type_p (TREE_TYPE (decl)))
-       emit_local_var (decl);
-      else
-       expand_anon_union_decl (decl, NULL_TREE,
-                               DECL_ANON_UNION_ELEMS (decl));
-    }
-  else
-    return 0;
-
-  return 1;
-}
-
-
 /* Return the VAR_DECL for a const char array naming the current
    function. If the VAR_DECL has not yet been created, create it
    now. RID indicates how it should be formatted and IDENTIFIER_NODE
    ID is its name (unfortunately C and C++ hold the RID values of
    keywords in different places, so we can't derive RID from ID in
-   this language independent code.  */
+   this language independent code. LOC is the location of the
+   function.  */
 
 tree
-fname_decl (unsigned int rid, tree id)
+fname_decl (location_t loc, unsigned int rid, tree id)
 {
   unsigned ix;
   tree decl = NULL_TREE;
@@ -1048,7 +1023,7 @@ fname_decl (unsigned int rid, tree id)
       input_location = saved_location;
     }
   if (!ix && !current_function_decl)
-    pedwarn (0, "%qD is not defined outside of function scope", decl);
+    pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
 
   return decl;
 }
@@ -1097,7 +1072,7 @@ fix_string_type (tree value)
           separate the %d from the 'C'.  'ISO' should not be
           translated, but it may be moved after 'C%d' in languages
           where modifiers follow nouns.  */
-       pedwarn (OPT_Woverlength_strings,
+       pedwarn (input_location, OPT_Woverlength_strings,
                 "string length %qd is greater than the length %qd "
                 "ISO C%d compilers are required to support",
                 nchars - 1, nchars_max, relevant_std);
@@ -1145,7 +1120,7 @@ constant_expression_warning (tree value)
          || TREE_CODE (value) == VECTOR_CST
          || TREE_CODE (value) == COMPLEX_CST)
       && TREE_OVERFLOW (value))
-    pedwarn (OPT_Woverflow, "overflow in constant expression");
+    pedwarn (input_location, OPT_Woverflow, "overflow in constant expression");
 }
 
 /* The same as above but print an unconditional error.  */
@@ -1316,31 +1291,6 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
   return false;
 }
 
-/* Print a warning about if (); or if () .. else; constructs
-   via the special empty statement node that we create.  INNER_THEN
-   and INNER_ELSE are the statement lists of the if and the else
-   block.  */
-
-void
-empty_if_body_warning (tree inner_then, tree inner_else)
-{
-  if (TREE_CODE (inner_then) == STATEMENT_LIST
-      && STATEMENT_LIST_TAIL (inner_then))
-    inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt;
-
-  if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST
-      && STATEMENT_LIST_TAIL (inner_else))
-    inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt;
-
-  if (IS_EMPTY_STMT (inner_then) && !inner_else)
-    warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
-             "in an %<if%> statement", EXPR_LOCUS (inner_then));
-
-  else if (inner_else && IS_EMPTY_STMT (inner_else))
-    warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
-             "in an %<else%> statement", EXPR_LOCUS (inner_else));
-}
-
 /* Warn for unlikely, improbable, or stupid DECL declarations
    of `main'.  */
 
@@ -1363,7 +1313,8 @@ check_main_parameter_types (tree decl)
        {
        case 1:
          if (TYPE_MAIN_VARIANT (type) != integer_type_node)
-           pedwarn (0, "first argument of %q+D should be %<int%>", decl);
+           pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>", 
+                   decl);
          break;
 
        case 2:
@@ -1371,8 +1322,8 @@ check_main_parameter_types (tree decl)
              || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
              || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                  != char_type_node))
-           pedwarn (0, "second argument of %q+D should be %<char **%>",
-                    decl);
+           pedwarn (input_location, OPT_Wmain, "second argument of %q+D should be %<char **%>",
+                   decl);
          break;
 
        case 3:
@@ -1380,8 +1331,8 @@ check_main_parameter_types (tree decl)
              || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
              || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                  != char_type_node))
-           pedwarn (0, "third argument of %q+D should probably be "
-                    "%<char **%>", decl);
+          pedwarn (input_location, OPT_Wmain, "third argument of %q+D should probably be "
+                   "%<char **%>", decl);
          break;
        }
    }
@@ -1390,7 +1341,7 @@ check_main_parameter_types (tree decl)
     argument because it's only mentioned in an appendix of the
     standard.  */
   if (argct > 0 && (argct < 2 || argct > 3))
-   pedwarn (0, "%q+D takes only zero or two arguments", decl);
+    pedwarn (input_location, OPT_Wmain, "%q+D takes only zero or two arguments", decl);
 }
 
 /* True if pointers to distinct types T1 and T2 can be converted to
@@ -1439,7 +1390,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
   if (emit_lax_note && !emitted_lax_note)
     {
       emitted_lax_note = true;
-      inform ("use -flax-vector-conversions to permit "
+      inform (input_location, "use -flax-vector-conversions to permit "
               "conversions between vectors with differing "
               "element types or numbers of subparts");
     }
@@ -1559,11 +1510,22 @@ conversion_warning (tree type, tree expr)
 {
   bool give_warning = false;
 
+  int i;
+  const int expr_num_operands = TREE_OPERAND_LENGTH (expr);
   tree expr_type = TREE_TYPE (expr);
 
   if (!warn_conversion && !warn_sign_conversion)
     return;
 
+  /* If any operand is artificial, then this expression was generated
+     by the compiler and we do not warn.  */
+  for (i = 0; i < expr_num_operands; i++)
+    {
+      tree op = TREE_OPERAND (expr, i);
+      if (op && DECL_P (op) && DECL_ARTIFICIAL (op))
+       return;
+    }
+
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:
@@ -1685,13 +1647,16 @@ conversion_warning (tree type, tree expr)
                                             TREE_OPERAND (expr, 1), 
                                             /* bitwise */1);
 
-             /* If one of the operands is a non-negative constant
-                that fits in the target type, then the type of the
-                other operand does not matter. */
              if (TREE_CODE (expr) == BIT_AND_EXPR)
                {
                  tree op0 = TREE_OPERAND (expr, 0);
                  tree op1 = TREE_OPERAND (expr, 1);
+                 bool unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+                 bool unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+                 /* If one of the operands is a non-negative constant
+                    that fits in the target type, then the type of the
+                    other operand does not matter. */
                  if ((TREE_CODE (op0) == INTEGER_CST
                       && int_fits_type_p (op0, c_common_signed_type (type))
                       && int_fits_type_p (op0, c_common_unsigned_type (type)))
@@ -1700,6 +1665,15 @@ conversion_warning (tree type, tree expr)
                          && int_fits_type_p (op1, 
                                              c_common_unsigned_type (type))))
                    return;
+                 /* If constant is unsigned and fits in the target
+                    type, then the result will also fit.  */
+                 else if ((TREE_CODE (op0) == INTEGER_CST
+                           && unsigned0 
+                           && int_fits_type_p (op0, type))
+                          || (TREE_CODE (op1) == INTEGER_CST
+                              && unsigned1
+                              && int_fits_type_p (op1, type)))
+                   return;
                }
            }
           /* Warn for integer types converted to smaller integer types.  */
@@ -2169,6 +2143,13 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
        return;
       }
 
+    case ADDR_EXPR:
+      x = TREE_OPERAND (x, 0);
+      if (DECL_P (x))
+       return;
+      writer = 0;
+      goto restart;
+
     default:
       /* For other expressions, simply recurse on their operands.
         Manual tail recursion for unary expressions.
@@ -2814,40 +2795,14 @@ c_register_builtin_type (tree type, const char* name)
 
   registered_builtin_types = tree_cons (0, type, registered_builtin_types);
 }
-
-\f
-/* Return the minimum number of bits needed to represent VALUE in a
-   signed or unsigned type, UNSIGNEDP says which.  */
-
-unsigned int
-min_precision (tree value, int unsignedp)
-{
-  int log;
-
-  /* If the value is negative, compute its negative minus 1.  The latter
-     adjustment is because the absolute value of the largest negative value
-     is one larger than the largest positive value.  This is equivalent to
-     a bit-wise negation, so use that operation instead.  */
-
-  if (tree_int_cst_sgn (value) < 0)
-    value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
-
-  /* Return the number of bits needed, taking into account the fact
-     that we need one more bit for a signed than unsigned type.  */
-
-  if (integer_zerop (value))
-    log = 0;
-  else
-    log = tree_floor_log2 (value);
-
-  return log + 1 + !unsignedp;
-}
 \f
 /* Print an error message for invalid operands to arith operation
-   CODE with TYPE0 for operand 0, and TYPE1 for operand 1.  */
+   CODE with TYPE0 for operand 0, and TYPE1 for operand 1.
+   LOCATION is the location of the message.  */
 
 void
-binary_op_error (enum tree_code code, tree type0, tree type1)
+binary_op_error (location_t location, enum tree_code code,
+                tree type0, tree type1)
 {
   const char *opname;
 
@@ -2898,8 +2853,9 @@ binary_op_error (enum tree_code code, tree type0, tree type1)
     default:
       gcc_unreachable ();
     }
-  error ("invalid operands to binary %s (have %qT and %qT)", opname,
-        type0, type1);
+  error_at (location,
+           "invalid operands to binary %s (have %qT and %qT)", opname,
+           type0, type1);
 }
 \f
 /* Subroutine of build_binary_op, used for comparison operations.
@@ -3265,19 +3221,19 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
-      pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
               "pointer of type %<void *%> used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
     {
-      pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
               "pointer to a function used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
     {
-      pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
               "pointer to member function used in arithmetic");
       size_exp = integer_one_node;
     }
@@ -3315,7 +3271,8 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
       /* Convert both subexpression types to the type of intop,
         because weird cases involving pointer arithmetic
         can result in a sum or difference with different type args.  */
-      ptrop = build_binary_op (subcode, ptrop,
+      ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
+                              subcode, ptrop,
                               convert (int_type, TREE_OPERAND (intop, 1)), 1);
       intop = convert (int_type, TREE_OPERAND (intop, 0));
     }
@@ -3331,7 +3288,8 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      Do this multiplication as signed, then convert to the appropriate
      type for the pointer operation.  */
   intop = convert (sizetype,
-                  build_binary_op (MULT_EXPR, intop,
+                  build_binary_op (EXPR_LOCATION (intop),
+                                   MULT_EXPR, intop,
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
@@ -3362,6 +3320,8 @@ decl_with_nonnull_addr_p (const_tree expr)
    have been validated to be of suitable type; otherwise, a bad
    diagnostic may result.
 
+   The EXPR is located at LOCATION.
+
    This preparation consists of taking the ordinary
    representation of an expression expr and producing a valid tree
    boolean expression describing whether expr is nonzero.  We could
@@ -3371,7 +3331,7 @@ decl_with_nonnull_addr_p (const_tree expr)
    The resulting type should always be `truthvalue_type_node'.  */
 
 tree
-c_common_truthvalue_conversion (tree expr)
+c_common_truthvalue_conversion (location_t location, tree expr)
 {
   switch (TREE_CODE (expr))
     {
@@ -3392,14 +3352,17 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
       return build2 (TREE_CODE (expr), truthvalue_type_node,
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)));
+                c_common_truthvalue_conversion (location, 
+                                                TREE_OPERAND (expr, 0)),
+                c_common_truthvalue_conversion (location,
+                                                TREE_OPERAND (expr, 1)));
 
     case TRUTH_NOT_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
       return build1 (TREE_CODE (expr), truthvalue_type_node,
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                c_common_truthvalue_conversion (location,
+                                                TREE_OPERAND (expr, 0)));
 
     case ERROR_MARK:
       return expr;
@@ -3420,7 +3383,7 @@ c_common_truthvalue_conversion (tree expr)
             : truthvalue_false_node;
 
     case FUNCTION_DECL:
-      expr = build_unary_op (ADDR_EXPR, expr, 0);
+      expr = build_unary_op (location, ADDR_EXPR, expr, 0);
       /* Fall through.  */
 
     case ADDR_EXPR:
@@ -3429,9 +3392,10 @@ c_common_truthvalue_conversion (tree expr)
        if (decl_with_nonnull_addr_p (inner))
          {
            /* Common Ada/Pascal programmer's mistake.  */
-           warning (OPT_Waddress,
-                    "the address of %qD will always evaluate as %<true%>",
-                    inner);
+           warning_at (location,
+                       OPT_Waddress,
+                       "the address of %qD will always evaluate as %<true%>",
+                       inner);
            return truthvalue_true_node;
          }
 
@@ -3451,17 +3415,20 @@ c_common_truthvalue_conversion (tree expr)
       }
 
     case COMPLEX_EXPR:
-      return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+      return build_binary_op (EXPR_LOCATION (expr),
+                             (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 0)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -3470,16 +3437,20 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build2 (COMPOUND_EXPR, truthvalue_type_node,
                       TREE_OPERAND (expr, 1),
-                      c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                      c_common_truthvalue_conversion 
+                       (location, TREE_OPERAND (expr, 0)));
       else
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (location,
+                                              TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       return fold_build3 (COND_EXPR, truthvalue_type_node,
                TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)));
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 2)));
 
     CASE_CONVERT:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -3490,7 +3461,8 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (location,
+                                              TREE_OPERAND (expr, 0));
       break;
 
     case MODIFY_EXPR:
@@ -3511,10 +3483,15 @@ c_common_truthvalue_conversion (tree expr)
     {
       tree t = save_expr (expr);
       return (build_binary_op
-             ((TREE_SIDE_EFFECTS (expr)
+             (EXPR_LOCATION (expr),
+              (TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion
+              (location,
+               build_unary_op (location, REALPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion
+              (location,
+               build_unary_op (location, IMAGPART_EXPR, t, 0)),
               0));
     }
 
@@ -3523,10 +3500,12 @@ c_common_truthvalue_conversion (tree expr)
       tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
                                          FCONST0 (TYPE_MODE
                                                   (TREE_TYPE (expr))));
-      return build_binary_op (NE_EXPR, expr, fixed_zero_node, 1);
+      return build_binary_op (EXPR_LOCATION (expr),
+                             NE_EXPR, expr, fixed_zero_node, 1);
     }
 
-  return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
+  return build_binary_op (EXPR_LOCATION (expr),
+                         NE_EXPR, expr, integer_zero_node, 1);
 }
 \f
 static void def_builtin_1  (enum built_in_function fncode,
@@ -3786,7 +3765,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
       if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
-           pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+           pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
                     "invalid application of %<sizeof%> to a function type");
           else if (!complain)
             return error_mark_node;
@@ -3799,7 +3778,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
     {
       if (type_code == VOID_TYPE
          && complain && (pedantic || warn_pointer_arith))
-       pedwarn (pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+       pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
                 "invalid application of %qs to a void type", op_name);
       else if (!complain)
         return error_mark_node;
@@ -4667,7 +4646,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
 
   /* Case ranges are a GNU extension.  */
   if (high_value)
-    pedwarn (OPT_pedantic, 
+    pedwarn (input_location, OPT_pedantic, 
             "range expressions in switch statements are non-standard");
 
   type = TREE_TYPE (cond);
@@ -4908,6 +4887,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
   for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
     {
       tree value = TREE_VALUE (chain);
+      if (TREE_CODE (value) == CONST_DECL)
+        value = DECL_INITIAL (value);
       node = splay_tree_lookup (cases, (splay_tree_key) value);
       if (node)
        {
@@ -4974,14 +4955,16 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
 }
 
 /* Finish an expression taking the address of LABEL (an
-   IDENTIFIER_NODE).  Returns an expression for the address.  */
+   IDENTIFIER_NODE).  Returns an expression for the address.
+
+   LOC is the location for the expression returned.  */
 
 tree
-finish_label_address_expr (tree label)
+finish_label_address_expr (tree label, location_t loc)
 {
   tree result;
 
-  pedwarn (OPT_pedantic, "taking the address of a label is non-standard");
+  pedwarn (input_location, OPT_pedantic, "taking the address of a label is non-standard");
 
   if (label == error_mark_node)
     return error_mark_node;
@@ -4996,6 +4979,7 @@ finish_label_address_expr (tree label)
       /* The current function in not necessarily uninlinable.
         Computed gotos are incompatible with inlining, but the value
         here could be used only in a diagnostic, for example.  */
+      protected_set_expr_location (result, loc);
     }
 
   return result;
@@ -5231,34 +5215,8 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                   name, "cold");
          *no_add_attrs = true;
        }
-      else
-       {
-         tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
-         /* If we are not at -O3, but are optimizing, turn on -O3
-            optimizations just for this one function.  */
-         if (((optimize > 0 && optimize < 3) || optimize_size)
-             && targetm.target_option.hot_attribute_sets_optimization
-             && (!old_opts || old_opts == optimization_default_node))
-           {
-             /* Create the hot optimization node if needed.  */
-             if (!optimization_hot_node)
-               {
-                 struct cl_optimization current_options;
-                 static const char *os_argv[] = { NULL, "-O3", NULL };
-
-                 cl_optimization_save (&current_options);
-                 decode_options (2, os_argv);
-                 optimization_hot_node = build_optimization_node ();
-                 cl_optimization_restore (&current_options);
-               }
-
-             DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
-               = optimization_hot_node;
-           }
-         /* Most of the rest of the hot processing is done later with
-            lookup_attribute.  */
-       }
+      /* Most of the rest of the hot processing is done later with
+        lookup_attribute.  */
     }
   else
     {
@@ -5283,34 +5241,8 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                   name, "hot");
          *no_add_attrs = true;
        }
-      else
-       {
-         tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
-
-         /* If we are optimizing, but not optimizing for space, turn on -Os
-            optimizations just for this one function.  */
-         if (optimize && !optimize_size
-             && targetm.target_option.cold_attribute_sets_optimization
-             && (!old_opts || old_opts == optimization_default_node))
-           {
-             /* Create the cold optimization node if needed.  */
-             if (!optimization_cold_node)
-               {
-                 struct cl_optimization current_options;
-                 static const char *os_argv[] = { NULL, "-Os", NULL };
-
-                 cl_optimization_save (&current_options);
-                 decode_options (2, os_argv);
-                 optimization_cold_node = build_optimization_node ();
-                 cl_optimization_restore (&current_options);
-               }
-
-             DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
-               = optimization_cold_node;
-           }
-         /* Most of the rest of the cold processing is done later with
-            lookup_attribute.  */
-       }
+      /* Most of the rest of the cold processing is done later with
+        lookup_attribute.  */
     }
   else
     {
@@ -6148,7 +6080,9 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   /* We must ignore the attribute when it is associated with
      local-scoped decls, since attribute alias is ignored and many
      such symbols do not even have a DECL_WEAK field.  */
-  if (decl_function_context (*node) || current_function_decl)
+  if (decl_function_context (*node)
+      || current_function_decl
+      || (TREE_CODE (*node) != VAR_DECL && TREE_CODE (*node) != FUNCTION_DECL))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
@@ -7009,11 +6943,10 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
   return NULL_TREE;
 }
 
-/* For handling "option" attribute. arguments as in
-   struct attribute_spec.handler.  */
+/* Handle a "target" attribute.  */
 
 static tree
-handle_option_attribute (tree *node, tree name, tree args, int flags,
+handle_target_attribute (tree *node, tree name, tree args, int flags,
                         bool *no_add_attrs)
 {
   /* Ensure we have a function type.  */
@@ -7022,14 +6955,6 @@ handle_option_attribute (tree *node, tree name, tree args, int flags,
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
-  else if (targetm.target_option.valid_attribute_p
-          == default_target_option_valid_attribute_p)
-    {
-      warning (OPT_Wattributes,
-              "%qE attribute is not supported on this machine",
-              name);
-      *no_add_attrs = true;
-    }
   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
                                                      flags))
     *no_add_attrs = true;
@@ -7663,6 +7588,7 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       return error_mark_node;
 
     case CALL_EXPR:
+    case TARGET_EXPR:
       error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
       return error_mark_node;
 
@@ -8122,94 +8048,132 @@ warn_array_subscript_with_type_char (tree index)
 /* 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.  */
+   operator used to combine expressions ARG_LEFT and ARG_RIGHT, which
+   before folding had 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 or unary 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)
+warn_about_parentheses (enum tree_code code,
+                       enum tree_code code_left, tree ARG_UNUSED (arg_left),
+                       enum tree_code code_right, tree arg_right)
 {
   if (!warn_parentheses)
     return;
 
-  if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+  /* This macro tests that the expression ARG with original tree code
+     CODE appears to be a boolean expression. or the result of folding a
+     boolean expression.  */
+#define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG)                             \
+       (truth_value_p (TREE_CODE (ARG))                                    \
+        || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE                     \
+        /* Folding may create 0 or 1 integers from other expressions.  */  \
+        || ((CODE) != INTEGER_CST                                          \
+            && (integer_onep (ARG) || integer_zerop (ARG))))
+
+  switch (code) 
     {
-      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+    case LSHIFT_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around + or - inside shift");
-    }
+                "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<-%> inside %<<<%>");
+      return;
 
-  if (code == TRUTH_ORIF_EXPR)
-    {
-      if (code_left == TRUTH_ANDIF_EXPR
-         || code_right == TRUTH_ANDIF_EXPR)
+    case RSHIFT_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around && within ||");
-    }
+                "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<-%> inside %<>>%>");
+      return;
 
-  if (code == BIT_IOR_EXPR)
-    {
+    case TRUTH_ORIF_EXPR:
+      if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<&&%> within %<||%>");
+      return;
+
+    case 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 |");
+                "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)
+      else 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 |");
-    }
+                "suggest parentheses around comparison in operand of %<|%>");
+      /* Check cases like !x | y */
+      else if (code_left == TRUTH_NOT_EXPR
+              && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+       warning (OPT_Wparentheses, "suggest parentheses around operand of"
+                "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
+      return;
 
-  if (code == BIT_XOR_EXPR)
-    {
+    case 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 ^");
+                "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)
+      else 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 ^");
-    }
+                "suggest parentheses around comparison in operand of %<^%>");
+      return;
 
-  if (code == BIT_AND_EXPR)
-    {
-      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+    case BIT_AND_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around + or - in operand of &");
+                "suggest parentheses around %<+%> in operand of %<&%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<-%> in operand of %<&%>");
       /* Check cases like x&y==z */
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-         || TREE_CODE_CLASS (code_right) == tcc_comparison)
+      else 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 &");
-    }
+                "suggest parentheses around comparison in operand of %<&%>");
+      /* Check cases like !x & y */
+      else if (code_left == TRUTH_NOT_EXPR
+              && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+       warning (OPT_Wparentheses, "suggest parentheses around operand of"
+                "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
+      return;
 
-  if (code == EQ_EXPR || code == NE_EXPR)
-    {
+    case EQ_EXPR:
       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 %s",
-                 code == EQ_EXPR ? "==" : "!=");
-    }
-  else if (TREE_CODE_CLASS (code) == tcc_comparison)
-    {
-      if ((TREE_CODE_CLASS (code_left) == tcc_comparison
-          && code_left != NE_EXPR && code_left != EQ_EXPR)
-         || (TREE_CODE_CLASS (code_right) == tcc_comparison
-             && code_right != NE_EXPR && code_right != EQ_EXPR))
-       warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
+                "suggest parentheses around comparison in operand of %<==%>");
+      return;
+    case NE_EXPR:
+      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 %<!=%>");
+      return;
+
+    default:
+      if (TREE_CODE_CLASS (code) == tcc_comparison
+          && ((TREE_CODE_CLASS (code_left) == tcc_comparison
+               && code_left != NE_EXPR && code_left != EQ_EXPR)
+              || (TREE_CODE_CLASS (code_right) == tcc_comparison
+                  && code_right != NE_EXPR && code_right != EQ_EXPR)))
+       warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
                 "have their mathematical meaning");
+      return;
     }
+#undef NOT_A_BOOLEAN_EXPR_P
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */
@@ -8230,10 +8194,11 @@ warn_for_unused_label (tree label)
 struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
 #endif
 
-/* Warn for division by zero according to the value of DIVISOR.  */
+/* Warn for division by zero according to the value of DIVISOR.  LOC
+   is the location of the division operator.  */
 
 void
-warn_for_div_by_zero (tree divisor)
+warn_for_div_by_zero (location_t loc, tree divisor)
 {
   /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning
      about division by zero.  Do not issue a warning if DIVISOR has a
@@ -8241,20 +8206,23 @@ warn_for_div_by_zero (tree divisor)
      generating a NaN.  */
   if (skip_evaluation == 0
       && (integer_zerop (divisor) || fixed_zerop (divisor)))
-    warning (OPT_Wdiv_by_zero, "division by zero");
+    warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
 }
 
 /* Subroutine of build_binary_op. Give warnings for comparisons
    between signed and unsigned quantities that may fail. Do the
    checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
    so that casts will be considered, but default promotions won't
-   be. 
+   be.
+
+   LOCATION is the location of the comparison operator.
 
    The arguments of this function map directly to local variables
    of build_binary_op.  */
 
 void 
-warn_for_sign_compare (tree orig_op0, tree orig_op1, 
+warn_for_sign_compare (location_t location,
+                      tree orig_op0, tree orig_op1, 
                       tree op0, tree op1, 
                       tree result_type, enum tree_code resultcode)
 {
@@ -8269,8 +8237,9 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
       && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
       != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
     {
-      warning (OPT_Wsign_compare, "comparison between types %qT and %qT",
-               TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
+      warning_at (location,
+                 OPT_Wsign_compare, "comparison between types %qT and %qT",
+                 TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
     }
 
   /* Do not warn if the comparison is being done in a signed type,
@@ -8316,8 +8285,9 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
                                    c_common_signed_type (result_type)))
         /* OK */;
       else 
-        warning (OPT_Wsign_compare, 
-                 "comparison between signed and unsigned integer expressions");
+        warning_at (location,
+                   OPT_Wsign_compare, 
+                   "comparison between signed and unsigned integer expressions");
     }
   
   /* Warn if two unsigned values are being compared in a size larger
@@ -8370,8 +8340,8 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
                    warning (OPT_Wsign_compare, 
                             "promoted ~unsigned is always non-zero");
                  else
-                   warning (OPT_Wsign_compare, 
-                            "comparison of promoted ~unsigned with constant");
+                   warning_at (location, OPT_Wsign_compare, 
+                               "comparison of promoted ~unsigned with constant");
                }
             }
         }
@@ -8380,7 +8350,7 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
                    < TYPE_PRECISION (result_type))
                && (TYPE_PRECISION (TREE_TYPE (op1))
                    < TYPE_PRECISION (result_type)))
-        warning (OPT_Wsign_compare, 
+        warning_at (location, OPT_Wsign_compare,
                  "comparison of promoted ~unsigned with unsigned");
     }
 }