OSDN Git Service

* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Factor
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 8c9e48c..43b2c13 100644 (file)
@@ -1,6 +1,7 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -32,7 +33,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "varray.h"
 #include "expr.h"
 #include "c-common.h"
 #include "varray.h"
 #include "expr.h"
 #include "c-common.h"
-#include "diagnostic.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "cpplib.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "cpplib.h"
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "c-tree.h"
 #include "toplev.h"
 #include "tree-inline.h"
 #include "c-tree.h"
 #include "toplev.h"
+#include "diagnostic.h"
 #include "tree-iterator.h"
 #include "hashtab.h"
 #include "tree-mudflap.h"
 #include "tree-iterator.h"
 #include "hashtab.h"
 #include "tree-mudflap.h"
@@ -50,63 +51,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "target-def.h"
 #include "gimple.h"
 #include "fixed-value.h"
 #include "target-def.h"
 #include "gimple.h"
 #include "fixed-value.h"
+#include "libfuncs.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
-/* We let tm.h override the types used here, to handle trivial differences
-   such as the choice of unsigned int or long unsigned int for size_t.
-   When machines start needing nontrivial differences in the size type,
-   it would be best to do something here to figure out automatically
-   from other information what type to use.  */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PID_TYPE
-#define PID_TYPE "int"
-#endif
-
-#ifndef CHAR16_TYPE
-#define CHAR16_TYPE "short unsigned int"
-#endif
-
-#ifndef CHAR32_TYPE
-#define CHAR32_TYPE "unsigned int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-
-/* WCHAR_TYPE gets overridden by -fshort-wchar.  */
-#define MODIFIED_WCHAR_TYPE \
-       (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WINT_TYPE
-#define WINT_TYPE "unsigned int"
-#endif
-
-#ifndef INTMAX_TYPE
-#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE)    \
-                    ? "int"                                    \
-                    : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
-                       ? "long int"                            \
-                       : "long long int"))
-#endif
-
-#ifndef UINTMAX_TYPE
-#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE)   \
-                    ? "unsigned int"                           \
-                    : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
-                       ? "long unsigned int"                   \
-                       : "long long unsigned int"))
-#endif
-
 /* The following symbols are subsumed in the c_global_trees array, and
    listed here individually for documentation purposes.
 
 /* The following symbols are subsumed in the c_global_trees array, and
    listed here individually for documentation purposes.
 
@@ -129,8 +77,6 @@ cpp_reader *parse_in;                /* Declared in c-pragma.h.  */
        tree unsigned_char_type_node;
        tree signed_char_type_node;
        tree wchar_type_node;
        tree unsigned_char_type_node;
        tree signed_char_type_node;
        tree wchar_type_node;
-       tree signed_wchar_type_node;
-       tree unsigned_wchar_type_node;
 
        tree char16_type_node;
        tree char32_type_node;
 
        tree char16_type_node;
        tree char32_type_node;
@@ -473,6 +419,11 @@ int flag_enforce_eh_specs = 1;
 
 int flag_threadsafe_statics = 1;
 
 
 int flag_threadsafe_statics = 1;
 
+/* Nonzero if we want to pretty-print template specializations as the
+   template signature followed by the arguments.  */
+
+int flag_pretty_templates = 1;
+
 /* Nonzero means warn about implicit declarations.  */
 
 int warn_implicit = 1;
 /* Nonzero means warn about implicit declarations.  */
 
 int warn_implicit = 1;
@@ -489,11 +440,15 @@ int max_tinst_depth = 500;
    type names and storage classes.  It is indexed by a RID_... value.  */
 tree *ridpointers;
 
    type names and storage classes.  It is indexed by a RID_... value.  */
 tree *ridpointers;
 
-tree (*make_fname_decl) (tree, int);
+tree (*make_fname_decl) (location_t, tree, int);
+
+/* Nonzero means don't warn about problems that occur when the code is
+   executed.  */
+int c_inhibit_evaluation_warnings;
 
 
-/* Nonzero means the expression being parsed will never be evaluated.
-   This is a count, since unevaluated expressions can nest.  */
-int skip_evaluation;
+/* Whether lexing has been completed, so subsequent preprocessor
+   errors should use the compiler's input_location.  */
+bool done_lexing = false;
 
 /* Information about how a function name is generated.  */
 struct fname_var_t
 
 /* Information about how a function name is generated.  */
 struct fname_var_t
@@ -516,6 +471,7 @@ const struct fname_var_t fname_vars[] =
   {NULL, 0, 0},
 };
 
   {NULL, 0, 0},
 };
 
+static tree c_fully_fold_internal (tree expr, bool, bool *, bool *);
 static tree check_case_value (tree);
 static bool check_case_bounds (tree, tree, tree *, tree *);
 
 static tree check_case_value (tree);
 static bool check_case_bounds (tree, tree, tree *, tree *);
 
@@ -600,6 +556,7 @@ const struct c_common_resword c_common_reswords[] =
 {
   { "_Bool",           RID_BOOL,      D_CONLY },
   { "_Complex",                RID_COMPLEX,    0 },
 {
   { "_Bool",           RID_BOOL,      D_CONLY },
   { "_Complex",                RID_COMPLEX,    0 },
+  { "_Imaginary",      RID_IMAGINARY, D_CONLY },
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
   { "_Decimal128",      RID_DFLOAT128, D_CONLY | D_EXT },
   { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
   { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
   { "_Decimal128",      RID_DFLOAT128, D_CONLY | D_EXT },
@@ -823,7 +780,7 @@ const struct attribute_spec c_common_attribute_table[] =
      to prevent its usage in source code.  */
   { "no vops",                0, 0, true,  false, false,
                              handle_novops_attribute },
      to prevent its usage in source code.  */
   { "no vops",                0, 0, true,  false, false,
                              handle_novops_attribute },
-  { "deprecated",             0, 0, false, false, false,
+  { "deprecated",             0, 1, false, false, false,
                              handle_deprecated_attribute },
   { "vector_size",           1, 1, false, true, false,
                              handle_vector_size_attribute },
                              handle_deprecated_attribute },
   { "vector_size",           1, 1, false, true, false,
                              handle_vector_size_attribute },
@@ -983,37 +940,16 @@ fname_as_string (int pretty_p)
   return namep;
 }
 
   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
 /* 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
 
 tree
-fname_decl (unsigned int rid, tree id)
+fname_decl (location_t loc, unsigned int rid, tree id)
 {
   unsigned ix;
   tree decl = NULL_TREE;
 {
   unsigned ix;
   tree decl = NULL_TREE;
@@ -1035,7 +971,7 @@ fname_decl (unsigned int rid, tree id)
       input_location = UNKNOWN_LOCATION;
 
       stmts = push_stmt_list ();
       input_location = UNKNOWN_LOCATION;
 
       stmts = push_stmt_list ();
-      decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
+      decl = (*make_fname_decl) (loc, id, fname_vars[ix].pretty);
       stmts = pop_stmt_list (stmts);
       if (!IS_EMPTY_STMT (stmts))
        saved_function_name_decls
       stmts = pop_stmt_list (stmts);
       if (!IS_EMPTY_STMT (stmts))
        saved_function_name_decls
@@ -1044,7 +980,7 @@ fname_decl (unsigned int rid, tree id)
       input_location = saved_location;
     }
   if (!ix && !current_function_decl)
       input_location = saved_location;
     }
   if (!ix && !current_function_decl)
-    pedwarn (input_location, 0, "%qD is not defined outside of function scope", decl);
+    pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
 
   return decl;
 }
 
   return decl;
 }
@@ -1126,6 +1062,407 @@ fix_string_type (tree value)
   return value;
 }
 \f
   return value;
 }
 \f
+/* Fully fold EXPR, an expression that was not folded (beyond integer
+   constant expressions and null pointer constants) when being built
+   up.  If IN_INIT, this is in a static initializer and certain
+   changes are made to the folding done.  Clear *MAYBE_CONST if
+   MAYBE_CONST is not NULL and EXPR is definitely not a constant
+   expression because it contains an evaluated operator (in C99) or an
+   operator outside of sizeof returning an integer constant (in C90)
+   not permitted in constant expressions, or because it contains an
+   evaluated arithmetic overflow.  (*MAYBE_CONST should typically be
+   set to true by callers before calling this function.)  Return the
+   folded expression.  Function arguments have already been folded
+   before calling this function, as have the contents of SAVE_EXPR,
+   TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
+   C_MAYBE_CONST_EXPR.  */
+
+tree
+c_fully_fold (tree expr, bool in_init, bool *maybe_const)
+{
+  tree ret;
+  tree eptype = NULL_TREE;
+  bool dummy = true;
+  bool maybe_const_itself = true;
+
+  /* This function is not relevant to C++ because C++ folds while
+     parsing, and may need changes to be correct for C++ when C++
+     stops folding while parsing.  */
+  if (c_dialect_cxx ())
+    gcc_unreachable ();
+
+  if (!maybe_const)
+    maybe_const = &dummy;
+  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+    {
+      eptype = TREE_TYPE (expr);
+      expr = TREE_OPERAND (expr, 0);
+    }
+  ret = c_fully_fold_internal (expr, in_init, maybe_const,
+                              &maybe_const_itself);
+  if (eptype)
+    ret = fold_convert (eptype, ret);
+  *maybe_const &= maybe_const_itself;
+  return ret;
+}
+
+/* Internal helper for c_fully_fold.  EXPR and IN_INIT are as for
+   c_fully_fold.  *MAYBE_CONST_OPERANDS is cleared because of operands
+   not permitted, while *MAYBE_CONST_ITSELF is cleared because of
+   arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from
+   both evaluated and unevaluated subexpressions while
+   *MAYBE_CONST_ITSELF is carried from only evaluated
+   subexpressions).  */
+
+static tree
+c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
+                      bool *maybe_const_itself)
+{
+  tree ret = expr;
+  enum tree_code code = TREE_CODE (expr);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
+  location_t loc = EXPR_LOCATION (expr);
+  tree op0, op1, op2, op3;
+  tree orig_op0, orig_op1, orig_op2;
+  bool op0_const = true, op1_const = true, op2_const = true;
+  bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
+  bool nowarning = TREE_NO_WARNING (expr);
+
+  /* This function is not relevant to C++ because C++ folds while
+     parsing, and may need changes to be correct for C++ when C++
+     stops folding while parsing.  */
+  if (c_dialect_cxx ())
+    gcc_unreachable ();
+
+  /* Constants, declarations, statements, errors, SAVE_EXPRs and
+     anything else not counted as an expression cannot usefully be
+     folded further at this point.  */
+  if (!IS_EXPR_CODE_CLASS (kind)
+      || kind == tcc_statement
+      || code == SAVE_EXPR)
+    return expr;
+
+  /* Operands of variable-length expressions (function calls) have
+     already been folded, as have __builtin_* function calls, and such
+     expressions cannot occur in constant expressions.  */
+  if (kind == tcc_vl_exp)
+    {
+      *maybe_const_operands = false;
+      ret = fold (expr);
+      goto out;
+    }
+
+  if (code == C_MAYBE_CONST_EXPR)
+    {
+      tree pre = C_MAYBE_CONST_EXPR_PRE (expr);
+      tree inner = C_MAYBE_CONST_EXPR_EXPR (expr);
+      if (C_MAYBE_CONST_EXPR_NON_CONST (expr))
+       *maybe_const_operands = false;
+      if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr))
+       *maybe_const_itself = false;
+      if (pre && !in_init)
+       ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
+      else
+       ret = inner;
+      goto out;
+    }
+
+  /* Assignment, increment, decrement, function call and comma
+     operators, and statement expressions, cannot occur in constant
+     expressions if evaluated / outside of sizeof.  (Function calls
+     were handled above, though VA_ARG_EXPR is treated like a function
+     call here, and statement expressions are handled through
+     C_MAYBE_CONST_EXPR to avoid folding inside them.)  */
+  switch (code)
+    {
+    case MODIFY_EXPR:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case COMPOUND_EXPR:
+      *maybe_const_operands = false;
+      break;
+
+    case VA_ARG_EXPR:
+    case TARGET_EXPR:
+    case BIND_EXPR:
+    case OBJ_TYPE_REF:
+      *maybe_const_operands = false;
+      ret = fold (expr);
+      goto out;
+
+    default:
+      break;
+    }
+
+  /* Fold individual tree codes as appropriate.  */
+  switch (code)
+    {
+    case COMPOUND_LITERAL_EXPR:
+      /* Any non-constancy will have been marked in a containing
+        C_MAYBE_CONST_EXPR; there is no more folding to do here.  */
+      goto out;
+
+    case COMPONENT_REF:
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      op1 = TREE_OPERAND (expr, 1);
+      op2 = TREE_OPERAND (expr, 2);
+      op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      if (op0 != orig_op0)
+       ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
+      if (ret != expr)
+       {
+         TREE_READONLY (ret) = TREE_READONLY (expr);
+         TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+       }
+      goto out;
+
+    case ARRAY_REF:
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      orig_op1 = op1 = TREE_OPERAND (expr, 1);
+      op2 = TREE_OPERAND (expr, 2);
+      op3 = TREE_OPERAND (expr, 3);
+      op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      op1 = decl_constant_value_for_optimization (op1);
+      if (op0 != orig_op0 || op1 != orig_op1)
+       ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
+      if (ret != expr)
+       {
+         TREE_READONLY (ret) = TREE_READONLY (expr);
+         TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
+         TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+       }
+      ret = fold (ret);
+      goto out;
+
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case POINTER_PLUS_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case BIT_AND_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case COMPLEX_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+      /* Binary operations evaluating both arguments (increment and
+        decrement are binary internally in GCC).  */
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      orig_op1 = op1 = TREE_OPERAND (expr, 1);
+      op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      if (code != MODIFY_EXPR
+         && code != PREDECREMENT_EXPR
+         && code != PREINCREMENT_EXPR
+         && code != POSTDECREMENT_EXPR
+         && code != POSTINCREMENT_EXPR)
+       op0 = decl_constant_value_for_optimization (op0);
+      /* The RHS of a MODIFY_EXPR was fully folded when building that
+        expression for the sake of conversion warnings.  */
+      if (code != MODIFY_EXPR)
+       op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+                                    maybe_const_itself);
+      op1 = decl_constant_value_for_optimization (op1);
+      if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+       ret = in_init
+         ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
+         : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+      else
+       ret = fold (expr);
+      goto out;
+
+    case INDIRECT_REF:
+    case FIX_TRUNC_EXPR:
+    case FLOAT_EXPR:
+    CASE_CONVERT:
+    case NON_LVALUE_EXPR:
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case ADDR_EXPR:
+    case CONJ_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      /* Unary operations.  */
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
+       op0 = decl_constant_value_for_optimization (op0);
+      if (op0 != orig_op0 || in_init)
+       ret = in_init
+         ? fold_build1_initializer (code, TREE_TYPE (expr), op0)
+         : fold_build1 (code, TREE_TYPE (expr), op0);
+      else
+       ret = fold (expr);
+      if (code == INDIRECT_REF
+         && ret != expr
+         && TREE_CODE (ret) == INDIRECT_REF)
+       {
+         TREE_READONLY (ret) = TREE_READONLY (expr);
+         TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
+         TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
+       }
+      goto out;
+
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+      /* Binary operations not necessarily evaluating both
+        arguments.  */
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      orig_op1 = op1 = TREE_OPERAND (expr, 1);
+      op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+      op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+       ret = in_init
+         ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1)
+         : fold_build2 (code, TREE_TYPE (expr), op0, op1);
+      else
+       ret = fold (expr);
+      *maybe_const_operands &= op0_const;
+      *maybe_const_itself &= op0_const_self;
+      if (!(flag_isoc99
+           && op0_const
+           && op0_const_self
+           && (code == TRUTH_ANDIF_EXPR
+               ? op0 == truthvalue_false_node
+               : op0 == truthvalue_true_node)))
+       *maybe_const_operands &= op1_const;
+      if (!(op0_const
+           && op0_const_self
+           && (code == TRUTH_ANDIF_EXPR
+               ? op0 == truthvalue_false_node
+               : op0 == truthvalue_true_node)))
+       *maybe_const_itself &= op1_const_self;
+      goto out;
+
+    case COND_EXPR:
+      orig_op0 = op0 = TREE_OPERAND (expr, 0);
+      orig_op1 = op1 = TREE_OPERAND (expr, 1);
+      orig_op2 = op2 = TREE_OPERAND (expr, 2);
+      op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+      op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+      if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
+       ret = fold_build3 (code, TREE_TYPE (expr), op0, op1, op2);
+      else
+       ret = fold (expr);
+      *maybe_const_operands &= op0_const;
+      *maybe_const_itself &= op0_const_self;
+      if (!(flag_isoc99
+           && op0_const
+           && op0_const_self
+           && op0 == truthvalue_false_node))
+       *maybe_const_operands &= op1_const;
+      if (!(op0_const
+           && op0_const_self
+           && op0 == truthvalue_false_node))
+       *maybe_const_itself &= op1_const_self;
+      if (!(flag_isoc99
+           && op0_const
+           && op0_const_self
+           && op0 == truthvalue_true_node))
+       *maybe_const_operands &= op2_const;
+      if (!(op0_const
+           && op0_const_self
+           && op0 == truthvalue_true_node))
+       *maybe_const_itself &= op2_const_self;
+      goto out;
+
+    case EXCESS_PRECISION_EXPR:
+      /* Each case where an operand with excess precision may be
+        encountered must remove the EXCESS_PRECISION_EXPR around
+        inner operands and possibly put one around the whole
+        expression or possibly convert to the semantic type (which
+        c_fully_fold does); we cannot tell at this stage which is
+        appropriate in any particular case.  */
+      gcc_unreachable ();
+
+    default:
+      /* Various codes may appear through folding built-in functions
+        and their arguments.  */
+      goto out;
+    }
+
+ out:
+  /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
+     have been done by this point, so remove them again.  */
+  nowarning |= TREE_NO_WARNING (ret);
+  STRIP_TYPE_NOPS (ret);
+  if (nowarning && !TREE_NO_WARNING (ret))
+    {
+      if (!CAN_HAVE_LOCATION_P (ret))
+       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+      TREE_NO_WARNING (ret) = 1;
+    }
+  if (ret != expr)
+    protected_set_expr_location (ret, loc);
+  return ret;
+}
+
+/* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
+   return EXP.  Otherwise, return either EXP or its known constant
+   value (if it has one), but return EXP if EXP has mode BLKmode.  ???
+   Is the BLKmode test appropriate?  */
+
+tree
+decl_constant_value_for_optimization (tree exp)
+{
+  tree ret;
+
+  /* This function is only used by C, for c_fully_fold and other
+     optimization, and may not be correct for C++.  */
+  if (c_dialect_cxx ())
+    gcc_unreachable ();
+
+  if (!optimize
+      || TREE_CODE (exp) != VAR_DECL
+      || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+      || DECL_MODE (exp) == BLKmode)
+    return exp;
+
+  ret = decl_constant_value (exp);
+  /* Avoid unwanted tree sharing between the initializer and current
+     function's body where the tree can be modified e.g. by the
+     gimplifier.  */
+  if (ret != exp && TREE_STATIC (exp))
+    ret = unshare_expr (ret);
+  return ret;
+}
+
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
    requires to be a constant expression.
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
    requires to be a constant expression.
@@ -1168,33 +1505,37 @@ constant_expression_error (tree value)
    already overflowed.  */
 
 void
    already overflowed.  */
 
 void
-overflow_warning (tree value)
+overflow_warning (location_t loc, tree value)
 {
 {
-  if (skip_evaluation) return;
+  if (c_inhibit_evaluation_warnings != 0)
+    return;
 
   switch (TREE_CODE (value))
     {
     case INTEGER_CST:
 
   switch (TREE_CODE (value))
     {
     case INTEGER_CST:
-      warning (OPT_Woverflow, "integer overflow in expression");
+      warning_at (loc, OPT_Woverflow, "integer overflow in expression");
       break;
       
     case REAL_CST:
       break;
       
     case REAL_CST:
-      warning (OPT_Woverflow, "floating point overflow in expression");
+      warning_at (loc, OPT_Woverflow,
+                 "floating point overflow in expression");
       break;
       
     case FIXED_CST:
       break;
       
     case FIXED_CST:
-      warning (OPT_Woverflow, "fixed-point overflow in expression");
+      warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
       break;
 
     case VECTOR_CST:
       break;
 
     case VECTOR_CST:
-      warning (OPT_Woverflow, "vector overflow in expression");
+      warning_at (loc, OPT_Woverflow, "vector overflow in expression");
       break;
       
     case COMPLEX_CST:
       if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
       break;
       
     case COMPLEX_CST:
       if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
-       warning (OPT_Woverflow, "complex integer overflow in expression");
+       warning_at (loc, OPT_Woverflow,
+                   "complex integer overflow in expression");
       else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
       else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
-       warning (OPT_Woverflow, "complex floating point overflow in expression");
+       warning_at (loc, OPT_Woverflow,
+                   "complex floating point overflow in expression");
       break;
 
     default:
       break;
 
     default:
@@ -1202,38 +1543,94 @@ overflow_warning (tree value)
     }
 }
 
     }
 }
 
+/* Warn about uses of logical || / && operator in a context where it
+   is likely that the bitwise equivalent was intended by the
+   programmer.  We have seen an expression in which CODE is a binary
+   operator used to combine expressions OP_LEFT and OP_RIGHT, which before folding
+   had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE.  */
+void
+warn_logical_operator (location_t location, enum tree_code code, tree type,
+                      enum tree_code code_left, tree op_left, 
+                      enum tree_code ARG_UNUSED (code_right), tree op_right)
+{
+  int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
+  int in0_p, in1_p, in_p;
+  tree low0, low1, low, high0, high1, high, lhs, rhs, tem;
+  bool strict_overflow_p = false;
+
+  if (code != TRUTH_ANDIF_EXPR
+      && code != TRUTH_AND_EXPR
+      && code != TRUTH_ORIF_EXPR
+      && code != TRUTH_OR_EXPR)
+    return;
 
 
-/* Warn about use of a logical || / && operator being used in a
-   context where it is likely that the bitwise equivalent was intended
-   by the programmer. CODE is the TREE_CODE of the operator, ARG1
-   and ARG2 the arguments.  */
+  /* Warn if &&/|| are being used in a context where it is
+     likely that the bitwise equivalent was intended by the
+     programmer. That is, an expression such as op && MASK
+     where op should not be any boolean expression, nor a
+     constant, and mask seems to be a non-boolean integer constant.  */
+  if (!truth_value_p (code_left)
+      && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
+      && !CONSTANT_CLASS_P (op_left)
+      && !TREE_NO_WARNING (op_left)
+      && TREE_CODE (op_right) == INTEGER_CST
+      && !integer_zerop (op_right)
+      && !integer_onep (op_right))
+    {
+      if (or_op)
+       warning_at (location, OPT_Wlogical_op, "logical %<or%>"
+                   " applied to non-boolean constant");
+      else
+       warning_at (location, OPT_Wlogical_op, "logical %<and%>"
+                   " applied to non-boolean constant");
+      TREE_NO_WARNING (op_left) = true;
+      return;
+    }
 
 
-void
-warn_logical_operator (enum tree_code code, tree arg1, tree
-    arg2)
-{
-  switch (code)
-    {
-      case TRUTH_ANDIF_EXPR:
-      case TRUTH_ORIF_EXPR:
-      case TRUTH_OR_EXPR:
-      case TRUTH_AND_EXPR:
-       if (!TREE_NO_WARNING (arg1)
-           && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-           && !CONSTANT_CLASS_P (arg1)
-           && TREE_CODE (arg2) == INTEGER_CST
-           && !integer_zerop (arg2))
-         {
-           warning (OPT_Wlogical_op,
-                    "logical %<%s%> with non-zero constant "
-                    "will always evaluate as true",
-                    ((code == TRUTH_ANDIF_EXPR)
-                     || (code == TRUTH_AND_EXPR)) ? "&&" : "||");
-           TREE_NO_WARNING (arg1) = true;
-         }
-       break;
-      default:
-       break;
+  /* We do not warn for constants because they are typical of macro
+     expansions that test for features.  */
+  if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right))
+    return;
+
+  /* This warning only makes sense with logical operands.  */
+  if (!(truth_value_p (TREE_CODE (op_left))
+       || INTEGRAL_TYPE_P (TREE_TYPE (op_left)))
+      || !(truth_value_p (TREE_CODE (op_right))
+          || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
+    return;
+
+  lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
+  rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
+
+  if (lhs && TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
+    lhs = C_MAYBE_CONST_EXPR_EXPR (lhs);
+
+  if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
+    rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
+  
+  /* If this is an OR operation, invert both sides; we will invert
+     again at the end.  */
+  if (or_op)
+    in0_p = !in0_p, in1_p = !in1_p;
+  
+  /* If both expressions are the same, if we can merge the ranges, and we
+     can build the range test, return it or it inverted.  */
+  if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
+      && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
+                      in1_p, low1, high1)
+      && 0 != (tem = build_range_check (type, lhs, in_p, low, high)))
+    {
+      if (TREE_CODE (tem) != INTEGER_CST)
+       return;
+
+      if (or_op)
+        warning_at (location, OPT_Wlogical_op,
+                    "logical %<or%> "
+                    "of collectively exhaustive tests is always true");
+      else
+        warning_at (location, OPT_Wlogical_op,
+                    "logical %<and%> "
+                    "of mutually exclusive tests is always false");
     }
 }
 
     }
 }
 
@@ -1246,6 +1643,10 @@ warn_logical_operator (enum tree_code code, tree arg1, tree
 bool
 strict_aliasing_warning (tree otype, tree type, tree expr)
 {
 bool
 strict_aliasing_warning (tree otype, tree type, tree expr)
 {
+  /* Strip pointer conversion chains and get to the correct original type.  */
+  STRIP_NOPS (expr);
+  otype = TREE_TYPE (expr);
+
   if (!(flag_strict_aliasing
        && POINTER_TYPE_P (type)
        && POINTER_TYPE_P (otype)
   if (!(flag_strict_aliasing
        && POINTER_TYPE_P (type)
        && POINTER_TYPE_P (otype)
@@ -1312,31 +1713,6 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
   return false;
 }
 
   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'.  */
 
 /* Warn for unlikely, improbable, or stupid DECL declarations
    of `main'.  */
 
@@ -1397,7 +1773,7 @@ bool
 vector_targets_convertible_p (const_tree t1, const_tree t2)
 {
   if (TREE_CODE (t1) == VECTOR_TYPE && TREE_CODE (t2) == VECTOR_TYPE
 vector_targets_convertible_p (const_tree t1, const_tree t2)
 {
   if (TREE_CODE (t1) == VECTOR_TYPE && TREE_CODE (t2) == VECTOR_TYPE
-      && (targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2))
+      && (TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
       && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
     return true;
 
       && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
     return true;
 
@@ -1415,7 +1791,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
   static bool emitted_lax_note = false;
   bool convertible_lax;
 
   static bool emitted_lax_note = false;
   bool convertible_lax;
 
-  if ((targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2))
+  if ((TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
       && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
     return true;
 
       && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
     return true;
 
@@ -1829,14 +2205,31 @@ tree
 convert_and_check (tree type, tree expr)
 {
   tree result;
 convert_and_check (tree type, tree expr)
 {
   tree result;
+  tree expr_for_warning;
+
+  /* Convert from a value with possible excess precision rather than
+     via the semantic type, but do not warn about values not fitting
+     exactly in the semantic type.  */
+  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+    {
+      tree orig_type = TREE_TYPE (expr);
+      expr = TREE_OPERAND (expr, 0);
+      expr_for_warning = convert (orig_type, expr);
+      if (orig_type == type)
+       return expr_for_warning;
+    }
+  else
+    expr_for_warning = expr;
 
   if (TREE_TYPE (expr) == type)
     return expr;
   
   result = convert (type, expr);
 
 
   if (TREE_TYPE (expr) == type)
     return expr;
   
   result = convert (type, expr);
 
-  if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
-    warnings_for_convert_and_check (type, expr, result);
+  if (c_inhibit_evaluation_warnings == 0
+      && !TREE_OVERFLOW_P (expr)
+      && result != error_mark_node)
+    warnings_for_convert_and_check (type, expr_for_warning, result);
 
   return result;
 }
 
   return result;
 }
@@ -1876,6 +2269,7 @@ static void add_tlist (struct tlist **, struct tlist *, tree, int);
 static void merge_tlist (struct tlist **, struct tlist *, int);
 static void verify_tree (tree, struct tlist **, struct tlist **, tree);
 static int warning_candidate_p (tree);
 static void merge_tlist (struct tlist **, struct tlist *, int);
 static void verify_tree (tree, struct tlist **, struct tlist **, tree);
 static int warning_candidate_p (tree);
+static bool candidate_equal_p (const_tree, const_tree);
 static void warn_for_collisions (struct tlist *);
 static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
 static struct tlist *new_tlist (struct tlist *, tree, tree);
 static void warn_for_collisions (struct tlist *);
 static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
 static struct tlist *new_tlist (struct tlist *, tree, tree);
@@ -1903,7 +2297,7 @@ add_tlist (struct tlist **to, struct tlist *add, tree exclude_writer, int copy)
       struct tlist *next = add->next;
       if (!copy)
        add->next = *to;
       struct tlist *next = add->next;
       if (!copy)
        add->next = *to;
-      if (!exclude_writer || add->writer != exclude_writer)
+      if (!exclude_writer || !candidate_equal_p (add->writer, exclude_writer))
        *to = copy ? new_tlist (*to, add->expr, add->writer) : add;
       add = next;
     }
        *to = copy ? new_tlist (*to, add->expr, add->writer) : add;
       add = next;
     }
@@ -1930,7 +2324,7 @@ merge_tlist (struct tlist **to, struct tlist *add, int copy)
       struct tlist *next = add->next;
 
       for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
       struct tlist *next = add->next;
 
       for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
-       if (tmp2->expr == add->expr)
+       if (candidate_equal_p (tmp2->expr, add->expr))
          {
            found = 1;
            if (!tmp2->writer)
          {
            found = 1;
            if (!tmp2->writer)
@@ -1958,15 +2352,14 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
 
   /* Avoid duplicate warnings.  */
   for (tmp = warned_ids; tmp; tmp = tmp->next)
 
   /* Avoid duplicate warnings.  */
   for (tmp = warned_ids; tmp; tmp = tmp->next)
-    if (tmp->expr == written)
+    if (candidate_equal_p (tmp->expr, written))
       return;
 
   while (list)
     {
       return;
 
   while (list)
     {
-      if (list->expr == written
-         && list->writer != writer
-         && (!only_writes || list->writer)
-         && DECL_NAME (list->expr))
+      if (candidate_equal_p (list->expr, written)
+         && !candidate_equal_p (list->writer, writer)
+         && (!only_writes || list->writer))
        {
          warned_ids = new_tlist (warned_ids, written, NULL_TREE);
          warning_at (EXPR_HAS_LOCATION (writer)
        {
          warned_ids = new_tlist (warned_ids, written, NULL_TREE);
          warning_at (EXPR_HAS_LOCATION (writer)
@@ -1998,7 +2391,17 @@ warn_for_collisions (struct tlist *list)
 static int
 warning_candidate_p (tree x)
 {
 static int
 warning_candidate_p (tree x)
 {
-  return TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == PARM_DECL;
+  /* !VOID_TYPE_P (TREE_TYPE (x)) is workaround for cp/tree.c
+     (lvalue_p) crash on TRY/CATCH. */
+  return !(DECL_P (x) && DECL_ARTIFICIAL (x))
+    && TREE_TYPE (x) && !VOID_TYPE_P (TREE_TYPE (x)) && lvalue_p (x);
+}
+
+/* Return nonzero if X and Y appear to be the same candidate (or NULL) */
+static bool
+candidate_equal_p (const_tree x, const_tree y)
+{
+  return (x == y) || (x && y && operand_equal_p (x, y, 0));
 }
 
 /* Walk the tree X, and record accesses to variables.  If X is written by the
 }
 
 /* Walk the tree X, and record accesses to variables.  If X is written by the
@@ -2044,10 +2447,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
   cl = TREE_CODE_CLASS (code);
 
   if (warning_candidate_p (x))
   cl = TREE_CODE_CLASS (code);
 
   if (warning_candidate_p (x))
-    {
-      *pno_sp = new_tlist (*pno_sp, x, writer);
-      return;
-    }
+    *pno_sp = new_tlist (*pno_sp, x, writer);
 
   switch (code)
     {
 
   switch (code)
     {
@@ -2160,7 +2560,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
       {
        struct tlist_cache *t;
        for (t = save_expr_cache; t; t = t->next)
       {
        struct tlist_cache *t;
        for (t = save_expr_cache; t; t = t->next)
-         if (t->expr == x)
+         if (candidate_equal_p (t->expr, x))
            break;
 
        if (!t)
            break;
 
        if (!t)
@@ -2765,7 +3165,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
 
 #define TYPE_OK(node)                                                      \
   (TYPE_MODE (type) == TYPE_MODE (node)                                            \
 
 #define TYPE_OK(node)                                                      \
   (TYPE_MODE (type) == TYPE_MODE (node)                                            \
-   && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+   && TYPE_PRECISION (type) == TYPE_PRECISION (node))
   if (TYPE_OK (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (TYPE_OK (integer_type_node))
   if (TYPE_OK (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (TYPE_OK (integer_type_node))
@@ -2795,10 +3195,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 #undef TYPE_OK
 
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 #undef TYPE_OK
 
-  if (c_dialect_cxx ())
-    return type;
-  else
-    return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+  return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
 }
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
 }
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
@@ -2833,7 +3230,8 @@ c_register_builtin_type (tree type, const char* name)
 {
   tree decl;
 
 {
   tree decl;
 
-  decl = build_decl (TYPE_DECL, get_identifier (name), type);
+  decl = build_decl (UNKNOWN_LOCATION,
+                    TYPE_DECL, get_identifier (name), type);
   DECL_ARTIFICIAL (decl) = 1;
   if (!TYPE_NAME (type))
     TYPE_NAME (type) = decl;
   DECL_ARTIFICIAL (decl) = 1;
   if (!TYPE_NAME (type))
     TYPE_NAME (type) = decl;
@@ -2841,40 +3239,14 @@ c_register_builtin_type (tree type, const char* name)
 
   registered_builtin_types = tree_cons (0, type, registered_builtin_types);
 }
 
   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
 \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
 
 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;
 
 {
   const char *opname;
 
@@ -2925,8 +3297,9 @@ binary_op_error (enum tree_code code, tree type0, tree type1)
     default:
       gcc_unreachable ();
     }
     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.
 }
 \f
 /* Subroutine of build_binary_op, used for comparison operations.
@@ -3342,7 +3715,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.  */
       /* 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));
     }
                               convert (int_type, TREE_OPERAND (intop, 1)), 1);
       intop = convert (int_type, TREE_OPERAND (intop, 0));
     }
@@ -3358,7 +3732,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,
      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.  */
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
@@ -3372,6 +3747,27 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
   return ret;
 }
 \f
   return ret;
 }
 \f
+/* Wrap a SAVE_EXPR around EXPR, if appropriate.  Like save_expr, but
+   for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
+   around the SAVE_EXPR if needed so that c_fully_fold does not need
+   to look inside SAVE_EXPRs.  */
+
+tree
+c_save_expr (tree expr)
+{
+  bool maybe_const = true;
+  if (c_dialect_cxx ())
+    return save_expr (expr);
+  expr = c_fully_fold (expr, false, &maybe_const);
+  expr = save_expr (expr);
+  if (!maybe_const)
+    {
+      expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+      C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
+    }
+  return expr;
+}
+
 /* Return whether EXPR is a declaration whose address can never be
    NULL.  */
 
 /* Return whether EXPR is a declaration whose address can never be
    NULL.  */
 
@@ -3389,6 +3785,8 @@ decl_with_nonnull_addr_p (const_tree expr)
    have been validated to be of suitable type; otherwise, a bad
    diagnostic may result.
 
    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
    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
@@ -3398,7 +3796,7 @@ decl_with_nonnull_addr_p (const_tree expr)
    The resulting type should always be `truthvalue_type_node'.  */
 
 tree
    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))
     {
 {
   switch (TREE_CODE (expr))
     {
@@ -3408,8 +3806,9 @@ c_common_truthvalue_conversion (tree expr)
     case ORDERED_EXPR: case UNORDERED_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
     case ORDERED_EXPR: case UNORDERED_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
-      return build2 (TREE_CODE (expr), truthvalue_type_node,
+      expr = build2 (TREE_CODE (expr), truthvalue_type_node,
                     TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
                     TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+      goto ret;
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
@@ -3418,15 +3817,20 @@ c_common_truthvalue_conversion (tree expr)
     case TRUTH_XOR_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
     case TRUTH_XOR_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)));
+      expr = build2 (TREE_CODE (expr), truthvalue_type_node,
+                    c_common_truthvalue_conversion (location, 
+                                                    TREE_OPERAND (expr, 0)),
+                    c_common_truthvalue_conversion (location,
+                                                    TREE_OPERAND (expr, 1)));
+      goto ret;
 
     case TRUTH_NOT_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
 
     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)));
+      expr = build1 (TREE_CODE (expr), truthvalue_type_node,
+                    c_common_truthvalue_conversion (location,
+                                                    TREE_OPERAND (expr, 0)));
+      goto ret;
 
     case ERROR_MARK:
       return expr;
 
     case ERROR_MARK:
       return expr;
@@ -3447,7 +3851,7 @@ c_common_truthvalue_conversion (tree expr)
             : truthvalue_false_node;
 
     case FUNCTION_DECL:
             : 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:
       /* Fall through.  */
 
     case ADDR_EXPR:
@@ -3456,9 +3860,10 @@ c_common_truthvalue_conversion (tree expr)
        if (decl_with_nonnull_addr_p (inner))
          {
            /* Common Ada/Pascal programmer's mistake.  */
        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;
          }
 
            return truthvalue_true_node;
          }
 
@@ -3471,42 +3876,74 @@ c_common_truthvalue_conversion (tree expr)
          }
 
        if (TREE_SIDE_EFFECTS (inner))
          }
 
        if (TREE_SIDE_EFFECTS (inner))
-         return build2 (COMPOUND_EXPR, truthvalue_type_node,
-                        inner, truthvalue_true_node);
+         {
+           expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
+                          inner, truthvalue_true_node);
+           goto ret;
+         }
        else
          return truthvalue_true_node;
       }
 
     case COMPLEX_EXPR:
        else
          return truthvalue_true_node;
       }
 
     case COMPLEX_EXPR:
-      return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+      expr = build_binary_op (EXPR_LOCATION (expr),
+                             (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
                               ? 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);
                              0);
+      goto ret;
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
+    case EXCESS_PRECISION_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
       /* 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:
       /* These don't change whether an object is zero or nonzero, but
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
       /* These don't change whether an object is zero or nonzero, but
         we can't ignore them if their second arg has side-effects.  */
       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)));
+       {
+         expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
+                        TREE_OPERAND (expr, 1),
+                        c_common_truthvalue_conversion 
+                        (location, TREE_OPERAND (expr, 0)));
+         goto ret;
+       }
       else
       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.  */
 
     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)));
+      if (c_dialect_cxx ())
+       {
+         expr = fold_build3 (COND_EXPR, truthvalue_type_node,
+                             TREE_OPERAND (expr, 0),
+                             c_common_truthvalue_conversion (location,
+                                                             TREE_OPERAND (expr,
+                                                                           1)),
+                             c_common_truthvalue_conversion (location,
+                                                             TREE_OPERAND (expr,
+                                                                           2)));
+         goto ret;
+       }
+      else
+       {
+         /* Folding will happen later for C.  */
+         expr = build3 (COND_EXPR, truthvalue_type_node,
+                        TREE_OPERAND (expr, 0),
+                        c_common_truthvalue_conversion (location,
+                                                        TREE_OPERAND (expr, 1)),
+                        c_common_truthvalue_conversion (location,
+                                                        TREE_OPERAND (expr, 2)));
+         goto ret;
+       }
 
     CASE_CONVERT:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
 
     CASE_CONVERT:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -3517,7 +3954,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))))
       /* 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:
       break;
 
     case MODIFY_EXPR:
@@ -3536,13 +3974,19 @@ c_common_truthvalue_conversion (tree expr)
 
   if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
     {
 
   if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
     {
-      tree t = save_expr (expr);
-      return (build_binary_op
-             ((TREE_SIDE_EFFECTS (expr)
+      tree t = c_save_expr (expr);
+      expr = (build_binary_op
+             (EXPR_LOCATION (expr),
+              (TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_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));
               0));
+      goto ret;
     }
 
   if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
     }
 
   if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
@@ -3550,10 +3994,14 @@ c_common_truthvalue_conversion (tree expr)
       tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
                                          FCONST0 (TYPE_MODE
                                                   (TREE_TYPE (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 (location, NE_EXPR, expr, fixed_zero_node, 1);
     }
     }
+  else
+    return build_binary_op (location, NE_EXPR, expr, integer_zero_node, 1);
 
 
-  return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
+ ret:
+  protected_set_expr_location (expr, location);
+  return expr;
 }
 \f
 static void def_builtin_1  (enum built_in_function fncode,
 }
 \f
 static void def_builtin_1  (enum built_in_function fncode,
@@ -3794,13 +4242,15 @@ c_common_get_alias_set (tree t)
   return -1;
 }
 \f
   return -1;
 }
 \f
-/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
-   second parameter indicates which OPERATOR is being applied.  The COMPLAIN
-   flag controls whether we should diagnose possibly ill-formed
-   constructs or not.  */
+/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
+   the second parameter indicates which OPERATOR is being applied.
+   The COMPLAIN flag controls whether we should diagnose possibly
+   ill-formed constructs or not.  LOC is the location of the SIZEOF or
+   TYPEOF operator.  */
 
 tree
 
 tree
-c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
+c_sizeof_or_alignof_type (location_t loc,
+                         tree type, bool is_sizeof, int complain)
 {
   const char *op_name;
   tree value = NULL;
 {
   const char *op_name;
   tree value = NULL;
@@ -3813,7 +4263,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
       if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
       if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
-           pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+           pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
                     "invalid application of %<sizeof%> to a function type");
           else if (!complain)
             return error_mark_node;
                     "invalid application of %<sizeof%> to a function type");
           else if (!complain)
             return error_mark_node;
@@ -3826,7 +4276,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
     {
       if (type_code == VOID_TYPE
          && complain && (pedantic || warn_pointer_arith))
     {
       if (type_code == VOID_TYPE
          && complain && (pedantic || warn_pointer_arith))
-       pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+       pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
                 "invalid application of %qs to a void type", op_name);
       else if (!complain)
         return error_mark_node;
                 "invalid application of %qs to a void type", op_name);
       else if (!complain)
         return error_mark_node;
@@ -3835,8 +4285,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
   else if (!COMPLETE_TYPE_P (type))
     {
       if (complain)
   else if (!COMPLETE_TYPE_P (type))
     {
       if (complain)
-       error ("invalid application of %qs to incomplete type %qT ",
-              op_name, type);
+       error_at (loc, "invalid application of %qs to incomplete type %qT ",
+                 op_name, type);
       value = size_zero_node;
     }
   else
       value = size_zero_node;
     }
   else
@@ -3863,10 +4313,11 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
 /* Implement the __alignof keyword: Return the minimum required
    alignment of EXPR, measured in bytes.  For VAR_DECLs,
    FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
 /* Implement the __alignof keyword: Return the minimum required
    alignment of EXPR, measured in bytes.  For VAR_DECLs,
    FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
-   from an "aligned" __attribute__ specification).  */
+   from an "aligned" __attribute__ specification).  LOC is the
+   location of the ALIGNOF operator.  */
 
 tree
 
 tree
-c_alignof_expr (tree expr)
+c_alignof_expr (location_t loc, tree expr)
 {
   tree t;
 
 {
   tree t;
 
@@ -3876,7 +4327,7 @@ c_alignof_expr (tree expr)
   else if (TREE_CODE (expr) == COMPONENT_REF
           && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
     {
   else if (TREE_CODE (expr) == COMPONENT_REF
           && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
     {
-      error ("%<__alignof%> applied to a bit-field");
+      error_at (loc, "%<__alignof%> applied to a bit-field");
       t = size_one_node;
     }
   else if (TREE_CODE (expr) == COMPONENT_REF
       t = size_one_node;
     }
   else if (TREE_CODE (expr) == COMPONENT_REF
@@ -3899,10 +4350,10 @@ c_alignof_expr (tree expr)
          if (thisalign > bestalign)
            best = t, bestalign = thisalign;
        }
          if (thisalign > bestalign)
            best = t, bestalign = thisalign;
        }
-      return c_alignof (TREE_TYPE (TREE_TYPE (best)));
+      return c_alignof (loc, TREE_TYPE (TREE_TYPE (best)));
     }
   else
     }
   else
-    return c_alignof (TREE_TYPE (expr));
+    return c_alignof (loc, TREE_TYPE (expr));
 
   return fold_convert (size_type_node, t);
 }
 
   return fold_convert (size_type_node, t);
 }
@@ -4092,6 +4543,16 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
     mudflap_init ();
 }
 
     mudflap_init ();
 }
 
+/* Like get_identifier, but avoid warnings about null arguments when
+   the argument may be NULL for targets where GCC lacks stdint.h type
+   information.  */
+
+static inline tree
+c_get_ident (const char *id)
+{
+  return get_identifier (id);
+}
+
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
 
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
 
@@ -4140,31 +4601,41 @@ c_common_nodes_and_builtins (void)
 
   /* These are types that c_common_type_for_size and
      c_common_type_for_mode use.  */
 
   /* These are types that c_common_type_for_size and
      c_common_type_for_mode use.  */
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         intQI_type_node));
                                         intQI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         intHI_type_node));
                                         intHI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         intSI_type_node));
                                         intSI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (targetm.scalar_mode_supported_p (TImode))
                                         intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (targetm.scalar_mode_supported_p (TImode))
-    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+    lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                          TYPE_DECL,
                                           get_identifier ("__int128_t"),
                                           intTI_type_node));
 #endif
                                           get_identifier ("__int128_t"),
                                           intTI_type_node));
 #endif
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         unsigned_intQI_type_node));
                                         unsigned_intQI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         unsigned_intHI_type_node));
                                         unsigned_intHI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         unsigned_intSI_type_node));
                                         unsigned_intSI_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (targetm.scalar_mode_supported_p (TImode))
                                         unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (targetm.scalar_mode_supported_p (TImode))
-    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+    lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                          TYPE_DECL,
                                           get_identifier ("__uint128_t"),
                                           unsigned_intTI_type_node));
 #endif
                                           get_identifier ("__uint128_t"),
                                           unsigned_intTI_type_node));
 #endif
@@ -4172,12 +4643,14 @@ c_common_nodes_and_builtins (void)
   /* Create the widest literal types.  */
   widest_integer_literal_type_node
     = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
   /* Create the widest literal types.  */
   widest_integer_literal_type_node
     = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         widest_integer_literal_type_node));
 
   widest_unsigned_literal_type_node
     = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
                                         widest_integer_literal_type_node));
 
   widest_unsigned_literal_type_node
     = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL, NULL_TREE,
                                         widest_unsigned_literal_type_node));
 
   /* `unsigned long' is the standard type for sizeof.
                                         widest_unsigned_literal_type_node));
 
   /* `unsigned long' is the standard type for sizeof.
@@ -4269,17 +4742,21 @@ c_common_nodes_and_builtins (void)
 
     }
 
 
     }
 
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL,
                                         get_identifier ("complex int"),
                                         complex_integer_type_node));
                                         get_identifier ("complex int"),
                                         complex_integer_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL,
                                         get_identifier ("complex float"),
                                         complex_float_type_node));
                                         get_identifier ("complex float"),
                                         complex_float_type_node));
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+  lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+                                        TYPE_DECL,
                                         get_identifier ("complex double"),
                                         complex_double_type_node));
   lang_hooks.decls.pushdecl
                                         get_identifier ("complex double"),
                                         complex_double_type_node));
   lang_hooks.decls.pushdecl
-    (build_decl (TYPE_DECL, get_identifier ("complex long double"),
+    (build_decl (UNKNOWN_LOCATION,
+                TYPE_DECL, get_identifier ("complex long double"),
                 complex_long_double_type_node));
 
   if (c_dialect_cxx ())
                 complex_long_double_type_node));
 
   if (c_dialect_cxx ())
@@ -4331,6 +4808,7 @@ c_common_nodes_and_builtins (void)
   wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
   wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
   wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
   wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
+  underlying_wchar_type_node = wchar_type_node;
   if (c_dialect_cxx ())
     {
       if (TYPE_UNSIGNED (wchar_type_node))
   if (c_dialect_cxx ())
     {
       if (TYPE_UNSIGNED (wchar_type_node))
@@ -4339,11 +4817,6 @@ c_common_nodes_and_builtins (void)
        wchar_type_node = make_signed_type (wchar_type_size);
       record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);
     }
        wchar_type_node = make_signed_type (wchar_type_size);
       record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);
     }
-  else
-    {
-      signed_wchar_type_node = c_common_signed_type (wchar_type_node);
-      unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);
-    }
 
   /* This is for wide string constants.  */
   wchar_array_type_node
 
   /* This is for wide string constants.  */
   wchar_array_type_node
@@ -4389,13 +4862,96 @@ c_common_nodes_and_builtins (void)
   uintmax_type_node =
     TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));
 
   uintmax_type_node =
     TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));
 
+  if (SIG_ATOMIC_TYPE)
+    sig_atomic_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (SIG_ATOMIC_TYPE)));
+  if (INT8_TYPE)
+    int8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT8_TYPE)));
+  if (INT16_TYPE)
+    int16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT16_TYPE)));
+  if (INT32_TYPE)
+    int32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT32_TYPE)));
+  if (INT64_TYPE)
+    int64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT64_TYPE)));
+  if (UINT8_TYPE)
+    uint8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT8_TYPE)));
+  if (UINT16_TYPE)
+    uint16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT16_TYPE)));
+  if (UINT32_TYPE)
+    c_uint32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT32_TYPE)));
+  if (UINT64_TYPE)
+    c_uint64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT64_TYPE)));
+  if (INT_LEAST8_TYPE)
+    int_least8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST8_TYPE)));
+  if (INT_LEAST16_TYPE)
+    int_least16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST16_TYPE)));
+  if (INT_LEAST32_TYPE)
+    int_least32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST32_TYPE)));
+  if (INT_LEAST64_TYPE)
+    int_least64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST64_TYPE)));
+  if (UINT_LEAST8_TYPE)
+    uint_least8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST8_TYPE)));
+  if (UINT_LEAST16_TYPE)
+    uint_least16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST16_TYPE)));
+  if (UINT_LEAST32_TYPE)
+    uint_least32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST32_TYPE)));
+  if (UINT_LEAST64_TYPE)
+    uint_least64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST64_TYPE)));
+  if (INT_FAST8_TYPE)
+    int_fast8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST8_TYPE)));
+  if (INT_FAST16_TYPE)
+    int_fast16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST16_TYPE)));
+  if (INT_FAST32_TYPE)
+    int_fast32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST32_TYPE)));
+  if (INT_FAST64_TYPE)
+    int_fast64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST64_TYPE)));
+  if (UINT_FAST8_TYPE)
+    uint_fast8_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST8_TYPE)));
+  if (UINT_FAST16_TYPE)
+    uint_fast16_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST16_TYPE)));
+  if (UINT_FAST32_TYPE)
+    uint_fast32_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST32_TYPE)));
+  if (UINT_FAST64_TYPE)
+    uint_fast64_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST64_TYPE)));
+  if (INTPTR_TYPE)
+    intptr_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (INTPTR_TYPE)));
+  if (UINTPTR_TYPE)
+    uintptr_type_node =
+      TREE_TYPE (identifier_global_value (c_get_ident (UINTPTR_TYPE)));
+
   default_function_type = build_function_type (integer_type_node, NULL_TREE);
   ptrdiff_type_node
     = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
   unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
 
   lang_hooks.decls.pushdecl
   default_function_type = build_function_type (integer_type_node, NULL_TREE);
   ptrdiff_type_node
     = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
   unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
 
   lang_hooks.decls.pushdecl
-    (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
+    (build_decl (UNKNOWN_LOCATION,
+                TYPE_DECL, get_identifier ("__builtin_va_list"),
                 va_list_type_node));
 #ifdef TARGET_ENUM_VA_LIST
   {
                 va_list_type_node));
 #ifdef TARGET_ENUM_VA_LIST
   {
@@ -4405,7 +4961,8 @@ c_common_nodes_and_builtins (void)
     for (l = 0; TARGET_ENUM_VA_LIST (l, &pname, &ptype); ++l)
       {
        lang_hooks.decls.pushdecl
     for (l = 0; TARGET_ENUM_VA_LIST (l, &pname, &ptype); ++l)
       {
        lang_hooks.decls.pushdecl
-         (build_decl (TYPE_DECL, get_identifier (pname),
+         (build_decl (UNKNOWN_LOCATION,
+                      TYPE_DECL, get_identifier (pname),
                       ptype));
 
       }
                       ptype));
 
       }
@@ -4451,10 +5008,28 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
 
   builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
   set_user_assembler_name (builtin, asmspec);
 
   builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
   set_user_assembler_name (builtin, asmspec);
-  if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
-    init_block_move_fn (asmspec);
-  else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
-    init_block_clear_fn (asmspec);
+  switch (DECL_FUNCTION_CODE (decl))
+    {
+    case BUILT_IN_MEMCPY:
+      init_block_move_fn (asmspec);
+      memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
+      break;
+    case BUILT_IN_MEMSET:
+      init_block_clear_fn (asmspec);
+      memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
+      break;
+    case BUILT_IN_MEMMOVE:
+      memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
+      break;
+    case BUILT_IN_MEMCMP:
+      memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
+      break;
+    case BUILT_IN_ABORT:
+      abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
+      break;
+    default:
+      break;
+    }
 }
 
 /* The number of named compound-literals generated thus far.  */
 }
 
 /* The number of named compound-literals generated thus far.  */
@@ -4473,9 +5048,11 @@ set_compound_literal_name (tree decl)
 }
 
 tree
 }
 
 tree
-build_va_arg (tree expr, tree type)
+build_va_arg (location_t loc, tree expr, tree type)
 {
 {
-  return build1 (VA_ARG_EXPR, type, expr);
+  expr = build1 (VA_ARG_EXPR, type, expr);
+  SET_EXPR_LOCATION (expr, loc);
+  return expr;
 }
 
 
 }
 
 
@@ -4657,17 +5234,18 @@ case_compare (splay_tree_key k1, splay_tree_key k2)
   return tree_int_cst_compare ((tree) k1, (tree) k2);
 }
 
   return tree_int_cst_compare ((tree) k1, (tree) k2);
 }
 
-/* Process a case label for the range LOW_VALUE ... HIGH_VALUE.  If
-   LOW_VALUE and HIGH_VALUE are both NULL_TREE then this case label is
-   actually a `default' label.  If only HIGH_VALUE is NULL_TREE, then
-   case label was declared using the usual C/C++ syntax, rather than
-   the GNU case range extension.  CASES is a tree containing all the
-   case ranges processed so far; COND is the condition for the
-   switch-statement itself.  Returns the CASE_LABEL_EXPR created, or
-   ERROR_MARK_NODE if no CASE_LABEL_EXPR is created.  */
+/* Process a case label, located at LOC, for the range LOW_VALUE
+   ... HIGH_VALUE.  If LOW_VALUE and HIGH_VALUE are both NULL_TREE
+   then this case label is actually a `default' label.  If only
+   HIGH_VALUE is NULL_TREE, then case label was declared using the
+   usual C/C++ syntax, rather than the GNU case range extension.
+   CASES is a tree containing all the case ranges processed so far;
+   COND is the condition for the switch-statement itself.  Returns the
+   CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR
+   is created.  */
 
 tree
 
 tree
-c_add_case_label (splay_tree cases, tree cond, tree orig_type,
+c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
                  tree low_value, tree high_value)
 {
   tree type;
                  tree low_value, tree high_value)
 {
   tree type;
@@ -4676,7 +5254,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
   splay_tree_node node;
 
   /* Create the LABEL_DECL itself.  */
   splay_tree_node node;
 
   /* Create the LABEL_DECL itself.  */
-  label = create_artificial_label ();
+  label = create_artificial_label (loc);
 
   /* If there was an error processing the switch condition, bail now
      before we get more confused.  */
 
   /* If there was an error processing the switch condition, bail now
      before we get more confused.  */
@@ -4688,13 +5266,13 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
       || (high_value && TREE_TYPE (high_value)
          && POINTER_TYPE_P (TREE_TYPE (high_value))))
     {
       || (high_value && TREE_TYPE (high_value)
          && POINTER_TYPE_P (TREE_TYPE (high_value))))
     {
-      error ("pointers are not permitted as case values");
+      error_at (loc, "pointers are not permitted as case values");
       goto error_out;
     }
 
   /* Case ranges are a GNU extension.  */
   if (high_value)
       goto error_out;
     }
 
   /* Case ranges are a GNU extension.  */
   if (high_value)
-    pedwarn (input_location, OPT_pedantic, 
+    pedwarn (loc, OPT_pedantic, 
             "range expressions in switch statements are non-standard");
 
   type = TREE_TYPE (cond);
             "range expressions in switch statements are non-standard");
 
   type = TREE_TYPE (cond);
@@ -4721,7 +5299,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
       if (tree_int_cst_equal (low_value, high_value))
        high_value = NULL_TREE;
       else if (!tree_int_cst_lt (low_value, high_value))
       if (tree_int_cst_equal (low_value, high_value))
        high_value = NULL_TREE;
       else if (!tree_int_cst_lt (low_value, high_value))
-       warning (0, "empty range specified");
+       warning_at (loc, 0, "empty range specified");
     }
 
   /* See if the case is in range of the type of the original testing
     }
 
   /* See if the case is in range of the type of the original testing
@@ -4781,24 +5359,26 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
 
       if (high_value)
        {
 
       if (high_value)
        {
-         error ("duplicate (or overlapping) case value");
-         error ("%Jthis is the first entry overlapping that value", duplicate);
+         error_at (loc, "duplicate (or overlapping) case value");
+         error_at (DECL_SOURCE_LOCATION (duplicate),
+                   "this is the first entry overlapping that value");
        }
       else if (low_value)
        {
        }
       else if (low_value)
        {
-         error ("duplicate case value") ;
-         error ("%Jpreviously used here", duplicate);
+         error_at (loc, "duplicate case value") ;
+         error_at (DECL_SOURCE_LOCATION (duplicate), "previously used here");
        }
       else
        {
        }
       else
        {
-         error ("multiple default labels in one switch");
-         error ("%Jthis is the first default label", duplicate);
+         error_at (loc, "multiple default labels in one switch");
+         error_at (DECL_SOURCE_LOCATION (duplicate),
+                   "this is the first default label");
        }
       goto error_out;
     }
 
   /* Add a CASE_LABEL to the statement-tree.  */
        }
       goto error_out;
     }
 
   /* Add a CASE_LABEL to the statement-tree.  */
-  case_label = add_stmt (build_case_label (low_value, high_value, label));
+  case_label = add_stmt (build_case_label (loc, low_value, high_value, label));
   /* Register this case label in the splay tree.  */
   splay_tree_insert (cases,
                     (splay_tree_key) low_value,
   /* Register this case label in the splay tree.  */
   splay_tree_insert (cases,
                     (splay_tree_key) low_value,
@@ -4812,8 +5392,8 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
      that just leads to duplicates and thence to failure later on.  */
   if (!cases->root)
     {
      that just leads to duplicates and thence to failure later on.  */
   if (!cases->root)
     {
-      tree t = create_artificial_label ();
-      add_stmt (build_stmt (LABEL_EXPR, t));
+      tree t = create_artificial_label (loc);
+      add_stmt (build_stmt (loc, LABEL_EXPR, t));
     }
   return error_mark_node;
 }
     }
   return error_mark_node;
 }
@@ -4899,7 +5479,6 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
   splay_tree_node default_node;
   splay_tree_node node;
   tree chain;
   splay_tree_node default_node;
   splay_tree_node node;
   tree chain;
-  int saved_warn_switch;
 
   if (!warn_switch && !warn_switch_enum && !warn_switch_default)
     return;
 
   if (!warn_switch && !warn_switch_enum && !warn_switch_default)
     return;
@@ -4913,15 +5492,15 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
   if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
     return;
 
   if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
     return;
 
-  /* If the switch expression was an enumerated type, check that
-     exactly all enumeration literals are covered by the cases.
-     The check is made when -Wswitch was specified and there is no
-     default case, or when -Wswitch-enum was specified.  */
-
-  if (!warn_switch_enum
-      && !(warn_switch && !default_node))
+  /* From here on, we only care about -Wswitch and -Wswitch-enum.  */
+  if (!warn_switch_enum && !warn_switch)
     return;
 
     return;
 
+  /* Check the cases.  Warn about case values which are not members of
+     the enumerated type.  For -Wswitch-enum, or for -Wswitch when
+     there is no default case, check that exactly all enumeration
+     literals are covered by the cases.  */
+
   /* Clearing COND if it is not an integer constant simplifies
      the tests inside the loop below.  */
   if (TREE_CODE (cond) != INTEGER_CST)
   /* Clearing COND if it is not an integer constant simplifies
      the tests inside the loop below.  */
   if (TREE_CODE (cond) != INTEGER_CST)
@@ -4972,13 +5551,15 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
        continue;
 
       /* If there is a default_node, the only relevant option is
        continue;
 
       /* If there is a default_node, the only relevant option is
-        Wswitch-enum. Otherwise, if both are enabled then we prefer
+        Wswitch-enum.  Otherwise, if both are enabled then we prefer
         to warn using -Wswitch because -Wswitch is enabled by -Wall
         while -Wswitch-enum is explicit.  */
         to warn using -Wswitch because -Wswitch is enabled by -Wall
         while -Wswitch-enum is explicit.  */
-      warning ((default_node || !warn_switch) 
-              ? OPT_Wswitch_enum : OPT_Wswitch,
-              "%Henumeration value %qE not handled in switch",
-              &switch_location, TREE_PURPOSE (chain));
+      warning_at (switch_location,
+                 (default_node || !warn_switch
+                  ? OPT_Wswitch_enum
+                  : OPT_Wswitch),
+                 "enumeration value %qE not handled in switch",
+                 TREE_PURPOSE (chain));
     }
 
   /* Warn if there are case expressions that don't correspond to
     }
 
   /* Warn if there are case expressions that don't correspond to
@@ -4990,16 +5571,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
      every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
      above.  This scan also resets those fields.  */
 
      every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
      above.  This scan also resets those fields.  */
 
-  /* If there is a default_node, the only relevant option is
-     Wswitch-enum. Otherwise, if both are enabled then we prefer
-     to warn using -Wswitch because -Wswitch is enabled by -Wall
-     while -Wswitch-enum is explicit.  */
-  saved_warn_switch = warn_switch;
-  if (default_node)
-    warn_switch = 0;
   splay_tree_foreach (cases, match_case_to_enum, type);
   splay_tree_foreach (cases, match_case_to_enum, type);
-  warn_switch = saved_warn_switch;
-
 }
 
 /* Finish an expression taking the address of LABEL (an
 }
 
 /* Finish an expression taking the address of LABEL (an
@@ -5032,43 +5604,6 @@ finish_label_address_expr (tree label, location_t loc)
 
   return result;
 }
 
   return result;
 }
-
-/* Hook used by expand_expr to expand language-specific tree codes.  */
-/* The only things that should go here are bits needed to expand
-   constant initializers.  Everything else should be handled by the
-   gimplification routines.  */
-
-rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
-              int modifiera /* Actually enum expand_modifier.  */,
-              rtx *alt_rtl)
-{
-  enum expand_modifier modifier = (enum expand_modifier) modifiera;
-  switch (TREE_CODE (exp))
-    {
-    case COMPOUND_LITERAL_EXPR:
-      {
-       /* Initialize the anonymous variable declared in the compound
-          literal, then return the variable.  */
-       tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
-       emit_local_var (decl);
-       return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Hook used by staticp to handle language-specific tree codes.  */
-
-tree
-c_staticp (tree exp)
-{
-  return (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
-         && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp))
-         ? exp : NULL);
-}
 \f
 
 /* Given a boolean expression ARG, return a tree representing an increment
 \f
 
 /* Given a boolean expression ARG, return a tree representing an increment
@@ -5110,8 +5645,8 @@ boolean_increment (enum tree_code code, tree arg)
   return val;
 }
 \f
   return val;
 }
 \f
-/* Built-in macros for stddef.h, that require macros defined in this
-   file.  */
+/* Built-in macros for stddef.h and stdint.h, that require macros
+   defined in this file.  */
 void
 c_stddef_cpp_builtins(void)
 {
 void
 c_stddef_cpp_builtins(void)
 {
@@ -5123,6 +5658,60 @@ c_stddef_cpp_builtins(void)
   builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
   builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
   builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
   builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
   builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
   builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
+  if (SIG_ATOMIC_TYPE)
+    builtin_define_with_value ("__SIG_ATOMIC_TYPE__", SIG_ATOMIC_TYPE, 0);
+  if (INT8_TYPE)
+    builtin_define_with_value ("__INT8_TYPE__", INT8_TYPE, 0);
+  if (INT16_TYPE)
+    builtin_define_with_value ("__INT16_TYPE__", INT16_TYPE, 0);
+  if (INT32_TYPE)
+    builtin_define_with_value ("__INT32_TYPE__", INT32_TYPE, 0);
+  if (INT64_TYPE)
+    builtin_define_with_value ("__INT64_TYPE__", INT64_TYPE, 0);
+  if (UINT8_TYPE)
+    builtin_define_with_value ("__UINT8_TYPE__", UINT8_TYPE, 0);
+  if (UINT16_TYPE)
+    builtin_define_with_value ("__UINT16_TYPE__", UINT16_TYPE, 0);
+  if (UINT32_TYPE)
+    builtin_define_with_value ("__UINT32_TYPE__", UINT32_TYPE, 0);
+  if (UINT64_TYPE)
+    builtin_define_with_value ("__UINT64_TYPE__", UINT64_TYPE, 0);
+  if (INT_LEAST8_TYPE)
+    builtin_define_with_value ("__INT_LEAST8_TYPE__", INT_LEAST8_TYPE, 0);
+  if (INT_LEAST16_TYPE)
+    builtin_define_with_value ("__INT_LEAST16_TYPE__", INT_LEAST16_TYPE, 0);
+  if (INT_LEAST32_TYPE)
+    builtin_define_with_value ("__INT_LEAST32_TYPE__", INT_LEAST32_TYPE, 0);
+  if (INT_LEAST64_TYPE)
+    builtin_define_with_value ("__INT_LEAST64_TYPE__", INT_LEAST64_TYPE, 0);
+  if (UINT_LEAST8_TYPE)
+    builtin_define_with_value ("__UINT_LEAST8_TYPE__", UINT_LEAST8_TYPE, 0);
+  if (UINT_LEAST16_TYPE)
+    builtin_define_with_value ("__UINT_LEAST16_TYPE__", UINT_LEAST16_TYPE, 0);
+  if (UINT_LEAST32_TYPE)
+    builtin_define_with_value ("__UINT_LEAST32_TYPE__", UINT_LEAST32_TYPE, 0);
+  if (UINT_LEAST64_TYPE)
+    builtin_define_with_value ("__UINT_LEAST64_TYPE__", UINT_LEAST64_TYPE, 0);
+  if (INT_FAST8_TYPE)
+    builtin_define_with_value ("__INT_FAST8_TYPE__", INT_FAST8_TYPE, 0);
+  if (INT_FAST16_TYPE)
+    builtin_define_with_value ("__INT_FAST16_TYPE__", INT_FAST16_TYPE, 0);
+  if (INT_FAST32_TYPE)
+    builtin_define_with_value ("__INT_FAST32_TYPE__", INT_FAST32_TYPE, 0);
+  if (INT_FAST64_TYPE)
+    builtin_define_with_value ("__INT_FAST64_TYPE__", INT_FAST64_TYPE, 0);
+  if (UINT_FAST8_TYPE)
+    builtin_define_with_value ("__UINT_FAST8_TYPE__", UINT_FAST8_TYPE, 0);
+  if (UINT_FAST16_TYPE)
+    builtin_define_with_value ("__UINT_FAST16_TYPE__", UINT_FAST16_TYPE, 0);
+  if (UINT_FAST32_TYPE)
+    builtin_define_with_value ("__UINT_FAST32_TYPE__", UINT_FAST32_TYPE, 0);
+  if (UINT_FAST64_TYPE)
+    builtin_define_with_value ("__UINT_FAST64_TYPE__", UINT_FAST64_TYPE, 0);
+  if (INTPTR_TYPE)
+    builtin_define_with_value ("__INTPTR_TYPE__", INTPTR_TYPE, 0);
+  if (UINTPTR_TYPE)
+    builtin_define_with_value ("__UINTPTR_TYPE__", UINTPTR_TYPE, 0);
 }
 
 static void
 }
 
 static void
@@ -5164,7 +5753,9 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     }
   else if (TREE_CODE (*node) == FIELD_DECL)
     {
     }
   else if (TREE_CODE (*node) == FIELD_DECL)
     {
-      if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT)
+      if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
+         /* Still pack bitfields.  */
+         && ! DECL_INITIAL (*node))
        warning (OPT_Wattributes,
                 "%qE attribute ignored for field of type %qT",
                 name, TREE_TYPE (*node));
        warning (OPT_Wattributes,
                 "%qE attribute ignored for field of type %qT",
                 name, TREE_TYPE (*node));
@@ -5711,15 +6302,16 @@ handle_mode_attribute (tree *node, tree name, tree args,
                       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   tree type = *node;
                       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   tree type = *node;
+  tree ident = TREE_VALUE (args);
 
   *no_add_attrs = true;
 
 
   *no_add_attrs = true;
 
-  if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
+  if (TREE_CODE (ident) != IDENTIFIER_NODE)
     warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
     {
       int j;
     warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
     {
       int j;
-      const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
+      const char *p = IDENTIFIER_POINTER (ident);
       int len = strlen (p);
       enum machine_mode mode = VOIDmode;
       tree typefm;
       int len = strlen (p);
       enum machine_mode mode = VOIDmode;
       tree typefm;
@@ -5759,7 +6351,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
       if (mode == VOIDmode)
        {
 
       if (mode == VOIDmode)
        {
-         error ("unknown machine mode %qs", p);
+         error ("unknown machine mode %qE", ident);
          return NULL_TREE;
        }
 
          return NULL_TREE;
        }
 
@@ -5957,7 +6549,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   tree *type = NULL;
   int is_type = 0;
   tree align_expr = (args ? TREE_VALUE (args)
   tree *type = NULL;
   int is_type = 0;
   tree align_expr = (args ? TREE_VALUE (args)
-                    : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+                    : size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT));
   int i;
 
   if (DECL_P (*node))
   int i;
 
   if (DECL_P (*node))
@@ -5979,7 +6571,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       error ("requested alignment is not a power of 2");
       *no_add_attrs = true;
     }
       error ("requested alignment is not a power of 2");
       *no_add_attrs = true;
     }
-  else if (i > HOST_BITS_PER_INT - 2)
+  else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
     {
       error ("requested alignment is too large");
       *no_add_attrs = true;
     {
       error ("requested alignment is too large");
       *no_add_attrs = true;
@@ -6001,7 +6593,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
        *type = build_variant_type_copy (*type);
 
       else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
        *type = build_variant_type_copy (*type);
 
-      TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
+      TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT;
       TYPE_USER_ALIGN (*type) = 1;
     }
   else if (! VAR_OR_FUNCTION_DECL_P (decl)
       TYPE_USER_ALIGN (*type) = 1;
     }
   else if (! VAR_OR_FUNCTION_DECL_P (decl)
@@ -6011,7 +6603,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       *no_add_attrs = true;
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL
       *no_add_attrs = true;
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL
-          && DECL_ALIGN (decl) > (1 << i) * BITS_PER_UNIT)
+          && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
     {
       if (DECL_USER_ALIGN (decl))
        error ("alignment for %q+D was previously specified as %d "
     {
       if (DECL_USER_ALIGN (decl))
        error ("alignment for %q+D was previously specified as %d "
@@ -6024,7 +6616,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
     }
   else
     {
     }
   else
     {
-      DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
+      DECL_ALIGN (decl) = (1U << i) * BITS_PER_UNIT;
       DECL_USER_ALIGN (decl) = 1;
     }
 
       DECL_USER_ALIGN (decl) = 1;
     }
 
@@ -6064,7 +6656,12 @@ handle_alias_attribute (tree *node, tree name, tree args,
 {
   tree decl = *node;
 
 {
   tree decl = *node;
 
-  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+  if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
       || (TREE_CODE (decl) != FUNCTION_DECL 
          && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
       /* A static variable declaration is always a tentative definition,
       || (TREE_CODE (decl) != FUNCTION_DECL 
          && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
       /* A static variable declaration is always a tentative definition,
@@ -6128,7 +6725,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.  */
   /* 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;
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
@@ -6291,8 +6890,18 @@ c_determine_visibility (tree decl)
      visibility_specified depending on #pragma GCC visibility.  */
   if (!DECL_VISIBILITY_SPECIFIED (decl))
     {
      visibility_specified depending on #pragma GCC visibility.  */
   if (!DECL_VISIBILITY_SPECIFIED (decl))
     {
-      DECL_VISIBILITY (decl) = default_visibility;
-      DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+      if (visibility_options.inpragma
+         || DECL_VISIBILITY (decl) != default_visibility)
+       {
+         DECL_VISIBILITY (decl) = default_visibility;
+         DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+         /* If visibility changed and DECL already has DECL_RTL, ensure
+            symbol flags are updated.  */
+         if (((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+              || TREE_CODE (decl) == FUNCTION_DECL)
+             && DECL_RTL_SET_P (decl))
+           make_decl_rtl (decl);
+       }
     }
   return false;
 }
     }
   return false;
 }
@@ -6310,7 +6919,7 @@ handle_tls_model_attribute (tree *node, tree name, tree args,
 
   *no_add_attrs = true;
 
 
   *no_add_attrs = true;
 
-  if (!DECL_THREAD_LOCAL_P (decl))
+  if (TREE_CODE (decl) != VAR_DECL || !DECL_THREAD_LOCAL_P (decl))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
@@ -6493,13 +7102,21 @@ handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
 
 static tree
 handle_deprecated_attribute (tree *node, tree name,
 
 static tree
 handle_deprecated_attribute (tree *node, tree name,
-                            tree ARG_UNUSED (args), int flags,
+                            tree args, int flags,
                             bool *no_add_attrs)
 {
   tree type = NULL_TREE;
   int warn = 0;
   tree what = NULL_TREE;
 
                             bool *no_add_attrs)
 {
   tree type = NULL_TREE;
   int warn = 0;
   tree what = NULL_TREE;
 
+  if (!args)
+    *no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+    {
+      error ("deprecated message is not a string");
+      *no_add_attrs = true;
+    }
+
   if (DECL_P (*node))
     {
       tree decl = *node;
   if (DECL_P (*node))
     {
       tree decl = *node;
@@ -6593,7 +7210,8 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
       || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
       || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT
          && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
-      || !host_integerp (TYPE_SIZE_UNIT (type), 1))
+      || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+      || TREE_CODE (type) == BOOLEAN_TYPE)
     {
       error ("invalid vector type for attribute %qE", name);
       return NULL_TREE;
     {
       error ("invalid vector type for attribute %qE", name);
       return NULL_TREE;
@@ -7025,6 +7643,7 @@ parse_optimize_options (tree args, bool attr_p)
   bool ret = true;
   unsigned opt_argc;
   unsigned i;
   bool ret = true;
   unsigned opt_argc;
   unsigned i;
+  int saved_flag_strict_aliasing;
   const char **opt_argv;
   tree ap;
 
   const char **opt_argv;
   tree ap;
 
@@ -7115,9 +7734,14 @@ parse_optimize_options (tree args, bool attr_p)
   for (i = 1; i < opt_argc; i++)
     opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
 
   for (i = 1; i < opt_argc; i++)
     opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
 
+  saved_flag_strict_aliasing = flag_strict_aliasing;
+
   /* Now parse the options.  */
   decode_options (opt_argc, opt_argv);
 
   /* Now parse the options.  */
   decode_options (opt_argc, opt_argv);
 
+  /* Don't allow changing -fstrict-aliasing.  */
+  flag_strict_aliasing = saved_flag_strict_aliasing;
+
   VEC_truncate (const_char_p, optimize_args, 0);
   return ret;
 }
   VEC_truncate (const_char_p, optimize_args, 0);
   return ret;
 }
@@ -7454,21 +8078,24 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
    TOKEN, which had the associated VALUE.  */
 
 void
    TOKEN, which had the associated VALUE.  */
 
 void
-c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type, 
+              tree value, unsigned char token_flags)
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
   char *message = NULL;
 
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
   char *message = NULL;
 
-  if (token == CPP_EOF)
+  if (token_type == CPP_EOF)
     message = catenate_messages (gmsgid, " at end of input");
     message = catenate_messages (gmsgid, " at end of input");
-  else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16
-          || token == CPP_CHAR32)
+  else if (token_type == CPP_CHAR 
+          || token_type == CPP_WCHAR 
+          || token_type == CPP_CHAR16
+          || token_type == CPP_CHAR32)
     {
       unsigned int val = TREE_INT_CST_LOW (value);
       const char *prefix;
 
     {
       unsigned int val = TREE_INT_CST_LOW (value);
       const char *prefix;
 
-      switch (token)
+      switch (token_type)
        {
        default:
          prefix = "";
        {
        default:
          prefix = "";
@@ -7493,26 +8120,28 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
       free (message);
       message = NULL;
     }
       free (message);
       message = NULL;
     }
-  else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16
-          || token == CPP_STRING32)
+  else if (token_type == CPP_STRING 
+          || token_type == CPP_WSTRING 
+          || token_type == CPP_STRING16
+          || token_type == CPP_STRING32)
     message = catenate_messages (gmsgid, " before string constant");
     message = catenate_messages (gmsgid, " before string constant");
-  else if (token == CPP_NUMBER)
+  else if (token_type == CPP_NUMBER)
     message = catenate_messages (gmsgid, " before numeric constant");
     message = catenate_messages (gmsgid, " before numeric constant");
-  else if (token == CPP_NAME)
+  else if (token_type == CPP_NAME)
     {
       message = catenate_messages (gmsgid, " before %qE");
       error (message, value);
       free (message);
       message = NULL;
     }
     {
       message = catenate_messages (gmsgid, " before %qE");
       error (message, value);
       free (message);
       message = NULL;
     }
-  else if (token == CPP_PRAGMA)
+  else if (token_type == CPP_PRAGMA)
     message = catenate_messages (gmsgid, " before %<#pragma%>");
     message = catenate_messages (gmsgid, " before %<#pragma%>");
-  else if (token == CPP_PRAGMA_EOL)
+  else if (token_type == CPP_PRAGMA_EOL)
     message = catenate_messages (gmsgid, " before end of line");
     message = catenate_messages (gmsgid, " before end of line");
-  else if (token < N_TTYPES)
+  else if (token_type < N_TTYPES)
     {
       message = catenate_messages (gmsgid, " before %qs token");
     {
       message = catenate_messages (gmsgid, " before %qs token");
-      error (message, cpp_type2name (token));
+      error (message, cpp_type2name (token_type, token_flags));
       free (message);
       message = NULL;
     }
       free (message);
       message = NULL;
     }
@@ -7527,6 +8156,68 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
 #undef catenate_messages
 }
 
 #undef catenate_messages
 }
 
+/* Callback from cpp_error for PFILE to print diagnostics from the
+   preprocessor.  The diagnostic is of type LEVEL, at location
+   LOCATION unless this is after lexing and the compiler's location
+   should be used instead, with column number possibly overridden by
+   COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
+   the arguments.  Returns true if a diagnostic was emitted, false
+   otherwise.  */
+
+bool
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+            location_t location, unsigned int column_override,
+            const char *msg, va_list *ap)
+{
+  diagnostic_info diagnostic;
+  diagnostic_t dlevel;
+  int save_warn_system_headers = warn_system_headers;
+  bool ret;
+
+  switch (level)
+    {
+    case CPP_DL_WARNING_SYSHDR:
+      if (flag_no_output)
+       return false;
+      warn_system_headers = 1;
+      /* Fall through.  */
+    case CPP_DL_WARNING:
+      if (flag_no_output)
+       return false;
+      dlevel = DK_WARNING;
+      break;
+    case CPP_DL_PEDWARN:
+      if (flag_no_output && !flag_pedantic_errors)
+       return false;
+      dlevel = DK_PEDWARN;
+      break;
+    case CPP_DL_ERROR:
+      dlevel = DK_ERROR;
+      break;
+    case CPP_DL_ICE:
+      dlevel = DK_ICE;
+      break;
+    case CPP_DL_NOTE:
+      dlevel = DK_NOTE;
+      break;
+    case CPP_DL_FATAL:
+      dlevel = DK_FATAL;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (done_lexing)
+    location = input_location;
+  diagnostic_set_info_translated (&diagnostic, msg, ap,
+                                 location, dlevel);
+  if (column_override)
+    diagnostic_override_column (&diagnostic, column_override);
+  ret = report_diagnostic (&diagnostic);
+  if (level == CPP_DL_WARNING_SYSHDR)
+    warn_system_headers = save_warn_system_headers;
+  return ret;
+}
+
 /* Walk a gimplified function and warn for functions whose return value is
    ignored and attribute((warn_unused_result)) is set.  This is done before
    inlining, so we don't have to worry about that.  */
 /* Walk a gimplified function and warn for functions whose return value is
    ignored and attribute((warn_unused_result)) is set.  This is done before
    inlining, so we don't have to worry about that.  */
@@ -7764,6 +8455,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
              tree curindex;
              unsigned HOST_WIDE_INT cnt;
              constructor_elt *ce;
              tree curindex;
              unsigned HOST_WIDE_INT cnt;
              constructor_elt *ce;
+             bool fold_p = false;
 
              if (VEC_index (constructor_elt, v, 0)->index)
                maxindex = fold_convert (sizetype,
 
              if (VEC_index (constructor_elt, v, 0)->index)
                maxindex = fold_convert (sizetype,
@@ -7775,14 +8467,20 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
                   VEC_iterate (constructor_elt, v, cnt, ce);
                   cnt++)
                {
                   VEC_iterate (constructor_elt, v, cnt, ce);
                   cnt++)
                {
+                 bool curfold_p = false;
                  if (ce->index)
                  if (ce->index)
-                   curindex = fold_convert (sizetype, ce->index);
+                   curindex = ce->index, curfold_p = true;
                  else
                  else
-                   curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
-
+                   {
+                     if (fold_p)
+                       curindex = fold_convert (sizetype, curindex);
+                     curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
+                   }
                  if (tree_int_cst_lt (maxindex, curindex))
                  if (tree_int_cst_lt (maxindex, curindex))
-                   maxindex = curindex;
+                   maxindex = curindex, fold_p = curfold_p;
                }
                }
+              if (fold_p)
+                maxindex = fold_convert (sizetype, maxindex);
            }
        }
       else
            }
        }
       else
@@ -7872,18 +8570,18 @@ builtin_type_for_size (int size, bool unsignedp)
    Returns 0 if an error is encountered.  */
 
 static int
    Returns 0 if an error is encountered.  */
 
 static int
-sync_resolve_size (tree function, tree params)
+sync_resolve_size (tree function, VEC(tree,gc) *params)
 {
   tree type;
   int size;
 
 {
   tree type;
   int size;
 
-  if (params == NULL)
+  if (VEC_empty (tree, params))
     {
       error ("too few arguments to function %qE", function);
       return 0;
     }
 
     {
       error ("too few arguments to function %qE", function);
       return 0;
     }
 
-  type = TREE_TYPE (TREE_VALUE (params));
+  type = TREE_TYPE (VEC_index (tree, params, 0));
   if (TREE_CODE (type) != POINTER_TYPE)
     goto incompatible;
 
   if (TREE_CODE (type) != POINTER_TYPE)
     goto incompatible;
 
@@ -7906,27 +8604,29 @@ sync_resolve_size (tree function, tree params)
    was encountered; true on success.  */
 
 static bool
    was encountered; true on success.  */
 
 static bool
-sync_resolve_params (tree orig_function, tree function, tree params)
+sync_resolve_params (tree orig_function, tree function, VEC(tree, gc) *params)
 {
   tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
   tree ptype;
   int number;
 {
   tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
   tree ptype;
   int number;
+  unsigned int parmnum;
 
   /* We've declared the implementation functions to use "volatile void *"
      as the pointer parameter, so we shouldn't get any complaints from the
      call to check_function_arguments what ever type the user used.  */
   arg_types = TREE_CHAIN (arg_types);
 
   /* We've declared the implementation functions to use "volatile void *"
      as the pointer parameter, so we shouldn't get any complaints from the
      call to check_function_arguments what ever type the user used.  */
   arg_types = TREE_CHAIN (arg_types);
-  ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
   number = 2;
 
   /* For the rest of the values, we need to cast these to FTYPE, so that we
      don't get warnings for passing pointer types, etc.  */
   number = 2;
 
   /* For the rest of the values, we need to cast these to FTYPE, so that we
      don't get warnings for passing pointer types, etc.  */
+  parmnum = 0;
   while (arg_types != void_list_node)
     {
       tree val;
 
   while (arg_types != void_list_node)
     {
       tree val;
 
-      params = TREE_CHAIN (params);
-      if (params == NULL)
+      ++parmnum;
+      if (VEC_length (tree, params) <= parmnum)
        {
          error ("too few arguments to function %qE", orig_function);
          return false;
        {
          error ("too few arguments to function %qE", orig_function);
          return false;
@@ -7935,10 +8635,10 @@ sync_resolve_params (tree orig_function, tree function, tree params)
       /* ??? Ideally for the first conversion we'd use convert_for_assignment
         so that we get warnings for anything that doesn't match the pointer
         type.  This isn't portable across the C and C++ front ends atm.  */
       /* ??? Ideally for the first conversion we'd use convert_for_assignment
         so that we get warnings for anything that doesn't match the pointer
         type.  This isn't portable across the C and C++ front ends atm.  */
-      val = TREE_VALUE (params);
+      val = VEC_index (tree, params, parmnum);
       val = convert (ptype, val);
       val = convert (TREE_VALUE (arg_types), val);
       val = convert (ptype, val);
       val = convert (TREE_VALUE (arg_types), val);
-      TREE_VALUE (params) = val;
+      VEC_replace (tree, params, parmnum, val);
 
       arg_types = TREE_CHAIN (arg_types);
       number++;
 
       arg_types = TREE_CHAIN (arg_types);
       number++;
@@ -7948,7 +8648,7 @@ sync_resolve_params (tree orig_function, tree function, tree params)
      being "an optional list of variables protected by the memory barrier".
      No clue what that's supposed to mean, precisely, but we consider all
      call-clobbered variables to be protected so we're safe.  */
      being "an optional list of variables protected by the memory barrier".
      No clue what that's supposed to mean, precisely, but we consider all
      call-clobbered variables to be protected so we're safe.  */
-  TREE_CHAIN (params) = NULL;
+  VEC_truncate (tree, params, parmnum + 1);
 
   return true;
 }
 
   return true;
 }
@@ -7958,9 +8658,9 @@ sync_resolve_params (tree orig_function, tree function, tree params)
    PARAMS.  */
 
 static tree
    PARAMS.  */
 
 static tree
-sync_resolve_return (tree params, tree result)
+sync_resolve_return (tree first_param, tree result)
 {
 {
-  tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  tree ptype = TREE_TYPE (TREE_TYPE (first_param));
   ptype = TYPE_MAIN_VARIANT (ptype);
   return convert (ptype, result);
 }
   ptype = TYPE_MAIN_VARIANT (ptype);
   return convert (ptype, result);
 }
@@ -7969,13 +8669,15 @@ sync_resolve_return (tree params, tree result)
    function should be called immediately after parsing the call expression
    before surrounding code has committed to the type of the expression.
 
    function should be called immediately after parsing the call expression
    before surrounding code has committed to the type of the expression.
 
+   LOC is the location of the builtin call.
+
    FUNCTION is the DECL that has been invoked; it is known to be a builtin.
    PARAMS is the argument list for the call.  The return value is non-null
    when expansion is complete, and null if normal processing should
    continue.  */
 
 tree
    FUNCTION is the DECL that has been invoked; it is known to be a builtin.
    PARAMS is the argument list for the call.  The return value is non-null
    when expansion is complete, and null if normal processing should
    continue.  */
 
 tree
-resolve_overloaded_builtin (tree function, tree params)
+resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
 {
   enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
   switch (DECL_BUILT_IN_CLASS (function))
 {
   enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
   switch (DECL_BUILT_IN_CLASS (function))
@@ -7984,7 +8686,7 @@ resolve_overloaded_builtin (tree function, tree params)
       break;
     case BUILT_IN_MD:
       if (targetm.resolve_overloaded_builtin)
       break;
     case BUILT_IN_MD:
       if (targetm.resolve_overloaded_builtin)
-       return targetm.resolve_overloaded_builtin (function, params);
+       return targetm.resolve_overloaded_builtin (loc, function, params);
       else
        return NULL_TREE;
     default:
       else
        return NULL_TREE;
     default:
@@ -8012,7 +8714,7 @@ resolve_overloaded_builtin (tree function, tree params)
     case BUILT_IN_LOCK_RELEASE_N:
       {
        int n = sync_resolve_size (function, params);
     case BUILT_IN_LOCK_RELEASE_N:
       {
        int n = sync_resolve_size (function, params);
-       tree new_function, result;
+       tree new_function, first_param, result;
 
        if (n == 0)
          return error_mark_node;
 
        if (n == 0)
          return error_mark_node;
@@ -8021,10 +8723,11 @@ resolve_overloaded_builtin (tree function, tree params)
        if (!sync_resolve_params (function, new_function, params))
          return error_mark_node;
 
        if (!sync_resolve_params (function, new_function, params))
          return error_mark_node;
 
-       result = build_function_call (new_function, params);
+       first_param = VEC_index (tree, params, 0);
+       result = build_function_call_vec (loc, new_function, params, NULL);
        if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
            && orig_code != BUILT_IN_LOCK_RELEASE_N)
        if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
            && orig_code != BUILT_IN_LOCK_RELEASE_N)
-         result = sync_resolve_return (params, result);
+         result = sync_resolve_return (first_param, result);
 
        return result;
       }
 
        return result;
       }
@@ -8094,94 +8797,134 @@ 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
 /* 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
 
 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_left,
+                       enum tree_code code_right, tree arg_right)
 {
   if (!warn_parentheses)
     return;
 
 {
   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,
        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,
        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,
       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 */
       /* 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,
        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,
       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 */
       /* 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,
        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,
        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 */
       /* 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,
        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,
       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
+               && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
+              || (TREE_CODE_CLASS (code_right) == tcc_comparison
+                  && code_right != NE_EXPR && code_right != EQ_EXPR
+                  && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
+       warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
                 "have their mathematical meaning");
                 "have their mathematical meaning");
+      return;
     }
     }
+#undef NOT_A_BOOLEAN_EXPR_P
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */
@@ -8202,31 +8945,35 @@ warn_for_unused_label (tree label)
 struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
 #endif
 
 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
 
 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
      floating-point type, since we consider 0.0/0.0 a valid way of
      generating a NaN.  */
 {
   /* 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
      floating-point type, since we consider 0.0/0.0 a valid way of
      generating a NaN.  */
-  if (skip_evaluation == 0
+  if (c_inhibit_evaluation_warnings == 0
       && (integer_zerop (divisor) || fixed_zerop (divisor)))
       && (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
 }
 
 /* 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 
 
    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)
 {
                       tree op0, tree op1, 
                       tree result_type, enum tree_code resultcode)
 {
@@ -8239,10 +8986,11 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
       && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
       && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
       && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
       && 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)))
+        != 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,
     }
 
   /* Do not warn if the comparison is being done in a signed type,
@@ -8255,9 +9003,9 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
     /* OK */;
   else
     {
     /* OK */;
   else
     {
-      tree sop, uop;
+      tree sop, uop, base_type;
       bool ovf;
       bool ovf;
-      
+
       if (op0_signed)
         sop = orig_op0, uop = orig_op1;
       else 
       if (op0_signed)
         sop = orig_op0, uop = orig_op1;
       else 
@@ -8265,6 +9013,8 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
 
       STRIP_TYPE_NOPS (sop); 
       STRIP_TYPE_NOPS (uop);
 
       STRIP_TYPE_NOPS (sop); 
       STRIP_TYPE_NOPS (uop);
+      base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
+                  ? TREE_TYPE (result_type) : result_type);
 
       /* Do not warn if the signed quantity is an unsuffixed integer
          literal (or some static constant expression involving such
 
       /* Do not warn if the signed quantity is an unsuffixed integer
          literal (or some static constant expression involving such
@@ -8277,7 +9027,7 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
          in the result if the result were signed.  */
       else if (TREE_CODE (uop) == INTEGER_CST
                && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
          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)))
+              && int_fits_type_p (uop, c_common_signed_type (base_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
         /* 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
@@ -8285,11 +9035,12 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
       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)),
       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)))
+                                  c_common_signed_type (base_type)))
         /* OK */;
       else 
         /* 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
     }
   
   /* Warn if two unsigned values are being compared in a size larger
@@ -8342,8 +9093,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, 
                             "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");
                }
             }
         }
                }
             }
         }
@@ -8352,9 +9103,146 @@ warn_for_sign_compare (tree orig_op0, tree orig_op1,
                    < TYPE_PRECISION (result_type))
                && (TYPE_PRECISION (TREE_TYPE (op1))
                    < TYPE_PRECISION (result_type)))
                    < 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");
     }
 }
 
                  "comparison of promoted ~unsigned with unsigned");
     }
 }
 
+/* Setup a TYPE_DECL node as a typedef representation.
+
+   X is a TYPE_DECL for a typedef statement.  Create a brand new
+   ..._TYPE node (which will be just a variant of the existing
+   ..._TYPE node with identical properties) and then install X
+   as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
+
+   The whole point here is to end up with a situation where each
+   and every ..._TYPE node the compiler creates will be uniquely
+   associated with AT MOST one node representing a typedef name.
+   This way, even though the compiler substitutes corresponding
+   ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
+   early on, later parts of the compiler can always do the reverse
+   translation and get back the corresponding typedef name.  For
+   example, given:
+
+       typedef struct S MY_TYPE;
+       MY_TYPE object;
+
+   Later parts of the compiler might only know that `object' was of
+   type `struct S' if it were not for code just below.  With this
+   code however, later parts of the compiler see something like:
+
+       struct S' == struct S
+       typedef struct S' MY_TYPE;
+       struct S' object;
+
+    And they can then deduce (from the node for type struct S') that
+    the original object declaration was:
+
+               MY_TYPE object;
+
+    Being able to do this is important for proper support of protoize,
+    and also for generating precise symbolic debugging information
+    which takes full account of the programmer's (typedef) vocabulary.
+
+    Obviously, we don't want to generate a duplicate ..._TYPE node if
+    the TYPE_DECL node that we are now processing really represents a
+    standard built-in type.  */
+
+void
+set_underlying_type (tree x)
+{
+  if (x == error_mark_node)
+    return;
+  if (DECL_IS_BUILTIN (x))
+    {
+      if (TYPE_NAME (TREE_TYPE (x)) == 0)
+       TYPE_NAME (TREE_TYPE (x)) = x;
+    }
+  else if (TREE_TYPE (x) != error_mark_node
+          && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
+    {
+      tree tt = TREE_TYPE (x);
+      DECL_ORIGINAL_TYPE (x) = tt;
+      tt = build_variant_type_copy (tt);
+      TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
+      TYPE_NAME (tt) = x;
+      TREE_USED (tt) = TREE_USED (x);
+      TREE_TYPE (x) = tt;
+    }
+}
+
+/* Returns true if X is a typedef decl.  */
+
+bool
+is_typedef_decl (tree x)
+{
+  return (x && TREE_CODE (x) == TYPE_DECL
+          && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
+}
+
+/* The C and C++ parsers both use vectors to hold function arguments.
+   For efficiency, we keep a cache of unused vectors.  This is the
+   cache.  */
+
+typedef VEC(tree,gc)* tree_gc_vec;
+DEF_VEC_P(tree_gc_vec);
+DEF_VEC_ALLOC_P(tree_gc_vec,gc);
+static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
+
+/* Return a new vector from the cache.  If the cache is empty,
+   allocate a new vector.  These vectors are GC'ed, so it is OK if the
+   pointer is not released..  */
+
+VEC(tree,gc) *
+make_tree_vector (void)
+{
+  if (!VEC_empty (tree_gc_vec, tree_vector_cache))
+    return VEC_pop (tree_gc_vec, tree_vector_cache);
+  else
+    {
+      /* Passing 0 to VEC_alloc returns NULL, and our callers require
+        that we always return a non-NULL value.  The vector code uses
+        4 when growing a NULL vector, so we do too.  */
+      return VEC_alloc (tree, gc, 4);
+    }
+}
+
+/* Release a vector of trees back to the cache.  */
+
+void
+release_tree_vector (VEC(tree,gc) *vec)
+{
+  if (vec != NULL)
+    {
+      VEC_truncate (tree, vec, 0);
+      VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
+    }
+}
+
+/* Get a new tree vector holding a single tree.  */
+
+VEC(tree,gc) *
+make_tree_vector_single (tree t)
+{
+  VEC(tree,gc) *ret = make_tree_vector ();
+  VEC_quick_push (tree, ret, t);
+  return ret;
+}
+
+/* Get a new tree vector which is a copy of an existing one.  */
+
+VEC(tree,gc) *
+make_tree_vector_copy (const VEC(tree,gc) *orig)
+{
+  VEC(tree,gc) *ret;
+  unsigned int ix;
+  tree t;
+
+  ret = make_tree_vector ();
+  VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
+  for (ix = 0; VEC_iterate (tree, orig, ix, t); ++ix)
+    VEC_quick_push (tree, ret, t);
+  return ret;
+}
+
 #include "gt-c-common.h"
 #include "gt-c-common.h"