OSDN Git Service

2008-10-30 Catherine Moore <clm@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index dac29ea..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 *);
@@ -598,7 +594,7 @@ static int resort_field_decl_cmp (const void *, const void *);
    If -fno-asm is used, D_ASM is added to the mask.  If
    -fno-gnu-keywords is used, D_EXT is added.  If -fno-asm and C in
    C89 mode, D_EXT89 is added for both -fno-asm and -fno-gnu-keywords.
-   In C with -Wcxx-compat, we warn if D_CXXWARN is set.  */
+   In C with -Wc++-compat, we warn if D_CXXWARN is set.  */
 
 const struct c_common_resword c_common_reswords[] =
 {
@@ -665,44 +661,44 @@ const struct c_common_resword c_common_reswords[] =
   { "__volatile__",    RID_VOLATILE,   0 },
   { "asm",             RID_ASM,        D_ASM },
   { "auto",            RID_AUTO,       0 },
-  { "bool",            RID_BOOL,       D_CXXONLY },
+  { "bool",            RID_BOOL,       D_CXXONLY | D_CXXWARN },
   { "break",           RID_BREAK,      0 },
   { "case",            RID_CASE,       0 },
-  { "catch",           RID_CATCH,      D_CXX_OBJC },
+  { "catch",           RID_CATCH,      D_CXX_OBJC | D_CXXWARN },
   { "char",            RID_CHAR,       0 },
-  { "char16_t",                RID_CHAR16,     D_CXXONLY | D_CXX0X },
-  { "char32_t",                RID_CHAR32,     D_CXXONLY | D_CXX0X },
-  { "class",           RID_CLASS,      D_CXX_OBJC },
+  { "char16_t",                RID_CHAR16,     D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "char32_t",                RID_CHAR32,     D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "class",           RID_CLASS,      D_CXX_OBJC | D_CXXWARN },
   { "const",           RID_CONST,      0 },
   { "const_cast",      RID_CONSTCAST,  D_CXXONLY | D_CXXWARN },
   { "continue",                RID_CONTINUE,   0 },
-  { "decltype",         RID_DECLTYPE,   D_CXXONLY | D_CXX0X },
+  { "decltype",         RID_DECLTYPE,   D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "default",         RID_DEFAULT,    0 },
-  { "delete",          RID_DELETE,     D_CXXONLY },
+  { "delete",          RID_DELETE,     D_CXXONLY | D_CXXWARN },
   { "do",              RID_DO,         0 },
   { "double",          RID_DOUBLE,     0 },
   { "dynamic_cast",    RID_DYNCAST,    D_CXXONLY | D_CXXWARN },
   { "else",            RID_ELSE,       0 },
   { "enum",            RID_ENUM,       0 },
-  { "explicit",                RID_EXPLICIT,   D_CXXONLY },
-  { "export",          RID_EXPORT,     D_CXXONLY },
+  { "explicit",                RID_EXPLICIT,   D_CXXONLY | D_CXXWARN },
+  { "export",          RID_EXPORT,     D_CXXONLY | D_CXXWARN },
   { "extern",          RID_EXTERN,     0 },
-  { "false",           RID_FALSE,      D_CXXONLY },
+  { "false",           RID_FALSE,      D_CXXONLY | D_CXXWARN },
   { "float",           RID_FLOAT,      0 },
   { "for",             RID_FOR,        0 },
-  { "friend",          RID_FRIEND,     D_CXXONLY },
+  { "friend",          RID_FRIEND,     D_CXXONLY | D_CXXWARN },
   { "goto",            RID_GOTO,       0 },
   { "if",              RID_IF,         0 },
   { "inline",          RID_INLINE,     D_EXT89 },
   { "int",             RID_INT,        0 },
   { "long",            RID_LONG,       0 },
   { "mutable",         RID_MUTABLE,    D_CXXONLY | D_CXXWARN },
-  { "namespace",       RID_NAMESPACE,  D_CXXONLY },
-  { "new",             RID_NEW,        D_CXXONLY },
-  { "operator",                RID_OPERATOR,   D_CXXONLY },
-  { "private",         RID_PRIVATE,    D_CXX_OBJC },
-  { "protected",       RID_PROTECTED,  D_CXX_OBJC },
-  { "public",          RID_PUBLIC,     D_CXX_OBJC },
+  { "namespace",       RID_NAMESPACE,  D_CXXONLY | D_CXXWARN },
+  { "new",             RID_NEW,        D_CXXONLY | D_CXXWARN },
+  { "operator",                RID_OPERATOR,   D_CXXONLY | D_CXXWARN },
+  { "private",         RID_PRIVATE,    D_CXX_OBJC | D_CXXWARN },
+  { "protected",       RID_PROTECTED,  D_CXX_OBJC | D_CXXWARN },
+  { "public",          RID_PUBLIC,     D_CXX_OBJC | D_CXXWARN },
   { "register",                RID_REGISTER,   0 },
   { "reinterpret_cast",        RID_REINTCAST,  D_CXXONLY | D_CXXWARN },
   { "restrict",                RID_RESTRICT,   D_CONLY | D_C99 },
@@ -715,19 +711,19 @@ const struct c_common_resword c_common_reswords[] =
   { "static_cast",     RID_STATCAST,   D_CXXONLY | D_CXXWARN },
   { "struct",          RID_STRUCT,     0 },
   { "switch",          RID_SWITCH,     0 },
-  { "template",                RID_TEMPLATE,   D_CXXONLY },
-  { "this",            RID_THIS,       D_CXXONLY },
-  { "throw",           RID_THROW,      D_CXX_OBJC },
-  { "true",            RID_TRUE,       D_CXXONLY },
-  { "try",             RID_TRY,        D_CXX_OBJC },
+  { "template",                RID_TEMPLATE,   D_CXXONLY | D_CXXWARN },
+  { "this",            RID_THIS,       D_CXXONLY | D_CXXWARN },
+  { "throw",           RID_THROW,      D_CXX_OBJC | D_CXXWARN },
+  { "true",            RID_TRUE,       D_CXXONLY | D_CXXWARN },
+  { "try",             RID_TRY,        D_CXX_OBJC | D_CXXWARN },
   { "typedef",         RID_TYPEDEF,    0 },
-  { "typename",                RID_TYPENAME,   D_CXXONLY },
-  { "typeid",          RID_TYPEID,     D_CXXONLY },
+  { "typename",                RID_TYPENAME,   D_CXXONLY | D_CXXWARN },
+  { "typeid",          RID_TYPEID,     D_CXXONLY | D_CXXWARN },
   { "typeof",          RID_TYPEOF,     D_ASM | D_EXT },
   { "union",           RID_UNION,      0 },
   { "unsigned",                RID_UNSIGNED,   0 },
-  { "using",           RID_USING,      D_CXXONLY },
-  { "virtual",         RID_VIRTUAL,    D_CXXONLY },
+  { "using",           RID_USING,      D_CXXONLY | D_CXXWARN },
+  { "virtual",         RID_VIRTUAL,    D_CXXONLY | D_CXXWARN },
   { "void",            RID_VOID,       0 },
   { "volatile",                RID_VOLATILE,   0 },
   { "wchar_t",         RID_WCHAR,      D_CXXONLY },
@@ -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,39 +1510,74 @@ conversion_warning (tree type, tree expr)
 {
   bool give_warning = false;
 
-  unsigned int formal_prec = TYPE_PRECISION (type);
+  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 (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+  /* 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:
+    case NE_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_NOT_EXPR:
+      /* Conversion from boolean to a signed:1 bit-field (which only
+        can hold the values 0 and -1) doesn't lose information - but
+        it does change the value.  */
+      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) 
+       warning (OPT_Wconversion,
+                 "conversion to %qT from boolean expression", type);
+      return;
+
+    case REAL_CST:
+    case INTEGER_CST:
+
       /* Warn for real constant that is not an exact integer converted
          to integer type.  */
-      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+      if (TREE_CODE (expr_type) == REAL_TYPE
           && TREE_CODE (type) == INTEGER_TYPE)
         {
-          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
             give_warning = true;
         }
       /* Warn for an integer constant that does not fit into integer type.  */
-      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == INTEGER_TYPE
                && !int_fits_type_p (expr, type))
         {
-          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type) 
+             && tree_int_cst_sgn (expr) < 0)
            warning (OPT_Wsign_conversion,
                     "negative integer implicitly converted to unsigned type");
-          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
-           warning (OPT_Wsign_conversion,
-                    "conversion of unsigned constant value to negative integer");
+          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
+           warning (OPT_Wsign_conversion,  "conversion of unsigned constant "
+                    "value to negative integer");
          else
            give_warning = true;
         }
       else if (TREE_CODE (type) == REAL_TYPE)
         {
           /* Warn for an integer constant that does not fit into real type.  */
-          if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE)
+          if (TREE_CODE (expr_type) == INTEGER_TYPE)
             {
               REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1599,8 +1585,8 @@ conversion_warning (tree type, tree expr)
             }
           /* Warn for a real constant that does not fit into a smaller
              real type.  */
-          else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-                   && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+          else if (TREE_CODE (expr_type) == REAL_TYPE
+                   && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
             {
               REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1611,11 +1597,31 @@ conversion_warning (tree type, tree expr)
       if (give_warning)
         warning (OPT_Wconversion,
                  "conversion to %qT alters %qT constant value",
-                 type, TREE_TYPE (expr));
-    }
-  else /* 'expr' is not a constant.  */
-    {
-      tree expr_type = TREE_TYPE (expr);
+                 type, expr_type);
+
+      return;
+
+    case COND_EXPR:
+      {
+       /* In case of COND_EXPR, if both operands are constants or
+          COND_EXPR, then we do not care about the type of COND_EXPR,
+          only about the conversion of each operand.  */
+       tree op1 = TREE_OPERAND (expr, 1);
+       tree op2 = TREE_OPERAND (expr, 2);
+
+       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST 
+            || TREE_CODE (op1) == COND_EXPR)
+           && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
+               || TREE_CODE (op2) == COND_EXPR))
+         {
+           conversion_warning (type, op1);
+           conversion_warning (type, op2);
+           return;
+         }
+       /* Fall through.  */
+      }
+
+    default: /* 'expr' is not a constant.  */
 
       /* Warn for real types converted to integer types.  */
       if (TREE_CODE (expr_type) == REAL_TYPE
@@ -1631,46 +1637,59 @@ conversion_warning (tree type, tree expr)
 
          /* Don't warn for short y; short x = ((int)y & 0xff);  */
          if (TREE_CODE (expr) == BIT_AND_EXPR 
-             || TREE_CODE (expr) == BIT_IOR_EXPR 
+               || TREE_CODE (expr) == BIT_IOR_EXPR 
              || TREE_CODE (expr) == BIT_XOR_EXPR)
            {
-           /* It both args were extended from a shortest type, use
-              that type if that is safe.  */
+             /* If both args were extended from a shortest type,
+                use that type if that is safe.  */
              expr_type = shorten_binary_op (expr_type, 
                                             TREE_OPERAND (expr, 0), 
                                             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)))
                      || (TREE_CODE (op1) == INTEGER_CST
-                      && int_fits_type_p (op1, c_common_signed_type (type))
-                      && int_fits_type_p (op1, c_common_unsigned_type (type))))
+                         && int_fits_type_p (op1, c_common_signed_type (type))
+                         && 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.  */
-          if (formal_prec < TYPE_PRECISION (expr_type)) 
+         if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) 
            give_warning = true;
 
          /* When they are the same width but different signedness,
             then the value may change.  */
-         else if ((formal_prec == TYPE_PRECISION (expr_type)
+         else if ((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
                    && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type))
                   /* Even when converted to a bigger type, if the type is
                      unsigned but expr is signed, then negative values
                      will be changed.  */
                   || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
-           warning (OPT_Wsign_conversion,
-                    "conversion to %qT from %qT may change the sign of the result",
+           warning (OPT_Wsign_conversion, "conversion to %qT from %qT "
+                    "may change the sign of the result",
                     type, expr_type);
         }
 
@@ -1682,8 +1701,10 @@ conversion_warning (tree type, tree expr)
         {
           tree type_low_bound = TYPE_MIN_VALUE (expr_type);
           tree type_high_bound = TYPE_MAX_VALUE (expr_type);
-          REAL_VALUE_TYPE real_low_bound = real_value_from_int_cst (0, type_low_bound);
-          REAL_VALUE_TYPE real_high_bound = real_value_from_int_cst (0, type_high_bound);
+          REAL_VALUE_TYPE real_low_bound 
+           = real_value_from_int_cst (0, type_low_bound);
+          REAL_VALUE_TYPE real_high_bound 
+           = real_value_from_int_cst (0, type_high_bound);
 
           if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
               || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
@@ -1693,7 +1714,7 @@ conversion_warning (tree type, tree expr)
       /* Warn for real types converted to smaller real types.  */
       else if (TREE_CODE (expr_type) == REAL_TYPE
                && TREE_CODE (type) == REAL_TYPE
-               && formal_prec < TYPE_PRECISION (expr_type))
+               && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
         give_warning = true;
 
 
@@ -1902,8 +1923,10 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
          && DECL_NAME (list->expr))
        {
          warned_ids = new_tlist (warned_ids, written, NULL_TREE);
-         warning (OPT_Wsequence_point, "operation on %qE may be undefined",
-                  list->expr);
+         warning_at (EXPR_HAS_LOCATION (writer)
+                     ? EXPR_LOCATION (writer) : input_location,
+                     OPT_Wsequence_point, "operation on %qE may be undefined",
+                     list->expr);
        }
       list = list->next;
     }
@@ -2120,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.
@@ -2765,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;
 
@@ -2849,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.
@@ -3216,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;
     }
@@ -3266,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));
     }
@@ -3282,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.  */
@@ -3313,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
@@ -3322,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))
     {
@@ -3343,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;
@@ -3371,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:
@@ -3380,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;
          }
 
@@ -3402,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:
@@ -3421,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,
@@ -3441,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:
@@ -3462,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));
     }
 
@@ -3474,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,
@@ -3737,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;
@@ -3750,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;
@@ -4618,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);
@@ -4859,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)
        {
@@ -4925,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;
@@ -4947,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;
@@ -5182,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
     {
@@ -5234,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
     {
@@ -6099,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;
@@ -6960,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.  */
@@ -6973,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;
@@ -7544,15 +7518,8 @@ c_warn_unused_result (gimple_seq seq)
          /* This is a naked call, as opposed to a GIMPLE_CALL with an
             LHS.  All calls whose value is ignored should be
             represented like this.  Look for the attribute.  */
-         fdecl = gimple_call_fn (g);
-         if (TREE_CODE (fdecl) == FUNCTION_DECL)
-           ftype = TREE_TYPE (fdecl);
-         else
-           {
-             ftype = TREE_TYPE (fdecl);
-             /* Look past pointer-to-function to the function type itself.  */
-             ftype = TREE_TYPE (ftype);
-           }
+         fdecl = gimple_call_fndecl (g);
+         ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
 
          if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
            {
@@ -7621,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;
 
@@ -8080,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.  */
@@ -8188,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
@@ -8199,7 +8206,153 @@ 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.
+
+   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 (location_t location,
+                      tree orig_op0, tree orig_op1, 
+                      tree op0, tree op1, 
+                      tree result_type, enum tree_code resultcode)
+{
+  int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+  int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
+  int unsignedp0, unsignedp1;
+  
+  /* In C++, check for comparison of different enum types.  */
+  if (c_dialect_cxx()
+      && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
+      && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
+      && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
+      != TYPE_MAIN_VARIANT (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,
+     since the signed type will only be chosen if it can represent
+     all the values of the unsigned type.  */
+  if (!TYPE_UNSIGNED (result_type))
+    /* OK */;
+  /* Do not warn if both operands are unsigned.  */
+  else if (op0_signed == op1_signed)
+    /* OK */;
+  else
+    {
+      tree sop, uop;
+      bool ovf;
+      
+      if (op0_signed)
+        sop = orig_op0, uop = orig_op1;
+      else 
+        sop = orig_op1, uop = orig_op0;
+
+      STRIP_TYPE_NOPS (sop); 
+      STRIP_TYPE_NOPS (uop);
+
+      /* Do not warn if the signed quantity is an unsuffixed integer
+         literal (or some static constant expression involving such
+         literals or a conditional expression involving such literals)
+         and it is non-negative.  */
+      if (tree_expr_nonnegative_warnv_p (sop, &ovf))
+        /* OK */;
+      /* Do not warn if the comparison is an equality operation, the
+         unsigned quantity is an integral constant, and it would fit
+         in the result if the result were signed.  */
+      else if (TREE_CODE (uop) == INTEGER_CST
+               && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
+               && int_fits_type_p (uop, c_common_signed_type (result_type)))
+        /* OK */;
+      /* In C, do not warn if the unsigned quantity is an enumeration
+         constant and its maximum value would fit in the result if the
+         result were signed.  */
+      else if (!c_dialect_cxx() && TREE_CODE (uop) == INTEGER_CST
+               && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
+               && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
+                                   c_common_signed_type (result_type)))
+        /* OK */;
+      else 
+        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
+     than their original size, and one (and only one) is the result of
+     a `~' operator.  This comparison will always fail.
+     
+     Also warn if one operand is a constant, and the constant does not
+     have all bits set that are set in the ~ operand when it is
+     extended.  */
+
+  op0 = get_narrower (op0, &unsignedp0);
+  op1 = get_narrower (op1, &unsignedp1);
+  
+  if ((TREE_CODE (op0) == BIT_NOT_EXPR)
+      ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
+    {
+      if (TREE_CODE (op0) == BIT_NOT_EXPR)
+       op0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
+      if (TREE_CODE (op1) == BIT_NOT_EXPR)
+       op1 = get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
+
+      if (host_integerp (op0, 0) || host_integerp (op1, 0))
+        {
+          tree primop;
+          HOST_WIDE_INT constant, mask;
+          int unsignedp;
+          unsigned int bits;
+          
+          if (host_integerp (op0, 0))
+            {
+              primop = op1;
+              unsignedp = unsignedp1;
+              constant = tree_low_cst (op0, 0);
+            }
+          else
+            {
+              primop = op0;
+              unsignedp = unsignedp0;
+              constant = tree_low_cst (op1, 0);
+            }
+          
+          bits = TYPE_PRECISION (TREE_TYPE (primop));
+          if (bits < TYPE_PRECISION (result_type)
+              && bits < HOST_BITS_PER_LONG && unsignedp)
+            {
+              mask = (~ (HOST_WIDE_INT) 0) << bits;
+              if ((mask & constant) != mask)
+               {
+                 if (constant == 0)
+                   warning (OPT_Wsign_compare, 
+                            "promoted ~unsigned is always non-zero");
+                 else
+                   warning_at (location, OPT_Wsign_compare, 
+                               "comparison of promoted ~unsigned with constant");
+               }
+            }
+        }
+      else if (unsignedp0 && unsignedp1
+               && (TYPE_PRECISION (TREE_TYPE (op0))
+                   < TYPE_PRECISION (result_type))
+               && (TYPE_PRECISION (TREE_TYPE (op1))
+                   < TYPE_PRECISION (result_type)))
+        warning_at (location, OPT_Wsign_compare,
+                 "comparison of promoted ~unsigned with unsigned");
+    }
 }
 
 #include "gt-c-common.h"