OSDN Git Service

PR c++/36625
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 84dea11..ac11367 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,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
 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 "diagnostic.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 "diagnostic.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 "libfuncs.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.
 
@@ -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 signed_wchar_type_node;
-       tree unsigned_wchar_type_node;
 
        tree char16_type_node;
        tree char32_type_node;
@@ -473,15 +419,20 @@ int flag_enforce_eh_specs = 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;
 
-/* Maximum template instantiation depth.  This limit is rather
-   arbitrary, but it exists to limit the time it takes to notice
-   infinite template instantiations.  */
+/* Maximum template instantiation depth.  This limit exists to limit the
+   time it takes to notice infinite template instantiations; the default
+   value of 1024 is likely to be in the next C++ standard.  */
 
-int max_tinst_depth = 500;
+int max_tinst_depth = 1024;
 
 
 
@@ -489,11 +440,15 @@ int max_tinst_depth = 500;
    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 the expression being parsed will never be evaluated.
-   This is a count, since unevaluated expressions can nest.  */
-int skip_evaluation;
+/* Nonzero means don't warn about problems that occur when the code is
+   executed.  */
+int c_inhibit_evaluation_warnings;
+
+/* 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
@@ -516,6 +471,7 @@ const struct fname_var_t fname_vars[] =
   {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 *);
 
@@ -526,6 +482,7 @@ static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
 static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
 static tree handle_always_inline_attribute (tree *, tree, tree, int,
                                            bool *);
 static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
@@ -600,6 +557,7 @@ const struct c_common_resword c_common_reswords[] =
 {
   { "_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 },
@@ -641,6 +599,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__is_enum",       RID_IS_ENUM,    D_CXXONLY },
   { "__is_pod",                RID_IS_POD,     D_CXXONLY },
   { "__is_polymorphic",        RID_IS_POLYMORPHIC, D_CXXONLY },
+  { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
+  { "__is_trivial",     RID_IS_TRIVIAL, D_CXXONLY },
   { "__is_union",      RID_IS_UNION,   D_CXXONLY },
   { "__imag",          RID_IMAGPART,   0 },
   { "__imag__",                RID_IMAGPART,   0 },
@@ -659,6 +619,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__typeof__",      RID_TYPEOF,     0 },
   { "__volatile",      RID_VOLATILE,   0 },
   { "__volatile__",    RID_VOLATILE,   0 },
+  { "alignof",         RID_ALIGNOF,    D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "asm",             RID_ASM,        D_ASM },
   { "auto",            RID_AUTO,       0 },
   { "bool",            RID_BOOL,       D_CXXONLY | D_CXXWARN },
@@ -670,6 +631,7 @@ const struct c_common_resword c_common_reswords[] =
   { "char32_t",                RID_CHAR32,     D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "class",           RID_CLASS,      D_CXX_OBJC | D_CXXWARN },
   { "const",           RID_CONST,      0 },
+  { "constexpr",       RID_CONSTEXPR,  D_CXXONLY | D_CXX0X | D_CXXWARN },
   { "const_cast",      RID_CONSTCAST,  D_CXXONLY | D_CXXWARN },
   { "continue",                RID_CONTINUE,   0 },
   { "decltype",         RID_DECLTYPE,   D_CXXONLY | D_CXX0X | D_CXXWARN },
@@ -748,6 +710,11 @@ const struct c_common_resword c_common_reswords[] =
   { "inout",           RID_INOUT,              D_OBJC },
   { "oneway",          RID_ONEWAY,             D_OBJC },
   { "out",             RID_OUT,                D_OBJC },
+
+#ifdef TARGET_ADDR_SPACE_KEYWORDS
+  /* Any address space keywords recognized by the target.  */
+  TARGET_ADDR_SPACE_KEYWORDS,
+#endif
 };
 
 const unsigned int num_c_common_reswords =
@@ -774,6 +741,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_noreturn_attribute },
   { "noinline",               0, 0, true,  false, false,
                              handle_noinline_attribute },
+  { "noclone",                0, 0, true,  false, false,
+                             handle_noclone_attribute },
   { "always_inline",          0, 0, true,  false, false,
                              handle_always_inline_attribute },
   { "gnu_inline",             0, 0, true,  false, false,
@@ -823,7 +792,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 },
-  { "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 },
@@ -876,6 +845,19 @@ const struct attribute_spec c_common_format_attribute_table[] =
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
+/* Return identifier for address space AS.  */
+const char *
+c_addr_space_name (addr_space_t as)
+{
+  unsigned int i;
+
+  for (i = 0; i < num_c_common_reswords; i++)
+    if (c_common_reswords[i].rid == RID_FIRST_ADDR_SPACE + as)
+      return c_common_reswords[i].word;
+
+  gcc_unreachable ();
+}
+
 /* Push current bindings for the function name VAR_DECLS.  */
 
 void
@@ -1014,7 +996,7 @@ fname_decl (location_t loc, unsigned int rid, tree id)
       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
@@ -1105,6 +1087,452 @@ fix_string_type (tree value)
   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;
+  location_t loc = EXPR_LOCATION (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 ();
+
+  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_loc (loc, 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);
+  int unused_p;
+
+  /* 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);
+      STRIP_TYPE_NOPS (op0);
+      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);
+      STRIP_TYPE_NOPS (op0);
+      op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
+                                  maybe_const_itself);
+      STRIP_TYPE_NOPS (op1);
+      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);
+      STRIP_TYPE_NOPS (op0);
+      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);
+      STRIP_TYPE_NOPS (op1);
+      op1 = decl_constant_value_for_optimization (op1);
+      if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+       ret = in_init
+         ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
+         : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
+      else
+       ret = fold (expr);
+      if (TREE_OVERFLOW_P (ret)
+         && !TREE_OVERFLOW_P (op0)
+         && !TREE_OVERFLOW_P (op1))
+       overflow_warning (EXPR_LOCATION (expr), ret);
+      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);
+      STRIP_TYPE_NOPS (op0);
+      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_loc (loc, code, TREE_TYPE (expr), op0)
+         : fold_build1_loc (loc, 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);
+       }
+      switch (code)
+       {
+       case FIX_TRUNC_EXPR:
+       case FLOAT_EXPR:
+       CASE_CONVERT:
+         /* Don't warn about explicit conversions.  We will already
+            have warned about suspect implicit conversions.  */
+         break;
+
+       default:
+         if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0))
+           overflow_warning (EXPR_LOCATION (expr), ret);
+         break;
+       }
+      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);
+      STRIP_TYPE_NOPS (op0);
+
+      unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
+                         ? truthvalue_false_node
+                         : truthvalue_true_node));
+      c_inhibit_evaluation_warnings += unused_p;
+      op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      STRIP_TYPE_NOPS (op1);
+      c_inhibit_evaluation_warnings -= unused_p;
+
+      if (op0 != orig_op0 || op1 != orig_op1 || in_init)
+       ret = in_init
+         ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
+         : fold_build2_loc (loc, 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);
+
+      STRIP_TYPE_NOPS (op0);
+      c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
+      op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      STRIP_TYPE_NOPS (op1);
+      c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
+
+      c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
+      op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+      STRIP_TYPE_NOPS (op2);
+      c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
+
+      if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
+       ret = fold_build3_loc (loc, 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.
@@ -1114,7 +1542,7 @@ fix_string_type (tree value)
 void
 constant_expression_warning (tree value)
 {
-  if (warn_overflow && pedantic 
+  if (warn_overflow && pedantic
       && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
          || TREE_CODE (value) == FIXED_CST
          || TREE_CODE (value) == VECTOR_CST
@@ -1147,33 +1575,37 @@ constant_expression_error (tree value)
    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:
-      warning (OPT_Woverflow, "integer overflow in expression");
+      warning_at (loc, OPT_Woverflow, "integer overflow in expression");
       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:
-      warning (OPT_Woverflow, "fixed-point overflow in expression");
+      warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
       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)
-       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)
-       warning (OPT_Woverflow, "complex floating point overflow in expression");
+       warning_at (loc, OPT_Woverflow,
+                   "complex floating point overflow in expression");
       break;
 
     default:
@@ -1181,38 +1613,95 @@ 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 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;
+    }
 
-/* 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.  */
+  /* 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;
 
-void
-warn_logical_operator (enum tree_code code, tree arg1, tree
-    arg2)
-{
-  switch (code)
+  /* 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 (UNKNOWN_LOCATION,
+                                       type, lhs, in_p, low, high)))
     {
-      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;
+      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");
     }
 }
 
@@ -1225,6 +1714,10 @@ warn_logical_operator (enum tree_code code, tree arg1, tree
 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)
@@ -1248,7 +1741,7 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
        }
       else
         {
-          /* warn_strict_aliasing >= 3.   This includes the default (3).  
+          /* warn_strict_aliasing >= 3.   This includes the default (3).
              Only warn if the cast is dereferenced immediately.  */
           alias_set_type set1 =
            get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
@@ -1313,7 +1806,7 @@ check_main_parameter_types (tree decl)
        {
        case 1:
          if (TYPE_MAIN_VARIANT (type) != integer_type_node)
-           pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>", 
+           pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
                    decl);
          break;
 
@@ -1351,7 +1844,7 @@ bool
 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;
 
@@ -1369,7 +1862,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
   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;
 
@@ -1408,7 +1901,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
    both args are zero-extended or both are sign-extended.
    Otherwise, we might change the result.
    Eg, (short)-1 | (unsigned short)-1 is (int)-1
-   but calculated in (unsigned short) it would be (unsigned short)-1.  
+   but calculated in (unsigned short) it would be (unsigned short)-1.
 */
 tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
 {
@@ -1423,13 +1916,13 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
      from signed char and that RESULT_TYPE is long long int.
      If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
      like
-     
+
      (long long int) (unsigned int) signed_char
 
      which get_narrower would narrow down to
-     
+
      (unsigned int) signed char
-     
+
      If we do not cast OP0 first, get_narrower would return
      signed_char, which is inconsistent with the case of the
      explicit cast.  */
@@ -1444,7 +1937,7 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
 
   /* Handle the case that OP0 (or OP1) does not *contain* a conversion
      but it *requires* conversion to FINAL_TYPE.  */
-  
+
   if ((TYPE_PRECISION (TREE_TYPE (op0))
        == TYPE_PRECISION (TREE_TYPE (arg0)))
       && TREE_TYPE (op0) != result_type)
@@ -1453,18 +1946,18 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
        == TYPE_PRECISION (TREE_TYPE (arg1)))
       && TREE_TYPE (op1) != result_type)
     unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
-  
+
   /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */
-  
+
   /* For bitwise operations, signedness of nominal type
      does not matter.  Consider only how operands were extended.  */
   if (bitwise)
     uns = unsigned0;
-  
+
   /* Note that in all three cases below we refrain from optimizing
      an unsigned operation on sign-extended args.
      That would not be valid.  */
-  
+
   /* Both args variable: if both extended in same way
      from same width, do it in that width.
      Do it unsigned if args were zero-extended.  */
@@ -1543,7 +2036,7 @@ conversion_warning (tree type, tree expr)
       /* Conversion from boolean to a signed:1 bit-field (which only
         can hold the values 0 and -1) doesn't lose information - but
         it does change the value.  */
-      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) 
+      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
        warning (OPT_Wconversion,
                  "conversion to %qT from boolean expression", type);
       return;
@@ -1564,7 +2057,7 @@ conversion_warning (tree type, tree expr)
                && TREE_CODE (type) == INTEGER_TYPE
                && !int_fits_type_p (expr, type))
         {
-          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type) 
+          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
              && tree_int_cst_sgn (expr) < 0)
            warning (OPT_Wsign_conversion,
                     "negative integer implicitly converted to unsigned type");
@@ -1609,7 +2102,7 @@ conversion_warning (tree type, tree expr)
        tree op1 = TREE_OPERAND (expr, 1);
        tree op2 = TREE_OPERAND (expr, 2);
 
-       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST 
+       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
             || TREE_CODE (op1) == COND_EXPR)
            && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
                || TREE_CODE (op2) == COND_EXPR))
@@ -1636,15 +2129,15 @@ conversion_warning (tree type, tree expr)
          expr_type = TREE_TYPE (expr);
 
          /* Don't warn for short y; short x = ((int)y & 0xff);  */
-         if (TREE_CODE (expr) == BIT_AND_EXPR 
-               || TREE_CODE (expr) == BIT_IOR_EXPR 
+         if (TREE_CODE (expr) == BIT_AND_EXPR
+               || TREE_CODE (expr) == BIT_IOR_EXPR
              || TREE_CODE (expr) == BIT_XOR_EXPR)
            {
              /* If both args were extended from a shortest type,
                 use that type if that is safe.  */
-             expr_type = shorten_binary_op (expr_type, 
-                                            TREE_OPERAND (expr, 0), 
-                                            TREE_OPERAND (expr, 1), 
+             expr_type = shorten_binary_op (expr_type,
+                                            TREE_OPERAND (expr, 0),
+                                            TREE_OPERAND (expr, 1),
                                             /* bitwise */1);
 
              if (TREE_CODE (expr) == BIT_AND_EXPR)
@@ -1662,13 +2155,13 @@ conversion_warning (tree type, tree expr)
                       && int_fits_type_p (op0, c_common_unsigned_type (type)))
                      || (TREE_CODE (op1) == INTEGER_CST
                          && int_fits_type_p (op1, c_common_signed_type (type))
-                         && int_fits_type_p (op1, 
+                         && int_fits_type_p (op1,
                                              c_common_unsigned_type (type))))
                    return;
                  /* If constant is unsigned and fits in the target
                     type, then the result will also fit.  */
                  else if ((TREE_CODE (op0) == INTEGER_CST
-                           && unsigned0 
+                           && unsigned0
                            && int_fits_type_p (op0, type))
                           || (TREE_CODE (op1) == INTEGER_CST
                               && unsigned1
@@ -1677,7 +2170,7 @@ conversion_warning (tree type, tree expr)
                }
            }
           /* Warn for integer types converted to smaller integer types.  */
-         if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) 
+         if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
            give_warning = true;
 
          /* When they are the same width but different signedness,
@@ -1699,12 +2192,17 @@ conversion_warning (tree type, tree expr)
       else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == REAL_TYPE)
         {
-          tree type_low_bound = TYPE_MIN_VALUE (expr_type);
-          tree type_high_bound = TYPE_MAX_VALUE (expr_type);
-          REAL_VALUE_TYPE real_low_bound 
-           = real_value_from_int_cst (0, type_low_bound);
-          REAL_VALUE_TYPE real_high_bound 
-           = real_value_from_int_cst (0, type_high_bound);
+         tree type_low_bound, type_high_bound;
+          REAL_VALUE_TYPE real_low_bound, real_high_bound;
+
+         /* Don't warn about char y = 0xff; float x = (int) y;  */
+         expr = get_unwidened (expr, 0);
+         expr_type = TREE_TYPE (expr);
+
+          type_low_bound = TYPE_MIN_VALUE (expr_type);
+          type_high_bound = TYPE_MAX_VALUE (expr_type);
+          real_low_bound = real_value_from_int_cst (0, type_low_bound);
+          real_high_bound = real_value_from_int_cst (0, type_high_bound);
 
           if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
               || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
@@ -1752,7 +2250,7 @@ warnings_for_convert_and_check (tree type, tree expr, tree result)
           else
             conversion_warning (type, expr);
         }
-      else if (!int_fits_type_p (expr, c_common_unsigned_type (type))) 
+      else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
        warning (OPT_Woverflow,
                 "overflow in implicit constant conversion");
       /* No warning for converting 0x80000000 to int.  */
@@ -1783,14 +2281,31 @@ tree
 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 (!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;
 }
@@ -1830,6 +2345,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 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);
@@ -1857,7 +2373,7 @@ add_tlist (struct tlist **to, struct tlist *add, tree exclude_writer, int copy)
       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;
     }
@@ -1884,7 +2400,7 @@ merge_tlist (struct tlist **to, struct tlist *add, int copy)
       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)
@@ -1912,15 +2428,14 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
 
   /* 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)
     {
-      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)
@@ -1952,7 +2467,17 @@ warn_for_collisions (struct tlist *list)
 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
@@ -1998,10 +2523,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
   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)
     {
@@ -2083,7 +2605,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
       {
        call_expr_arg_iterator iter;
        tree arg;
-       tmp_before = tmp_nosp = 0; 
+       tmp_before = tmp_nosp = 0;
        verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE);
        FOR_EACH_CALL_EXPR_ARG (arg, iter, x)
          {
@@ -2114,7 +2636,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)
-         if (t->expr == x)
+         if (candidate_equal_p (t->expr, x))
            break;
 
        if (!t)
@@ -2719,7 +3241,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
 
 #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))
@@ -2749,10 +3271,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
     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.  */
@@ -2787,7 +3306,8 @@ c_register_builtin_type (tree type, const char* name)
 {
   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;
@@ -3170,7 +3690,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning (OPT_Wtype_limits, 
+               warning (OPT_Wtype_limits,
                         "comparison of unsigned expression >= 0 is always true");
              value = truthvalue_true_node;
              break;
@@ -3180,7 +3700,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning (OPT_Wtype_limits, 
+               warning (OPT_Wtype_limits,
                         "comparison of unsigned expression < 0 is always false");
              value = truthvalue_false_node;
              break;
@@ -3212,7 +3732,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
    of pointer PTROP and integer INTOP.  */
 
 tree
-pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
+pointer_int_sum (location_t loc, enum tree_code resultcode,
+                tree ptrop, tree intop)
 {
   tree size_exp, ret;
 
@@ -3221,19 +3742,19 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
-      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
               "pointer of type %<void *%> used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
     {
-      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
               "pointer to a function used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
     {
-      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+      pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
               "pointer to member function used in arithmetic");
       size_exp = integer_one_node;
     }
@@ -3285,24 +3806,73 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
                                             TYPE_UNSIGNED (sizetype)), intop);
 
   /* Replace the integer argument with a suitable product by the object size.
-     Do this multiplication as signed, then convert to the appropriate
-     type for the pointer operation.  */
-  intop = convert (sizetype,
-                  build_binary_op (EXPR_LOCATION (intop),
-                                   MULT_EXPR, intop,
-                                   convert (TREE_TYPE (intop), size_exp), 1));
+     Do this multiplication as signed, then convert to the appropriate type
+     for the pointer operation and disregard an overflow that occured only
+     because of the sign-extension change in the latter conversion.  */
+  {
+    tree t = build_binary_op (loc,
+                             MULT_EXPR, intop,
+                             convert (TREE_TYPE (intop), size_exp), 1);
+    intop = convert (sizetype, t);
+    if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
+      intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
+                                 TREE_INT_CST_HIGH (intop));
+  }
 
   /* Create the sum or difference.  */
   if (resultcode == MINUS_EXPR)
-    intop = fold_build1 (NEGATE_EXPR, sizetype, intop);
+    intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
 
-  ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop);
+  ret = fold_build2_loc (loc, POINTER_PLUS_EXPR, result_type, ptrop, intop);
 
   fold_undefer_and_ignore_overflow_warnings ();
 
   return ret;
 }
 \f
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+   and if NON_CONST is known not to be permitted in an evaluated part
+   of a constant expression.  */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+  bool nowarning = TREE_NO_WARNING (expr);
+  location_t loc = EXPR_LOCATION (expr);
+
+  /* This should never be called for C++.  */
+  if (c_dialect_cxx ())
+    gcc_unreachable ();
+
+  /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING.  */
+  STRIP_TYPE_NOPS (expr);
+  expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+  C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+  if (nowarning)
+    TREE_NO_WARNING (expr) = 1;
+  protected_set_expr_location (expr, loc);
+
+  return expr;
+}
+
+/* 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 = c_wrap_maybe_const (expr, true);
+  return expr;
+}
+
 /* Return whether EXPR is a declaration whose address can never be
    NULL.  */
 
@@ -3341,8 +3911,9 @@ c_common_truthvalue_conversion (location_t location, tree 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));
+      goto ret;
 
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
@@ -3351,18 +3922,20 @@ c_common_truthvalue_conversion (location_t location, tree 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 (location, 
-                                                TREE_OPERAND (expr, 0)),
-                c_common_truthvalue_conversion (location,
-                                                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;
-      return build1 (TREE_CODE (expr), truthvalue_type_node,
-                c_common_truthvalue_conversion (location,
-                                                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;
@@ -3408,14 +3981,17 @@ c_common_truthvalue_conversion (location_t location, tree expr)
          }
 
        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:
-      return build_binary_op (EXPR_LOCATION (expr),
+      expr = build_binary_op (EXPR_LOCATION (expr),
                              (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
                c_common_truthvalue_conversion (location,
@@ -3423,10 +3999,12 @@ c_common_truthvalue_conversion (location_t location, tree expr)
                c_common_truthvalue_conversion (location,
                                                TREE_OPERAND (expr, 1)),
                              0);
+      goto ret;
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
+    case EXCESS_PRECISION_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
       return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
 
@@ -3435,22 +4013,42 @@ c_common_truthvalue_conversion (location_t location, tree 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 
-                       (location, 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
        return c_common_truthvalue_conversion (location,
                                               TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
-      return fold_build3 (COND_EXPR, truthvalue_type_node,
-               TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (location,
-                                               TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (location,
-                                               TREE_OPERAND (expr, 2)));
+      if (c_dialect_cxx ())
+       {
+         expr = fold_build3_loc (location, 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,
@@ -3481,8 +4079,8 @@ c_common_truthvalue_conversion (location_t location, tree expr)
 
   if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
     {
-      tree t = save_expr (expr);
-      return (build_binary_op
+      tree t = c_save_expr (expr);
+      expr = (build_binary_op
              (EXPR_LOCATION (expr),
               (TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
@@ -3493,6 +4091,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
               (location,
                build_unary_op (location, IMAGPART_EXPR, t, 0)),
               0));
+      goto ret;
     }
 
   if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
@@ -3500,12 +4099,14 @@ c_common_truthvalue_conversion (location_t location, tree expr)
       tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
                                          FCONST0 (TYPE_MODE
                                                   (TREE_TYPE (expr))));
-      return build_binary_op (EXPR_LOCATION (expr),
-                             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 (EXPR_LOCATION (expr),
-                         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,
@@ -3550,11 +4151,6 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
          || !POINTER_TYPE_P (type)
          || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
        error ("invalid use of %<restrict%>");
-      else if (flag_strict_aliasing && type == TREE_TYPE (decl))
-       /* Indicate we need to make a unique alias set for this pointer.
-          We can't do it here because it might be pointing to an
-          incomplete type.  */
-       DECL_POINTER_ALIAS_SET (decl) = -2;
     }
 }
 
@@ -3616,6 +4212,15 @@ c_common_get_alias_set (tree t)
   tree u;
   PTR *slot;
 
+  /* For VLAs, use the alias set of the element type rather than the
+     default of alias set 0 for types compared structurally.  */
+  if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t))
+    {
+      if (TREE_CODE (t) == ARRAY_TYPE)
+       return get_alias_set (TREE_TYPE (t));
+      return -1;
+    }
+
   /* Permit type-punning when accessing a union, provided the access
      is directly through the union.  For example, this code does not
      permit taking the address of a union member and then storing
@@ -3746,13 +4351,15 @@ c_common_get_alias_set (tree t)
   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
-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;
@@ -3765,7 +4372,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
       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;
@@ -3778,7 +4385,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
     {
       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;
@@ -3787,17 +4394,17 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
   else if (!COMPLETE_TYPE_P (type))
     {
       if (complain)
-       error ("invalid application of %qs to incomplete type %qT ",
-              op_name, type);
-      value = size_zero_node;
+       error_at (loc, "invalid application of %qs to incomplete type %qT ",
+                 op_name, type);
+      return error_mark_node;
     }
   else
     {
       if (is_sizeof)
        /* Convert in case a char is more than one unit.  */
-       value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                           size_int (TYPE_PRECISION (char_type_node)
-                                     / BITS_PER_UNIT));
+       value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                               size_int (TYPE_PRECISION (char_type_node)
+                                         / BITS_PER_UNIT));
       else
        value = size_int (TYPE_ALIGN_UNIT (type));
     }
@@ -3806,7 +4413,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
      TYPE_IS_SIZETYPE means that certain things (like overflow) will
      never happen.  However, this node should really have type
      `size_t', which is just a typedef for an ordinary integer type.  */
-  value = fold_convert (size_type_node, value);
+  value = fold_convert_loc (loc, size_type_node, value);
   gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
 
   return value;
@@ -3815,10 +4422,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
-   from an "aligned" __attribute__ specification).  */
+   from an "aligned" __attribute__ specification).  LOC is the
+   location of the ALIGNOF operator.  */
 
 tree
-c_alignof_expr (tree expr)
+c_alignof_expr (location_t loc, tree expr)
 {
   tree t;
 
@@ -3828,7 +4436,7 @@ c_alignof_expr (tree expr)
   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
@@ -3851,12 +4459,12 @@ c_alignof_expr (tree expr)
          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
-    return c_alignof (TREE_TYPE (expr));
+    return c_alignof (loc, TREE_TYPE (expr));
 
-  return fold_convert (size_type_node, t);
+  return fold_convert_loc (loc, size_type_node, t);
 }
 \f
 /* Handle C and C++ default attributes.  */
@@ -4044,6 +4652,16 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
     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.  */
 
@@ -4092,31 +4710,41 @@ c_common_nodes_and_builtins (void)
 
   /* 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));
-  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));
-  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));
-  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))
-    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
-  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));
-  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));
-  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));
-  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))
-    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
@@ -4124,12 +4752,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);
-  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);
-  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.
@@ -4151,7 +4781,7 @@ c_common_nodes_and_builtins (void)
 
   /* Only supported decimal floating point extension if the target
      actually supports underlying modes. */
-  if (targetm.scalar_mode_supported_p (SDmode) 
+  if (targetm.scalar_mode_supported_p (SDmode)
       && targetm.scalar_mode_supported_p (DDmode)
       && targetm.scalar_mode_supported_p (TDmode))
     {
@@ -4221,17 +4851,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));
-  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));
-  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
-    (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 ())
@@ -4283,6 +4917,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);
+  underlying_wchar_type_node = wchar_type_node;
   if (c_dialect_cxx ())
     {
       if (TYPE_UNSIGNED (wchar_type_node))
@@ -4291,11 +4926,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);
     }
-  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
@@ -4341,13 +4971,96 @@ c_common_nodes_and_builtins (void)
   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
-    (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
   {
@@ -4357,7 +5070,8 @@ c_common_nodes_and_builtins (void)
     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));
 
       }
@@ -4389,26 +5103,6 @@ c_common_nodes_and_builtins (void)
   memset (builtin_types, 0, sizeof (builtin_types));
 }
 
-/* Look up the function in built_in_decls that corresponds to DECL
-   and set ASMSPEC as its user assembler name.  DECL must be a
-   function decl that declares a builtin.  */
-
-void
-set_builtin_user_assembler_name (tree decl, const char *asmspec)
-{
-  tree builtin;
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
-             && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
-             && asmspec != 0);
-
-  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);
-}
-
 /* The number of named compound-literals generated thus far.  */
 static GTY(()) int compound_literal_number;
 
@@ -4425,9 +5119,11 @@ set_compound_literal_name (tree decl)
 }
 
 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;
 }
 
 
@@ -4609,17 +5305,18 @@ case_compare (splay_tree_key k1, splay_tree_key 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
-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;
@@ -4628,7 +5325,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
   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.  */
@@ -4640,13 +5337,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))))
     {
-      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)
-    pedwarn (input_location, OPT_pedantic, 
+    pedwarn (loc, OPT_pedantic,
             "range expressions in switch statements are non-standard");
 
   type = TREE_TYPE (cond);
@@ -4673,7 +5370,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))
-       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
@@ -4733,24 +5430,26 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
 
       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)
        {
-         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
        {
-         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.  */
-  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,
@@ -4764,8 +5463,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)
     {
-      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;
 }
@@ -4794,13 +5493,15 @@ match_case_to_enum_1 (tree key, tree type, tree label)
              (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
 
   if (TYPE_NAME (type) == 0)
-    warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
-            "%Jcase value %qs not in enumerated type",
-            CASE_LABEL (label), buf);
+    warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
+               warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+               "case value %qs not in enumerated type",
+               buf);
   else
-    warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
-            "%Jcase value %qs not in enumerated type %qT",
-            CASE_LABEL (label), buf, type);
+    warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
+               warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
+               "case value %qs not in enumerated type %qT",
+               buf, type);
 }
 
 /* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
@@ -4851,29 +5552,28 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
   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;
 
   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
   if (!default_node)
-    warning (OPT_Wswitch_default, "%Hswitch missing default case",
-            &switch_location);
+    warning_at (switch_location, OPT_Wswitch_default,
+               "switch missing default case");
 
   /* From here on, we only care about about enumerated types.  */
   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;
 
+  /* 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)
@@ -4924,13 +5624,15 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
        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.  */
-      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
@@ -4942,16 +5644,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.  */
 
-  /* 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);
-  warn_switch = saved_warn_switch;
-
 }
 
 /* Finish an expression taking the address of LABEL (an
@@ -4976,7 +5669,7 @@ finish_label_address_expr (tree label, location_t loc)
     {
       TREE_USED (label) = 1;
       result = build1 (ADDR_EXPR, ptr_type_node, label);
-      /* The current function in not necessarily uninlinable.
+      /* The current function is not necessarily uninlinable.
         Computed gotos are incompatible with inlining, but the value
         here could be used only in a diagnostic, for example.  */
       protected_set_expr_location (result, loc);
@@ -4984,43 +5677,6 @@ finish_label_address_expr (tree label, location_t loc)
 
   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
@@ -5046,11 +5702,11 @@ boolean_increment (enum tree_code code, tree arg)
       break;
     case PREDECREMENT_EXPR:
       val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
-                   invert_truthvalue (arg));
+                   invert_truthvalue_loc (input_location, arg));
       break;
     case POSTDECREMENT_EXPR:
       val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
-                   invert_truthvalue (arg));
+                   invert_truthvalue_loc (input_location, arg));
       arg = save_expr (arg);
       val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
       val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
@@ -5062,8 +5718,8 @@ boolean_increment (enum tree_code code, tree arg)
   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)
 {
@@ -5075,6 +5731,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);
+  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
@@ -5099,6 +5809,17 @@ c_init_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
+/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
+   identifier as an argument, so the front end shouldn't look it up.  */
+
+bool
+attribute_takes_identifier_p (tree attr_id)
+{
+  return (is_attribute_p ("mode", attr_id)
+         || is_attribute_p ("format", attr_id)
+         || is_attribute_p ("cleanup", attr_id));
+}
+
 /* Attribute handlers common to C front ends.  */
 
 /* Handle a "packed" attribute; arguments as in
@@ -5116,7 +5837,9 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     }
   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));
@@ -5272,6 +5995,23 @@ handle_noinline_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* Handle a "noclone" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_noclone_attribute (tree *node, tree name,
+                         tree ARG_UNUSED (args),
+                         int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "always_inline" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -5398,6 +6138,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
     {
       TREE_USED (node) = 1;
       DECL_PRESERVE_P (node) = 1;
+      if (TREE_CODE (node) == VAR_DECL)
+       DECL_READ_P (node) = 1;
     }
   else
     {
@@ -5424,7 +6166,12 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
          || TREE_CODE (decl) == FUNCTION_DECL
          || TREE_CODE (decl) == LABEL_DECL
          || TREE_CODE (decl) == TYPE_DECL)
-       TREE_USED (decl) = 1;
+       {
+         TREE_USED (decl) = 1;
+         if (TREE_CODE (decl) == VAR_DECL
+             || TREE_CODE (decl) == PARM_DECL)
+           DECL_READ_P (decl) = 1;
+       }
       else
        {
          warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -5529,7 +6276,7 @@ handle_transparent_union_attribute (tree *node, tree name,
          *node = type = build_duplicate_type (type);
        }
 
-      TYPE_TRANSPARENT_UNION (type) = 1;
+      TYPE_TRANSPARENT_AGGR (type) = 1;
       return NULL_TREE;
     }
 
@@ -5551,7 +6298,7 @@ get_priority (tree args, bool is_destructor)
 
   if (!args)
     return DEFAULT_INIT_PRIORITY;
-  
+
   if (!SUPPORTS_INIT_PRIORITY)
     {
       if (is_destructor)
@@ -5575,12 +6322,12 @@ get_priority (tree args, bool is_destructor)
       if (is_destructor)
        warning (0,
                 "destructor priorities from 0 to %d are reserved "
-                "for the implementation", 
+                "for the implementation",
                 MAX_RESERVED_INIT_PRIORITY);
       else
        warning (0,
                 "constructor priorities from 0 to %d are reserved "
-                "for the implementation", 
+                "for the implementation",
                 MAX_RESERVED_INIT_PRIORITY);
     }
   return pri;
@@ -5663,15 +6410,16 @@ handle_mode_attribute (tree *node, tree name, tree args,
                       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   tree type = *node;
+  tree ident = TREE_VALUE (args);
 
   *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;
-      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;
@@ -5711,7 +6459,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
       if (mode == VOIDmode)
        {
-         error ("unknown machine mode %qs", p);
+         error ("unknown machine mode %qE", ident);
          return NULL_TREE;
        }
 
@@ -5758,9 +6506,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
       if (POINTER_TYPE_P (type))
        {
+         addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
          tree (*fn)(tree, enum machine_mode, bool);
 
-         if (!targetm.valid_pointer_mode (mode))
+         if (!targetm.addr_space.valid_pointer_mode (mode, as))
            {
              error ("invalid pointer mode %qs", p);
              return NULL_TREE;
@@ -5858,8 +6607,9 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
              && current_function_decl != NULL_TREE
              && !TREE_STATIC (decl))
            {
-             error ("%Jsection attribute cannot be specified for "
-                    "local variables", decl);
+             error_at (DECL_SOURCE_LOCATION (decl),
+                       "section attribute cannot be specified for "
+                       "local variables");
              *no_add_attrs = true;
            }
 
@@ -5891,7 +6641,8 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
     }
   else
     {
-      error ("%Jsection attributes are not supported for this target", *node);
+      error_at (DECL_SOURCE_LOCATION (*node),
+               "section attributes are not supported for this target");
       *no_add_attrs = true;
     }
 
@@ -5909,7 +6660,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)
-                    : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+                    : size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT));
   int i;
 
   if (DECL_P (*node))
@@ -5931,7 +6682,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;
     }
-  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;
@@ -5953,7 +6704,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);
 
-      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)
@@ -5963,7 +6714,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       *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 "
@@ -5976,7 +6727,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
     }
   else
     {
-      DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
+      DECL_ALIGN (decl) = (1U << i) * BITS_PER_UNIT;
       DECL_USER_ALIGN (decl) = 1;
     }
 
@@ -6016,12 +6767,17 @@ handle_alias_attribute (tree *node, tree name, tree args,
 {
   tree decl = *node;
 
-  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
-      || (TREE_CODE (decl) != FUNCTION_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,
         but the alias is a non-tentative definition which overrides.  */
-      || (TREE_CODE (decl) != FUNCTION_DECL 
+      || (TREE_CODE (decl) != FUNCTION_DECL
          && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
     {
       error ("%q+D defined both normally and as an alias", decl);
@@ -6105,8 +6861,8 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else
     {
       if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
-       error ("%Jweakref attribute must appear before alias attribute",
-              *node);
+       error_at (DECL_SOURCE_LOCATION (*node),
+                 "weakref attribute must appear before alias attribute");
 
       /* Can't call declare_weak because it wants this to be TREE_PUBLIC,
         and that isn't supported; and because it wants to add it to
@@ -6245,8 +7001,18 @@ c_determine_visibility (tree 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;
 }
@@ -6264,7 +7030,7 @@ handle_tls_model_attribute (tree *node, tree name, tree args,
 
   *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;
@@ -6306,12 +7072,14 @@ handle_no_instrument_function_attribute (tree *node, tree name,
 
   if (TREE_CODE (decl) != FUNCTION_DECL)
     {
-      error ("%J%qE attribute applies only to functions", decl, name);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "%qE attribute applies only to functions", name);
       *no_add_attrs = true;
     }
   else if (DECL_INITIAL (decl))
     {
-      error ("%Jcan%'t set %qE attribute after definition", decl, name);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "can%'t set %qE attribute after definition", name);
       *no_add_attrs = true;
     }
   else
@@ -6352,11 +7120,11 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
       tree position = TREE_VALUE (args);
 
       if (TREE_CODE (position) != INTEGER_CST
-         || TREE_INT_CST_HIGH (position) 
+         || TREE_INT_CST_HIGH (position)
          || TREE_INT_CST_LOW (position) < 1
          || TREE_INT_CST_LOW (position) > arg_count )
        {
-         warning (OPT_Wattributes, 
+         warning (OPT_Wattributes,
                   "alloc_size parameter outside range");
          *no_add_attrs = true;
          return NULL_TREE;
@@ -6396,12 +7164,14 @@ handle_no_limit_stack_attribute (tree *node, tree name,
 
   if (TREE_CODE (decl) != FUNCTION_DECL)
     {
-      error ("%J%qE attribute applies only to functions", decl, name);
+      error_at (DECL_SOURCE_LOCATION (decl),
+            "%qE attribute applies only to functions", name);
       *no_add_attrs = true;
     }
   else if (DECL_INITIAL (decl))
     {
-      error ("%Jcan%'t set %qE attribute after definition", decl, name);
+      error_at (DECL_SOURCE_LOCATION (decl),
+               "can%'t set %qE attribute after definition", name);
       *no_add_attrs = true;
     }
   else
@@ -6447,13 +7217,21 @@ handle_novops_attribute (tree *node, tree ARG_UNUSED (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;
 
+  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;
@@ -6547,7 +7325,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))
-      || !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;
@@ -6903,7 +7682,7 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
       if (TREE_CODE (position) != INTEGER_CST)
        {
-         warning (OPT_Wattributes, 
+         warning (OPT_Wattributes,
                   "requested position is not an integer constant");
          *no_add_attrs = true;
        }
@@ -6929,10 +7708,10 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
                               bool * ARG_UNUSED (no_add_attrs))
 {
   tree params;
-  
+
   /* Ensure we have a function type.  */
   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-  
+
   params = TYPE_ARG_TYPES (*node);
   while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
     params = TREE_CHAIN (params);
@@ -6979,6 +7758,7 @@ parse_optimize_options (tree args, bool attr_p)
   bool ret = true;
   unsigned opt_argc;
   unsigned i;
+  int saved_flag_strict_aliasing;
   const char **opt_argv;
   tree ap;
 
@@ -7069,9 +7849,16 @@ 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);
 
+  saved_flag_strict_aliasing = flag_strict_aliasing;
+
   /* Now parse the options.  */
   decode_options (opt_argc, opt_argv);
 
+  targetm.override_options_after_change();
+
+  /* Don't allow changing -fstrict-aliasing.  */
+  flag_strict_aliasing = saved_flag_strict_aliasing;
+
   VEC_truncate (const_char_p, optimize_args, 0);
   return ret;
 }
@@ -7217,21 +8004,24 @@ check_function_arguments_recurse (void (*callback)
   (*callback) (ctx, param, param_num);
 }
 
-/* Checks the number of arguments NARGS against the required number
-   REQUIRED and issues an error if there is a mismatch.  Returns true
-   if the number of arguments is correct, otherwise false.  */
+/* Checks for a builtin function FNDECL that the number of arguments
+   NARGS against the required number REQUIRED and issues an error if
+   there is a mismatch.  Returns true if the number of arguments is
+   correct, otherwise false.  */
 
 static bool
-validate_nargs (tree fndecl, int nargs, int required)
+builtin_function_validate_nargs (tree fndecl, int nargs, int required)
 {
   if (nargs < required)
     {
-      error ("not enough arguments to function %qE", fndecl);
+      error_at (input_location,
+               "not enough arguments to function %qE", fndecl);
       return false;
     }
   else if (nargs > required)
     {
-      error ("too many arguments to function %qE", fndecl);
+      error_at (input_location,
+               "too many arguments to function %qE", fndecl);
       return false;
     }
   return true;
@@ -7250,14 +8040,14 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args)
   switch (DECL_FUNCTION_CODE (fndecl))
     {
     case BUILT_IN_CONSTANT_P:
-      return validate_nargs (fndecl, nargs, 1);
+      return builtin_function_validate_nargs (fndecl, nargs, 1);
 
     case BUILT_IN_ISFINITE:
     case BUILT_IN_ISINF:
     case BUILT_IN_ISINF_SIGN:
     case BUILT_IN_ISNAN:
     case BUILT_IN_ISNORMAL:
-      if (validate_nargs (fndecl, nargs, 1))
+      if (builtin_function_validate_nargs (fndecl, nargs, 1))
        {
          if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE)
            {
@@ -7275,7 +8065,7 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args)
     case BUILT_IN_ISLESSEQUAL:
     case BUILT_IN_ISLESSGREATER:
     case BUILT_IN_ISUNORDERED:
-      if (validate_nargs (fndecl, nargs, 2))
+      if (builtin_function_validate_nargs (fndecl, nargs, 2))
        {
          enum tree_code code0, code1;
          code0 = TREE_CODE (TREE_TYPE (args[0]));
@@ -7293,10 +8083,10 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args)
       return false;
 
     case BUILT_IN_FPCLASSIFY:
-      if (validate_nargs (fndecl, nargs, 6))
+      if (builtin_function_validate_nargs (fndecl, nargs, 6))
        {
          unsigned i;
-         
+
          for (i=0; i<5; i++)
            if (TREE_CODE (args[i]) != INTEGER_CST)
              {
@@ -7408,21 +8198,24 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
    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;
 
-  if (token == CPP_EOF)
+  if (token_type == CPP_EOF)
     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;
 
-      switch (token)
+      switch (token_type)
        {
        default:
          prefix = "";
@@ -7447,26 +8240,29 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
       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
+          || token_type == CPP_UTF8STRING)
     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");
-  else if (token == CPP_NAME)
+  else if (token_type == CPP_NAME)
     {
       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%>");
-  else if (token == CPP_PRAGMA_EOL)
+  else if (token_type == CPP_PRAGMA_EOL)
     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");
-      error (message, cpp_type2name (token));
+      error (message, cpp_type2name (token_type, token_flags));
       free (message);
       message = NULL;
     }
@@ -7481,66 +8277,112 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
 #undef catenate_messages
 }
 
-/* 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.  */
+/* Mapping for cpp message reasons to the options that enable them.  */
 
-void
-c_warn_unused_result (gimple_seq seq)
+struct reason_option_codes_t
 {
-  tree fdecl, ftype;
-  gimple_stmt_iterator i;
+  const int reason;            /* cpplib message reason.  */
+  const int option_code;       /* gcc option that controls this message.  */
+};
 
-  for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
-    {
-      gimple g = gsi_stmt (i);
+static const struct reason_option_codes_t option_codes[] = {
+  {CPP_W_DEPRECATED,                   OPT_Wdeprecated},
+  {CPP_W_COMMENTS,                     OPT_Wcomments},
+  {CPP_W_TRIGRAPHS,                    OPT_Wtrigraphs},
+  {CPP_W_MULTICHAR,                    OPT_Wmultichar},
+  {CPP_W_TRADITIONAL,                  OPT_Wtraditional},
+  {CPP_W_LONG_LONG,                    OPT_Wlong_long},
+  {CPP_W_ENDIF_LABELS,                 OPT_Wendif_labels},
+  {CPP_W_VARIADIC_MACROS,              OPT_Wvariadic_macros},
+  {CPP_W_BUILTIN_MACRO_REDEFINED,      OPT_Wbuiltin_macro_redefined},
+  {CPP_W_UNDEF,                                OPT_Wundef},
+  {CPP_W_UNUSED_MACROS,                        OPT_Wunused_macros},
+  {CPP_W_CXX_OPERATOR_NAMES,           OPT_Wc___compat},
+  {CPP_W_NORMALIZE,                    OPT_Wnormalized_},
+  {CPP_W_INVALID_PCH,                  OPT_Winvalid_pch},
+  {CPP_W_WARNING_DIRECTIVE,            OPT_Wcpp},
+  {CPP_W_NONE,                         0}
+};
 
-      switch (gimple_code (g))
-       {
-       case GIMPLE_BIND:
-         c_warn_unused_result (gimple_bind_body (g));
-         break;
-       case GIMPLE_TRY:
-         c_warn_unused_result (gimple_try_eval (g));
-         c_warn_unused_result (gimple_try_cleanup (g));
-         break;
-       case GIMPLE_CATCH:
-         c_warn_unused_result (gimple_catch_handler (g));
-         break;
-       case GIMPLE_EH_FILTER:
-         c_warn_unused_result (gimple_eh_filter_failure (g));
-         break;
+/* Return the gcc option code associated with the reason for a cpp
+   message, or 0 if none.  */
 
-       case GIMPLE_CALL:
-         if (gimple_call_lhs (g))
-           break;
+static int
+c_option_controlling_cpp_error (int reason)
+{
+  const struct reason_option_codes_t *entry;
 
-         /* This is a naked call, as opposed to a GIMPLE_CALL with an
-            LHS.  All calls whose value is ignored should be
-            represented like this.  Look for the attribute.  */
-         fdecl = gimple_call_fndecl (g);
-         ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
+  for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
+    {
+      if (entry->reason == reason)
+       return entry->option_code;
+    }
+  return 0;
+}
 
-         if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
-           {
-             location_t loc = gimple_location (g);
+/* Callback from cpp_error for PFILE to print diagnostics from the
+   preprocessor.  The diagnostic is of type LEVEL, with REASON set
+   to the reason code if LEVEL is represents a warning, 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.  */
 
-             if (fdecl)
-               warning (0, "%Hignoring return value of %qD, "
-                        "declared with attribute warn_unused_result",
-                        &loc, fdecl);
-             else
-               warning (0, "%Hignoring return value of function "
-                        "declared with attribute warn_unused_result",
-                        &loc);
-           }
-         break;
+bool
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
+            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;
 
-       default:
-         /* Not a container, not a call, or a call whose value is used.  */
-         break;
-       }
+  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);
+  diagnostic_override_option_index (&diagnostic,
+                                    c_option_controlling_cpp_error (reason));
+  ret = report_diagnostic (&diagnostic);
+  if (level == CPP_DL_WARNING_SYSHDR)
+    warn_system_headers = save_warn_system_headers;
+  return ret;
 }
 
 /* Convert a character from the host to the target execution character
@@ -7592,15 +8434,14 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
       return error_mark_node;
 
-    case INTEGER_CST:
-      gcc_assert (integer_zerop (expr));
-      return size_zero_node;
-
     case NOP_EXPR:
     case INDIRECT_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
-      gcc_assert (base == error_mark_node || base == size_zero_node);
-      return base;
+      if (!integer_zerop (TREE_OPERAND (expr, 0)))
+       {
+         error ("cannot apply %<offsetof%> to a non constant address");
+         return error_mark_node;
+       }
+      return size_zero_node;
 
     case COMPONENT_REF:
       base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
@@ -7614,9 +8455,10 @@ fold_offsetof_1 (tree expr, tree stop_ref)
                 "member %qD", t);
          return error_mark_node;
        }
-      off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
-                       size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
-                                 / BITS_PER_UNIT));
+      off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+                           size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
+                                                   1)
+                                     / BITS_PER_UNIT));
       break;
 
     case ARRAY_REF:
@@ -7628,10 +8470,52 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
        {
          code = MINUS_EXPR;
-         t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
+         t = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (t), t);
        }
       t = convert (sizetype, t);
       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+
+      /* Check if the offset goes beyond the upper bound of the array.  */
+      if (code == PLUS_EXPR && TREE_CODE (t) == INTEGER_CST)
+       {
+         tree upbound = array_ref_up_bound (expr);
+         if (upbound != NULL_TREE
+             && TREE_CODE (upbound) == INTEGER_CST
+             && !tree_int_cst_equal (upbound,
+                                     TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+           {
+             upbound = size_binop (PLUS_EXPR, upbound,
+                                   build_int_cst (TREE_TYPE (upbound), 1));
+             if (tree_int_cst_lt (upbound, t))
+               {
+                 tree v;
+
+                 for (v = TREE_OPERAND (expr, 0);
+                      TREE_CODE (v) == COMPONENT_REF;
+                      v = TREE_OPERAND (v, 0))
+                   if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+                       == RECORD_TYPE)
+                     {
+                       tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
+                       for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
+                         if (TREE_CODE (fld_chain) == FIELD_DECL)
+                           break;
+
+                       if (fld_chain)
+                         break;
+                     }
+                 /* Don't warn if the array might be considered a poor
+                    man's flexible array member with a very permissive
+                    definition thereof.  */
+                 if (TREE_CODE (v) == ARRAY_REF
+                     || TREE_CODE (v) == COMPONENT_REF)
+                   warning (OPT_Warray_bounds,
+                            "index %E denotes an offset "
+                            "greater than size of %qT",
+                            t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+               }
+           }
+       }
       break;
 
     case COMPOUND_EXPR:
@@ -7718,25 +8602,33 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
              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,
-                                        VEC_index (constructor_elt,
-                                                   v, 0)->index);
+               maxindex = fold_convert_loc (input_location, sizetype,
+                                            VEC_index (constructor_elt,
+                                                       v, 0)->index);
              curindex = maxindex;
 
              for (cnt = 1;
                   VEC_iterate (constructor_elt, v, cnt, ce);
                   cnt++)
                {
+                 bool curfold_p = false;
                  if (ce->index)
-                   curindex = fold_convert (sizetype, ce->index);
+                   curindex = ce->index, curfold_p = true;
                  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))
-                   maxindex = curindex;
+                   maxindex = curindex, fold_p = curfold_p;
                }
+              if (fold_p)
+                maxindex = fold_convert (sizetype, maxindex);
            }
        }
       else
@@ -7759,7 +8651,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   if (quals == 0)
     unqual_elt = elt;
   else
-    unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+    unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
 
   /* Using build_distinct_type_copy and modifying things afterward instead
      of using build_array_type to create a new type preserves all of the
@@ -7771,7 +8663,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
   /* Make sure we have the canonical MAIN_TYPE. */
   hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode);
-  hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)), 
+  hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
                                    hashcode);
   main_type = type_hash_canon (hashcode, main_type);
 
@@ -7782,7 +8674,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
           || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
               != TYPE_DOMAIN (main_type)))
-    TYPE_CANONICAL (main_type) 
+    TYPE_CANONICAL (main_type)
       = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
                          TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
   else
@@ -7826,18 +8718,18 @@ builtin_type_for_size (int size, bool unsignedp)
    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;
 
-  if (params == NULL)
+  if (VEC_empty (tree, params))
     {
       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;
 
@@ -7860,27 +8752,29 @@ sync_resolve_size (tree function, tree params)
    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;
+  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);
-  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.  */
+  parmnum = 0;
   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;
@@ -7889,10 +8783,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.  */
-      val = TREE_VALUE (params);
+      val = VEC_index (tree, params, parmnum);
       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++;
@@ -7902,7 +8796,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.  */
-  TREE_CHAIN (params) = NULL;
+  VEC_truncate (tree, params, parmnum + 1);
 
   return true;
 }
@@ -7912,9 +8806,9 @@ sync_resolve_params (tree orig_function, tree function, tree params)
    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);
 }
@@ -7923,13 +8817,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.
 
+   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
-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))
@@ -7938,7 +8834,7 @@ resolve_overloaded_builtin (tree function, tree params)
       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:
@@ -7966,7 +8862,7 @@ resolve_overloaded_builtin (tree function, tree 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;
@@ -7975,10 +8871,11 @@ resolve_overloaded_builtin (tree function, tree params)
        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)
-         result = sync_resolve_return (params, result);
+         result = sync_resolve_return (first_param, result);
 
        return result;
       }
@@ -8056,7 +8953,7 @@ warn_array_subscript_with_type_char (tree index)
 
 void
 warn_about_parentheses (enum tree_code code,
-                       enum tree_code code_left, tree ARG_UNUSED (arg_left),
+                       enum tree_code code_left, tree arg_left,
                        enum tree_code code_right, tree arg_right)
 {
   if (!warn_parentheses)
@@ -8072,7 +8969,7 @@ warn_about_parentheses (enum tree_code code,
         || ((CODE) != INTEGER_CST                                          \
             && (integer_onep (ARG) || integer_zerop (ARG))))
 
-  switch (code) 
+  switch (code)
     {
     case LSHIFT_EXPR:
       if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
@@ -8113,7 +9010,7 @@ warn_about_parentheses (enum tree_code code,
       /* 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"
+       warning (OPT_Wparentheses, "suggest parentheses around operand of "
                 "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
       return;
 
@@ -8146,7 +9043,7 @@ warn_about_parentheses (enum tree_code code,
       /* 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"
+       warning (OPT_Wparentheses, "suggest parentheses around operand of "
                 "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
       return;
 
@@ -8166,9 +9063,11 @@ warn_about_parentheses (enum tree_code code,
     default:
       if (TREE_CODE_CLASS (code) == tcc_comparison
           && ((TREE_CODE_CLASS (code_left) == tcc_comparison
-               && code_left != NE_EXPR && code_left != EQ_EXPR)
+               && 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)))
+                  && 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");
       return;
@@ -8204,7 +9103,7 @@ warn_for_div_by_zero (location_t loc, tree divisor)
      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)))
     warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
 }
@@ -8220,22 +9119,22 @@ warn_for_div_by_zero (location_t loc, tree divisor)
    The arguments of this function map directly to local variables
    of build_binary_op.  */
 
-void 
+void
 warn_for_sign_compare (location_t location,
-                      tree orig_op0, tree orig_op1, 
-                      tree op0, tree op1, 
+                      tree orig_op0, tree orig_op1,
+                      tree op0, tree op1,
                       tree result_type, enum tree_code resultcode)
 {
   int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
   int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
   int unsignedp0, unsignedp1;
-  
+
   /* In C++, check for comparison of different enum types.  */
   if (c_dialect_cxx()
       && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
       && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
       && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
-      != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
+        != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
     {
       warning_at (location,
                  OPT_Wsign_compare, "comparison between types %qT and %qT",
@@ -8252,16 +9151,18 @@ warn_for_sign_compare (location_t location,
     /* OK */;
   else
     {
-      tree sop, uop;
+      tree sop, uop, base_type;
       bool ovf;
-      
+
       if (op0_signed)
         sop = orig_op0, uop = orig_op1;
-      else 
+      else
         sop = orig_op1, uop = orig_op0;
 
-      STRIP_TYPE_NOPS (sop); 
+      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
@@ -8274,7 +9175,7 @@ warn_for_sign_compare (location_t location,
          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
@@ -8282,25 +9183,25 @@ warn_for_sign_compare (location_t location,
       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 
+      else
         warning_at (location,
-                   OPT_Wsign_compare, 
+                   OPT_Wsign_compare,
                    "comparison between signed and unsigned integer expressions");
     }
-  
+
   /* Warn if two unsigned values are being compared in a size larger
      than their original size, and one (and only one) is the result of
      a `~' operator.  This comparison will always fail.
-     
+
      Also warn if one operand is a constant, and the constant does not
      have all bits set that are set in the ~ operand when it is
      extended.  */
 
   op0 = get_narrower (op0, &unsignedp0);
   op1 = get_narrower (op1, &unsignedp1);
-  
+
   if ((TREE_CODE (op0) == BIT_NOT_EXPR)
       ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
     {
@@ -8315,7 +9216,7 @@ warn_for_sign_compare (location_t location,
           HOST_WIDE_INT constant, mask;
           int unsignedp;
           unsigned int bits;
-          
+
           if (host_integerp (op0, 0))
             {
               primop = op1;
@@ -8328,7 +9229,7 @@ warn_for_sign_compare (location_t location,
               unsignedp = unsignedp0;
               constant = tree_low_cst (op1, 0);
             }
-          
+
           bits = TYPE_PRECISION (TREE_TYPE (primop));
           if (bits < TYPE_PRECISION (result_type)
               && bits < HOST_BITS_PER_LONG && unsignedp)
@@ -8337,10 +9238,10 @@ warn_for_sign_compare (location_t location,
               if ((mask & constant) != mask)
                {
                  if (constant == 0)
-                   warning (OPT_Wsign_compare, 
+                   warning (OPT_Wsign_compare,
                             "promoted ~unsigned is always non-zero");
                  else
-                   warning_at (location, OPT_Wsign_compare, 
+                   warning_at (location, OPT_Wsign_compare,
                                "comparison of promoted ~unsigned with constant");
                }
             }
@@ -8355,4 +9256,166 @@ warn_for_sign_compare (location_t location,
     }
 }
 
+/* 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);
+}
+
+/* Record the types used by the current global variable declaration
+   being parsed, so that we can decide later to emit their debug info.
+   Those types are in types_used_by_cur_var_decl, and we are going to
+   store them in the types_used_by_vars_hash hash table.
+   DECL is the declaration of the global variable that has been parsed.  */
+
+void
+record_types_used_by_current_var_decl (tree decl)
+{
+  gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
+
+  if (types_used_by_cur_var_decl)
+    {
+      tree node;
+      for (node = types_used_by_cur_var_decl;
+          node;
+          node = TREE_CHAIN (node))
+      {
+       tree type = TREE_PURPOSE (node);
+       types_used_by_var_decl_insert (type, decl);
+      }
+      types_used_by_cur_var_decl = NULL;
+    }
+}
+
+/* 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"