OSDN Git Service

2009-05-12 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index ae8861e..a9929c1 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks-def.h"
 #include "pointer-set.h"
 #include "gimple.h"
+#include "plugin.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -125,6 +126,15 @@ static GTY(()) struct stmt_tree_s c_stmt_tree;
 tree c_break_label;
 tree c_cont_label;
 
+/* True if we are currently parsing the fields of a struct or
+   union.  */
+
+static bool in_struct;
+
+/* A list of types defined in the current struct or union.  */
+
+static VEC(tree,heap) *struct_types;
+
 /* Linked list of TRANSLATION_UNIT_DECLS for the translation units
    included in this invocation.  Note that the current translation
    unit is not included in this list.  */
@@ -197,8 +207,7 @@ bool c_override_global_bindings_to_false;
    in all such cases, the binding in the outer scope will have its
    invisible bit true.  */
 
-struct c_binding GTY((chain_next ("%h.prev")))
-{
+struct GTY((chain_next ("%h.prev"))) c_binding {
   tree decl;                   /* the decl bound */
   tree type;                   /* the type in this scope */
   tree id;                     /* the identifier it's bound to */
@@ -209,6 +218,7 @@ struct c_binding GTY((chain_next ("%h.prev")))
   BOOL_BITFIELD nested : 1;     /* do not set DECL_CONTEXT when popping */
   BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
   /* one free bit */
+  location_t locus;            /* location for nested bindings */
 };
 #define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
 #define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
@@ -234,8 +244,7 @@ struct c_binding GTY((chain_next ("%h.prev")))
    These describe the values of the identifier in the three different
    namespaces defined by the language.  */
 
-struct lang_identifier GTY(())
-{
+struct GTY(()) lang_identifier {
   struct c_common_identifier common_id;
   struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
   struct c_binding *tag_binding;    /* struct/union/enum tags */
@@ -248,10 +257,9 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 
 /* The resulting tree type.  */
 
-union lang_tree_node
-  GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) TREE_CHAIN (&%h.generic))")))
-{
+union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) TREE_CHAIN (&%h.generic))")))  lang_tree_node
+ {
   union tree_node GTY ((tag ("0"),
                        desc ("tree_node_structure (&%h)")))
     generic;
@@ -303,8 +311,7 @@ union lang_tree_node
    pop_scope relies on this.  */
 
 
-struct c_scope GTY((chain_next ("%h.outer")))
-{
+struct GTY((chain_next ("%h.outer"))) c_scope {
   /* The scope containing this one.  */
   struct c_scope *outer;
 
@@ -344,6 +351,9 @@ struct c_scope GTY((chain_next ("%h.outer")))
 
   /* True means make a BLOCK for this scope no matter what.  */
   BOOL_BITFIELD keep : 1;
+
+  /* True means that an unsuffixed float constant is _Decimal64.  */
+  BOOL_BITFIELD float_const_decimal64 : 1;
 };
 
 /* The scope currently in effect.  */
@@ -395,6 +405,32 @@ static GTY((deletable)) struct c_binding *binding_freelist;
   t_->to##_last = f_->from##_last;                             \
 } while (0)
 
+/* A c_inline_static structure stores details of a static identifier
+   referenced in a definition of a function that may be an inline
+   definition if no subsequent declaration of that function uses
+   "extern" or does not use "inline".  */
+
+struct GTY((chain_next ("%h.next"))) c_inline_static {
+  /* The location for a diagnostic.  */
+  location_t location;
+
+  /* The function that may be an inline definition.  */
+  tree function;
+
+  /* The object or function referenced.  */
+  tree static_decl;
+
+  /* What sort of reference this is.  */
+  enum c_inline_static_type type;
+
+  /* The next such structure or NULL.  */
+  struct c_inline_static *next;
+};
+
+/* List of static identifiers used or referenced in functions that may
+   be inline definitions.  */
+static GTY(()) struct c_inline_static *c_inline_statics;
+
 /* True means unconditionally make a BLOCK for the next scope pushed.  */
 
 static bool keep_next_level_flag;
@@ -410,8 +446,8 @@ static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (tree, int);
 static tree grokdeclarator (const struct c_declarator *,
                            struct c_declspecs *,
-                           enum decl_context, bool, tree *, tree *,
-                           enum deprecated_states);
+                           enum decl_context, bool, tree *, tree *, tree *,
+                           bool *, enum deprecated_states);
 static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 \f
@@ -460,7 +496,8 @@ c_print_identifier (FILE *file, tree node, int indent)
    which may be any of several kinds of DECL or TYPE or error_mark_node,
    in the scope SCOPE.  */
 static void
-bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
+bind (tree name, tree decl, struct c_scope *scope, bool invisible,
+      bool nested, location_t locus)
 {
   struct c_binding *b, **here;
 
@@ -479,6 +516,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
   b->invisible = invisible;
   b->nested = nested;
   b->inner_comp = 0;
+  b->locus = locus;
 
   b->type = 0;
 
@@ -555,6 +593,53 @@ c_finish_incomplete_decl (tree decl)
     }
 }
 \f
+/* Record that inline function FUNC contains a reference (location
+   LOC) to static DECL (file-scope or function-local according to
+   TYPE).  */
+
+void
+record_inline_static (location_t loc, tree func, tree decl,
+                     enum c_inline_static_type type)
+{
+  struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
+  csi->location = loc;
+  csi->function = func;
+  csi->static_decl = decl;
+  csi->type = type;
+  csi->next = c_inline_statics;
+  c_inline_statics = csi;
+}
+
+/* Check for references to static declarations in inline functions at
+   the end of the translation unit and diagnose them if the functions
+   are still inline definitions.  */
+
+static void
+check_inline_statics (void)
+{
+  struct c_inline_static *csi;
+  for (csi = c_inline_statics; csi; csi = csi->next)
+    {
+      if (DECL_EXTERNAL (csi->function))
+       switch (csi->type)
+         {
+         case csi_internal:
+           pedwarn (csi->location, 0,
+                    "%qD is static but used in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         case csi_modifiable:
+           pedwarn (csi->location, 0,
+                    "%q+D is static but declared in inline function %qD "
+                    "which is not static", csi->static_decl, csi->function);
+           break;
+         default:
+           gcc_unreachable ();
+         }
+    }
+  c_inline_statics = NULL;
+}
+\f
 /* The Objective-C front-end often needs to determine the current scope.  */
 
 void *
@@ -590,7 +675,9 @@ objc_mark_locals_volatile (void *enclosing_blk)
 int
 global_bindings_p (void)
 {
-  return current_scope == file_scope && !c_override_global_bindings_to_false;
+  return (current_scope == file_scope && !c_override_global_bindings_to_false
+         ? -1
+         : 0);
 }
 
 void
@@ -599,6 +686,30 @@ keep_next_level (void)
   keep_next_level_flag = true;
 }
 
+/* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
+
+void
+set_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = true;
+}
+
+/* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma.  */
+
+void
+clear_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = false;
+}
+
+/* Return nonzero if an unsuffixed float constant is _Decimal64.  */
+
+bool
+float_const_decimal64_p (void)
+{
+  return current_scope->float_const_decimal64;
+}
+
 /* Identify this scope as currently being filled with parameters.  */
 
 void
@@ -630,6 +741,13 @@ push_scope (void)
 
       keep_next_level_flag = false;
       next_is_function_body = false;
+
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope->outer)
+       current_scope->float_const_decimal64
+         = current_scope->outer->float_const_decimal64;
+      else
+       current_scope->float_const_decimal64 = false;
     }
   else
     {
@@ -642,6 +760,12 @@ push_scope (void)
       else
        scope = GGC_CNEW (struct c_scope);
 
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope)
+       scope->float_const_decimal64 = current_scope->float_const_decimal64;
+      else
+       scope->float_const_decimal64 = false;
+
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
       scope->depth        = current_scope ? (current_scope->depth + 1) : 0;
@@ -781,14 +905,18 @@ pop_scope (void)
              error ("nested function %q+D declared but never defined", p);
              undef_nested_function = true;
            }
-         /* C99 6.7.4p6: "a function with external linkage... declared
-            with an inline function specifier ... shall also be defined in the
-            same translation unit."  */
          else if (DECL_DECLARED_INLINE_P (p)
                   && TREE_PUBLIC (p)
-                  && !DECL_INITIAL (p)
-                  && !flag_gnu89_inline)
-           pedwarn (input_location, 0, "inline function %q+D declared but never defined", p);
+                  && !DECL_INITIAL (p))
+           {
+             /* C99 6.7.4p6: "a function with external linkage... declared
+                with an inline function specifier ... shall also be defined
+                in the same translation unit."  */
+             if (!flag_gnu89_inline)
+               pedwarn (input_location, 0,
+                        "inline function %q+D declared but never defined", p);
+             DECL_EXTERNAL (p) = 1;
+           }
 
          goto common_symbol;
 
@@ -820,6 +948,29 @@ pop_scope (void)
              TREE_CHAIN (p) = BLOCK_VARS (block);
              BLOCK_VARS (block) = p;
            }
+         else if (VAR_OR_FUNCTION_DECL_P (p))
+           {
+             /* For block local externs add a special
+                DECL_EXTERNAL decl for debug info generation.  */
+             tree extp = copy_node (p);
+
+             DECL_EXTERNAL (extp) = 1;
+             TREE_STATIC (extp) = 0;
+             TREE_PUBLIC (extp) = 1;
+             DECL_INITIAL (extp) = NULL_TREE;
+             DECL_LANG_SPECIFIC (extp) = NULL;
+             DECL_CONTEXT (extp) = current_function_decl;
+             if (TREE_CODE (p) == FUNCTION_DECL)
+               {
+                 DECL_RESULT (extp) = NULL_TREE;
+                 DECL_SAVED_TREE (extp) = NULL_TREE;
+                 DECL_STRUCT_FUNCTION (extp) = NULL;
+               }
+             if (b->locus != UNKNOWN_LOCATION)
+               DECL_SOURCE_LOCATION (extp) = b->locus;
+             TREE_CHAIN (extp) = BLOCK_VARS (block);
+             BLOCK_VARS (block) = extp;
+           }
          /* If this is the file scope, and we are processing more
             than one translation unit in this compilation, set
             DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
@@ -901,7 +1052,7 @@ push_file_scope (void)
 
   for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
     bind (DECL_NAME (decl), decl, file_scope,
-         /*invisible=*/false, /*nested=*/true);
+         /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
 }
 
 void
@@ -917,6 +1068,8 @@ pop_file_scope (void)
      still works without it.  */
   finish_fname_decls ();
 
+  check_inline_statics ();
+
   /* This is the point to write out a PCH if we're doing that.
      In that case we do not want to do anything else.  */
   if (pch_file)
@@ -942,12 +1095,12 @@ pop_file_scope (void)
    In that case, the TYPE_SIZE will be zero.  */
 
 static void
-pushtag (tree name, tree type)
+pushtag (tree name, tree type, location_t loc)
 {
   /* Record the identifier as the type's name if it has none.  */
   if (name && !TYPE_NAME (type))
     TYPE_NAME (type) = name;
-  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
+  bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc);
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current scope.  This fake
@@ -1775,17 +1928,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
         throw it away, in case it was inlined into a function that
         hasn't been written out yet.  */
       if (new_is_definition && DECL_INITIAL (olddecl))
-       {
-         if (TREE_USED (olddecl)
-             /* We never inline re-defined extern inline functions.
-                FIXME: This would be better handled by keeping both functions
-                as separate declarations.  */
-             && cgraph_function_possibly_inlined_p (olddecl))
-           (*debug_hooks->outlining_inline_function) (olddecl);
-
-         /* The new defn must not be inline.  */
-         DECL_UNINLINABLE (newdecl) = 1;
-       }
+       /* The new defn must not be inline.  */
+       DECL_UNINLINABLE (newdecl) = 1;
       else
        {
          /* If either decl says `inline', this fn is inline, unless
@@ -1831,12 +1975,15 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       /* Also preserve various other info from the definition.  */
       if (!new_is_definition)
        {
+         tree t;
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
          DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
          DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
          gimple_set_body (newdecl, gimple_body (olddecl));
-         DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+         DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
+         for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
+           DECL_CONTEXT (t) = newdecl;
 
          /* See if we've got a function to instantiate from.  */
          if (DECL_SAVED_TREE (olddecl))
@@ -1858,6 +2005,9 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
   {
     unsigned olddecl_uid = DECL_UID (olddecl);
     tree olddecl_context = DECL_CONTEXT (olddecl);
+    tree olddecl_arguments = NULL;
+    if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      olddecl_arguments = DECL_ARGUMENTS (olddecl);
 
     memcpy ((char *) olddecl + sizeof (struct tree_common),
            (char *) newdecl + sizeof (struct tree_common),
@@ -1888,6 +2038,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       }
     DECL_UID (olddecl) = olddecl_uid;
     DECL_CONTEXT (olddecl) = olddecl_context;
+    if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      DECL_ARGUMENTS (olddecl) = olddecl_arguments;
   }
 
   /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
@@ -1980,67 +2132,6 @@ warn_if_shadowing (tree new_decl)
       }
 }
 
-
-/* Subroutine of pushdecl.
-
-   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.  */
-
-static void
-clone_underlying_type (tree x)
-{
-  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_NAME (tt) = x;
-      TREE_USED (tt) = TREE_USED (x);
-      TREE_TYPE (x) = tt;
-    }
-}
-
 /* Record a decl-node X as belonging to the current lexical scope.
    Check for errors (such as an incompatible declaration for the same
    name already seen in the same scope).
@@ -2056,6 +2147,7 @@ pushdecl (tree x)
   struct c_scope *scope = current_scope;
   struct c_binding *b;
   bool nested = false;
+  location_t locus = DECL_SOURCE_LOCATION (x);
 
   /* Must set DECL_CONTEXT for everything not at file scope or
      DECL_FILE_SCOPE_P won't work.  Local externs don't count
@@ -2074,7 +2166,8 @@ pushdecl (tree x)
   /* Anonymous decls are just inserted in the scope.  */
   if (!name)
     {
-      bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
+      bind (name, x, scope, /*invisible=*/false, /*nested=*/false,
+           locus);
       return x;
     }
 
@@ -2234,7 +2327,8 @@ pushdecl (tree x)
              = build_type_attribute_variant (thistype,
                                              TYPE_ATTRIBUTES (b->type));
          TREE_TYPE (b->decl) = thistype;
-         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
+               locus);
          return b->decl;
        }
       else if (TREE_PUBLIC (x))
@@ -2252,7 +2346,7 @@ pushdecl (tree x)
          else
            {
              bind (name, x, external_scope, /*invisible=*/true,
-                   /*nested=*/false);
+                   /*nested=*/false, locus);
              nested = true;
            }
        }
@@ -2263,9 +2357,9 @@ pushdecl (tree x)
 
  skip_external_and_shadow_checks:
   if (TREE_CODE (x) == TYPE_DECL)
-    clone_underlying_type (x);
+    set_underlying_type (x);
 
-  bind (name, x, scope, /*invisible=*/false, nested);
+  bind (name, x, scope, /*invisible=*/false, nested, locus);
 
   /* If x's type is incomplete because it's based on a
      structure or union which has not yet been fully declared,
@@ -2314,11 +2408,12 @@ pushdecl_top_level (tree x)
 
   if (TREE_PUBLIC (x))
     {
-      bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+      bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false,
+           UNKNOWN_LOCATION);
       nested = true;
     }
   if (file_scope)
-    bind (name, x, file_scope, /*invisible=*/false, nested);
+    bind (name, x, file_scope, /*invisible=*/false, nested, UNKNOWN_LOCATION);
 
   return x;
 }
@@ -2373,7 +2468,8 @@ implicitly_declare (tree functionid)
       if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
        {
          bind (functionid, decl, file_scope,
-               /*invisible=*/false, /*nested=*/true);
+               /*invisible=*/false, /*nested=*/true,
+               DECL_SOURCE_LOCATION (decl));
          return decl;
        }
       else
@@ -2414,7 +2510,8 @@ implicitly_declare (tree functionid)
          b->type = TREE_TYPE (decl);
          TREE_TYPE (decl) = newtype;
          bind (functionid, decl, current_scope,
-               /*invisible=*/false, /*nested=*/true);
+               /*invisible=*/false, /*nested=*/true,
+               DECL_SOURCE_LOCATION (decl));
          return decl;
        }
     }
@@ -2477,7 +2574,8 @@ undeclared_variable (tree id, location_t loc)
         will be nonnull but current_function_scope will be null.  */
       scope = current_function_scope ? current_function_scope : current_scope;
     }
-  bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
+  bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false,
+       UNKNOWN_LOCATION);
 }
 \f
 /* Subroutine of lookup_label, declare_label, define_label: construct a
@@ -2531,7 +2629,7 @@ lookup_label (tree name)
 
   /* Ordinary labels go in the current function scope.  */
   bind (name, label, current_function_scope,
-       /*invisible=*/false, /*nested=*/false);
+       /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
   return label;
 }
 
@@ -2561,7 +2659,7 @@ declare_label (tree name)
 
   /* Declared labels go in the current scope.  */
   bind (name, label, current_scope,
-       /*invisible=*/false, /*nested=*/false);
+       /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
   return label;
 }
 
@@ -2608,7 +2706,7 @@ define_label (location_t location, tree name)
 
       /* Ordinary labels go in the current function scope.  */
       bind (name, label, current_function_scope,
-           /*invisible=*/false, /*nested=*/false);
+           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
     }
 
   if (!in_system_header && lookup_name (name))
@@ -2635,10 +2733,13 @@ define_label (location_t location, tree name)
    If THISLEVEL_ONLY is nonzero, searches only the current_scope.
    CODE says which kind of type the caller wants;
    it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
+   If PLOC is not NULL and this returns non-null, it sets *PLOC to the
+   location where the tag was defined.
    If the wrong kind of type is found, an error is reported.  */
 
 static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only)
+lookup_tag (enum tree_code code, tree name, int thislevel_only,
+           location_t *ploc)
 {
   struct c_binding *b = I_TAG_BINDING (name);
   int thislevel = 0;
@@ -2675,6 +2776,10 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only)
       if (thislevel)
        pending_xref_error ();
     }
+
+  if (ploc != NULL)
+    *ploc = b->locus;
+
   return b->decl;
 }
 
@@ -2811,10 +2916,10 @@ c_make_fname_decl (tree id, int type_dep)
     {
       DECL_CONTEXT (decl) = current_function_decl;
       bind (id, decl, current_function_scope,
-           /*invisible=*/false, /*nested=*/false);
+           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
     }
 
-  finish_decl (decl, init, NULL_TREE);
+  finish_decl (decl, init, NULL_TREE, NULL_TREE);
 
   return decl;
 }
@@ -2831,7 +2936,8 @@ c_builtin_function (tree decl)
   /* Should never be called on a symbol with a preexisting meaning.  */
   gcc_assert (!I_SYMBOL_BINDING (id));
 
-  bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
+  bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false,
+       UNKNOWN_LOCATION);
 
   /* Builtins in the implementation namespace are made visible without
      needing to be explicitly declared.  See push_file_scope.  */
@@ -2856,7 +2962,8 @@ c_builtin_function_ext_scope (tree decl)
   /* Should never be called on a symbol with a preexisting meaning.  */
   gcc_assert (!I_SYMBOL_BINDING (id));
 
-  bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false);
+  bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
+       UNKNOWN_LOCATION);
 
   /* Builtins in the implementation namespace are made visible without
      needing to be explicitly declared.  See push_file_scope.  */
@@ -2904,6 +3011,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 
          found_tag = true;
 
+         if (declspecs->restrict_p)
+           {
+             error ("invalid use of %<restrict%>");
+             warned = 1;
+           }
+
          if (name == 0)
            {
              if (warned != 1 && code != ENUMERAL_TYPE)
@@ -2939,12 +3052,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
          else
            {
              pending_invalid_xref = 0;
-             t = lookup_tag (code, name, 1);
+             t = lookup_tag (code, name, 1, NULL);
 
              if (t == 0)
                {
                  t = make_node (code);
-                 pushtag (name, t);
+                 pushtag (name, t, input_location);
                }
            }
        }
@@ -3133,10 +3246,15 @@ add_flexible_array_elts_to_size (tree decl, tree init)
     }
 }
 \f
-/* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
+/* Decode a "typename", such as "int **", returning a ..._TYPE node.
+   Set *EXPR, if EXPR not NULL, to any expression to be evaluated
+   before the type name, and set *EXPR_CONST_OPERANDS, if
+   EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
+   appear in a constant expression.  */
 
 tree
-groktypename (struct c_type_name *type_name)
+groktypename (struct c_type_name *type_name, tree *expr,
+             bool *expr_const_operands)
 {
   tree type;
   tree attrs = type_name->specs->attrs;
@@ -3144,7 +3262,8 @@ groktypename (struct c_type_name *type_name)
   type_name->specs->attrs = NULL_TREE;
 
   type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
-                        false, NULL, &attrs, DEPRECATED_NORMAL);
+                        false, NULL, &attrs, expr, expr_const_operands,
+                        DEPRECATED_NORMAL);
 
   /* Apply attributes.  */
   decl_attributes (&type, attrs, 0);
@@ -3173,6 +3292,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
 {
   tree decl;
   tree tem;
+  tree expr = NULL_TREE;
   enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
   /* An object declared as __attribute__((deprecated)) suppresses
@@ -3181,11 +3301,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
     deprecated_state = DEPRECATED_SUPPRESS;
 
   decl = grokdeclarator (declarator, declspecs,
-                        NORMAL, initialized, NULL, &attributes,
+                        NORMAL, initialized, NULL, &attributes, &expr, NULL,
                         deprecated_state);
   if (!decl)
     return 0;
 
+  if (expr)
+    add_stmt (expr);
+
   if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
     warning (OPT_Wmain, "%q+D is usually a function", decl);
 
@@ -3333,9 +3456,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
       && !TREE_READONLY (decl)
       && DECL_DECLARED_INLINE_P (current_function_decl)
       && DECL_EXTERNAL (current_function_decl))
-    pedwarn (input_location, 0,
-            "%q+D is static but declared in inline function %qD "
-            "which is not static", decl, current_function_decl);
+    record_inline_static (input_location, current_function_decl,
+                         decl, csi_modifiable);
 
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
@@ -3369,11 +3491,12 @@ c_maybe_initialize_eh (void)
 
 /* Finish processing of a declaration;
    install its initial value.
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
    If the length of an array type is not known before,
    it must be determined now, from the initial value, or it is an error.  */
 
 void
-finish_decl (tree decl, tree init, tree asmspec_tree)
+finish_decl (tree decl, tree init, tree origtype, tree asmspec_tree)
 {
   tree type;
   int was_incomplete = (DECL_SIZE (decl) == 0);
@@ -3395,7 +3518,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
     init = 0;
 
   if (init)
-    store_init_value (decl, init);
+    store_init_value (decl, init, origtype);
 
   if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
                            || TREE_CODE (decl) == FUNCTION_DECL
@@ -3648,11 +3771,14 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
          tree cleanup_decl = lookup_name (cleanup_id);
          tree cleanup;
+         VEC(tree,gc) *vec;
 
          /* Build "cleanup(&decl)" for the destructor.  */
-         cleanup = build_unary_op (ADDR_EXPR, decl, 0);
-         cleanup = build_tree_list (NULL_TREE, cleanup);
-         cleanup = build_function_call (cleanup_decl, cleanup);
+         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+         vec = VEC_alloc (tree, gc, 1);
+         VEC_quick_push (tree, vec, cleanup);
+         cleanup = build_function_call_vec (cleanup_decl, vec, NULL);
+         VEC_free (tree, gc, vec);
 
          /* Don't warn about decl unused; the cleanup uses it.  */
          TREE_USED (decl) = 1;
@@ -3673,7 +3799,7 @@ grokparm (const struct c_parm *parm)
 {
   tree attrs = parm->attrs;
   tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
-                             NULL, &attrs, DEPRECATED_NORMAL);
+                             NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
 
   decl_attributes (&decl, attrs, 0);
 
@@ -3690,12 +3816,12 @@ push_parm_decl (const struct c_parm *parm)
   tree decl;
 
   decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
-                        &attrs, DEPRECATED_NORMAL);
+                        &attrs, NULL, NULL, DEPRECATED_NORMAL);
   decl_attributes (&decl, attrs, 0);
 
   decl = pushdecl (decl);
 
-  finish_decl (decl, NULL_TREE, NULL_TREE);
+  finish_decl (decl, NULL_TREE, NULL_TREE, NULL_TREE);
 }
 
 /* Mark all the parameter declarations to date as forward decls.
@@ -3721,10 +3847,11 @@ mark_forward_parm_decls (void)
 /* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
    literal, which may be an incomplete array type completed by the
    initializer; INIT is a CONSTRUCTOR that initializes the compound
-   literal.  */
+   literal.  NON_CONST is true if the initializers contain something
+   that cannot occur in a constant expression.  */
 
 tree
-build_compound_literal (tree type, tree init)
+build_compound_literal (tree type, tree init, bool non_const)
 {
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
@@ -3744,7 +3871,7 @@ build_compound_literal (tree type, tree init)
   TREE_USED (decl) = 1;
   TREE_TYPE (decl) = type;
   TREE_READONLY (decl) = TYPE_READONLY (type);
-  store_init_value (decl, init);
+  store_init_value (decl, init, NULL_TREE);
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
     {
@@ -3777,8 +3904,25 @@ build_compound_literal (tree type, tree init)
       rest_of_decl_compilation (decl, 1, 0);
     }
 
+  if (non_const)
+    {
+      complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
+      C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
+    }
+
   return complit;
 }
+
+/* Check the type of a compound literal.  Here we just check that it
+   is valid for C++.  */
+
+void
+check_compound_literal_type (struct c_type_name *type_name, location_t loc)
+{
+  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+    warning_at (loc, OPT_Wc___compat,
+               "defining a type in a compound literal is invalid in C++");
+}
 \f
 /* Determine whether TYPE is a structure with a flexible array member,
    or a union containing such a structure (possibly recursively).  */
@@ -3816,12 +3960,14 @@ flexible_array_type_p (tree type)
 /* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
    replacing with appropriate values if they are invalid.  */
 static void
-check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
+check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
 {
   tree type_mv;
   unsigned int max_width;
   unsigned HOST_WIDE_INT w;
-  const char *name = orig_name ? orig_name: _("<anonymous>");
+  const char *name = (orig_name
+                     ? identifier_to_locale (IDENTIFIER_POINTER (orig_name))
+                     : _("<anonymous>"));
 
   /* Detect and ignore out of range field width and process valid
      field widths.  */
@@ -3878,8 +4024,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
     {
       struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
       if (!lt
-         || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
-         || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+         || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+         || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
        warning (0, "%qs is narrower than values of its type", name);
     }
 }
@@ -3889,7 +4035,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
 /* Print warning about variable length array if necessary.  */
 
 static void
-warn_variable_length_array (const char *name, tree size)
+warn_variable_length_array (tree name, tree size)
 {
   int const_size = TREE_CONSTANT (size);
 
@@ -3898,7 +4044,8 @@ warn_variable_length_array (const char *name, tree size)
       if (const_size)
        {
          if (name)
-           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array %qs whose size "
+           pedwarn (input_location, OPT_Wvla,
+                    "ISO C90 forbids array %qE whose size "
                     "can%'t be evaluated",
                     name);
          else
@@ -3908,7 +4055,8 @@ warn_variable_length_array (const char *name, tree size)
       else
        {
          if (name) 
-           pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array %qs",
+           pedwarn (input_location, OPT_Wvla,
+                    "ISO C90 forbids variable length array %qE",
                     name);
          else
            pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
@@ -3920,7 +4068,7 @@ warn_variable_length_array (const char *name, tree size)
         {
          if (name)
            warning (OPT_Wvla,
-                    "the size of array %qs can"
+                    "the size of array %qE can"
                     "%'t be evaluated", name);
          else
            warning (OPT_Wvla,
@@ -3930,7 +4078,7 @@ warn_variable_length_array (const char *name, tree size)
        {
          if (name)
            warning (OPT_Wvla,
-                    "variable length array %qs is used",
+                    "variable length array %qE is used",
                     name);
          else
            warning (OPT_Wvla,
@@ -3939,6 +4087,34 @@ warn_variable_length_array (const char *name, tree size)
     }
 }
 
+/* Given a size SIZE that may not be a constant, return a SAVE_EXPR to
+   serve as the actual size-expression for a type or decl.  This is
+   like variable_size in stor-layout.c, but we make global_bindings_p
+   return negative to avoid calls to that function from outside the
+   front end resulting in errors at file scope, then call this version
+   instead from front-end code.  */
+
+static tree
+c_variable_size (tree size)
+{
+  tree save;
+
+  if (TREE_CONSTANT (size))
+    return size;
+
+  size = save_expr (size);
+
+  save = skip_simple_arithmetic (size);
+
+  if (cfun && cfun->dont_save_pending_sizes_p)
+    return size;
+
+  if (!global_bindings_p ())
+    put_pending_size (save);
+
+  return size;
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -3963,6 +4139,11 @@ warn_variable_length_array (const char *name, tree size)
    DECL_ATTRS points to the list of attributes that should be added to this
      decl.  Any nested attributes that belong on the decl itself will be
      added to this list.
+   If EXPR is not NULL, any expressions that need to be evaluated as
+     part of evaluating variably modified types will be stored in *EXPR.
+   If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
+     set to indicate whether operands in *EXPR can be used in constant
+     expressions.
    DEPRECATED_STATE is a deprecated_states value indicating whether
    deprecation warnings should be suppressed.
 
@@ -3977,7 +4158,8 @@ static tree
 grokdeclarator (const struct c_declarator *declarator,
                struct c_declspecs *declspecs,
                enum decl_context decl_context, bool initialized, tree *width,
-               tree *decl_attrs, enum deprecated_states deprecated_state)
+               tree *decl_attrs, tree *expr, bool *expr_const_operands,
+               enum deprecated_states deprecated_state)
 {
   tree type = declspecs->type;
   bool threadp = declspecs->thread_p;
@@ -3986,7 +4168,7 @@ grokdeclarator (const struct c_declarator *declarator,
   int restrictp;
   int volatilep;
   int type_quals = TYPE_UNQUALIFIED;
-  const char *name, *orig_name;
+  tree name = NULL_TREE;
   bool funcdef_flag = false;
   bool funcdef_syntax = false;
   int size_varies = 0;
@@ -3999,15 +4181,24 @@ grokdeclarator (const struct c_declarator *declarator,
   bool bitfield = width != NULL;
   tree element_type;
   struct c_arg_info *arg_info = 0;
+  tree expr_dummy;
+  bool expr_const_operands_dummy;
+
+  if (expr == NULL)
+    expr = &expr_dummy;
+  if (expr_const_operands == NULL)
+    expr_const_operands = &expr_const_operands_dummy;
+
+  *expr = declspecs->expr;
+  *expr_const_operands = declspecs->expr_const_operands;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
 
   /* Look inside a declarator for the name being declared
-     and get it as a string, for an error message.  */
+     and get it as an IDENTIFIER_NODE, for an error message.  */
   {
     const struct c_declarator *decl = declarator;
-    name = 0;
 
     while (decl)
       switch (decl->kind)
@@ -4025,16 +4216,21 @@ grokdeclarator (const struct c_declarator *declarator,
 
        case cdk_id:
          if (decl->u.id)
-           name = IDENTIFIER_POINTER (decl->u.id);
+           name = decl->u.id;
          decl = 0;
          break;
 
        default:
          gcc_unreachable ();
        }
-    orig_name = name;
     if (name == 0)
-      name = "type name";
+      {
+       gcc_assert (decl_context == PARM
+                   || decl_context == TYPENAME
+                   || (decl_context == FIELD
+                       && declarator->kind == cdk_id));
+       gcc_assert (!initialized);
+      }
   }
 
   /* A function definition's declarator must have the form of
@@ -4050,13 +4246,16 @@ grokdeclarator (const struct c_declarator *declarator,
     decl_context = PARM;
 
   if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
-    warn_deprecated_use (declspecs->type);
+    warn_deprecated_use (declspecs->type, declspecs->decl_attr);
 
   if ((decl_context == NORMAL || decl_context == FIELD)
       && current_scope == file_scope
       && variably_modified_type_p (type, NULL_TREE))
     {
-      error ("variably modified %qs at file scope", name);
+      if (name)
+       error ("variably modified %qE at file scope", name);
+      else
+       error ("variably modified field at file scope");
       type = integer_type_node;
     }
 
@@ -4072,9 +4271,16 @@ grokdeclarator (const struct c_declarator *declarator,
       if ((warn_implicit_int || warn_return_type || flag_isoc99)
          && funcdef_flag)
        warn_about_return_type = 1;
-      else 
-       pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int, 
-                    "type defaults to %<int%> in declaration of %qs", name);
+      else
+       {
+         if (name)
+           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int, 
+                        "type defaults to %<int%> in declaration of %qE",
+                        name);
+         else
+           pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int, 
+                        "type defaults to %<int%> in type name");
+       }
     }
 
   /* Adjust the type if a bit-field is being declared,
@@ -4148,11 +4354,17 @@ grokdeclarator (const struct c_declarator *declarator,
          switch (decl_context)
            {
            case FIELD:
-             error ("storage class specified for structure field %qs",
-                    name);
+             if (name)
+               error ("storage class specified for structure field %qE",
+                      name);
+             else
+               error ("storage class specified for structure field");
              break;
            case PARM:
-             error ("storage class specified for parameter %qs", name);
+             if (name)
+               error ("storage class specified for parameter %qE", name);
+             else
+               error ("storage class specified for unnamed parameter");
              break;
            default:
              error ("storage class specified for typename");
@@ -4172,26 +4384,26 @@ grokdeclarator (const struct c_declarator *declarator,
            /* It is fine to have 'extern const' when compiling at C
               and C++ intersection.  */
            if (!(warn_cxx_compat && constp))
-             warning (0, "%qs initialized and declared %<extern%>", name);
+             warning (0, "%qE initialized and declared %<extern%>", name);
          }
       else
-       error ("%qs has both %<extern%> and initializer", name);
+       error ("%qE has both %<extern%> and initializer", name);
     }
   else if (current_scope == file_scope)
     {
       if (storage_class == csc_auto)
-       error ("file-scope declaration of %qs specifies %<auto%>", name);
+       error ("file-scope declaration of %qE specifies %<auto%>", name);
       if (pedantic && storage_class == csc_register)
        pedwarn (input_location, OPT_pedantic,
-                "file-scope declaration of %qs specifies %<register%>", name);
+                "file-scope declaration of %qE specifies %<register%>", name);
     }
   else
     {
       if (storage_class == csc_extern && funcdef_flag)
-       error ("nested function %qs declared %<extern%>", name);
+       error ("nested function %qE declared %<extern%>", name);
       else if (threadp && storage_class == csc_none)
        {
-         error ("function-scope %qs implicitly auto and declared "
+         error ("function-scope %qE implicitly auto and declared "
                 "%<__thread%>",
                 name);
          threadp = false;
@@ -4285,13 +4497,19 @@ grokdeclarator (const struct c_declarator *declarator,
 
            if (VOID_TYPE_P (type))
              {
-               error ("declaration of %qs as array of voids", name);
+               if (name)
+                 error ("declaration of %qE as array of voids", name);
+               else
+                 error ("declaration of type name as array of voids");
                type = error_mark_node;
              }
 
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
-               error ("declaration of %qs as array of functions", name);
+               if (name)
+                 error ("declaration of %qE as array of functions", name);
+               else
+                 error ("declaration of type name as array of functions");
                type = error_mark_node;
              }
 
@@ -4311,33 +4529,70 @@ grokdeclarator (const struct c_declarator *declarator,
 
            if (size)
              {
+               bool size_maybe_const = true;
+               bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+                                      && !TREE_OVERFLOW (size));
+               bool this_size_varies = false;
+
                /* Strip NON_LVALUE_EXPRs since we aren't using as an
                   lvalue.  */
                STRIP_TYPE_NOPS (size);
 
                if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
                  {
-                   error ("size of array %qs has non-integer type", name);
+                   if (name)
+                     error ("size of array %qE has non-integer type", name);
+                   else
+                     error ("size of unnamed array has non-integer type");
                    size = integer_one_node;
                  }
 
-               if (pedantic && integer_zerop (size))
-                 pedwarn (input_location, OPT_pedantic,
-                          "ISO C forbids zero-size array %qs", name);
+               size = c_fully_fold (size, false, &size_maybe_const);
+
+               if (pedantic && size_maybe_const && integer_zerop (size))
+                 {
+                   if (name)
+                     pedwarn (input_location, OPT_pedantic,
+                              "ISO C forbids zero-size array %qE", name);
+                   else
+                     pedwarn (input_location, OPT_pedantic,
+                              "ISO C forbids zero-size array");
+                 }
 
-               if (TREE_CODE (size) == INTEGER_CST)
+               if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
                  {
                    constant_expression_warning (size);
                    if (tree_int_cst_sgn (size) < 0)
                      {
-                       error ("size of array %qs is negative", name);
+                       if (name)
+                         error ("size of array %qE is negative", name);
+                       else
+                         error ("size of unnamed array is negative");
                        size = integer_one_node;
                      }
+                   /* Handle a size folded to an integer constant but
+                      not an integer constant expression.  */
+                   if (!size_int_const)
+                     {
+                       /* If this is a file scope declaration of an
+                          ordinary identifier, this is invalid code;
+                          diagnosing it here and not subsequently
+                          treating the type as variable-length avoids
+                          more confusing diagnostics later.  */
+                       if ((decl_context == NORMAL || decl_context == FIELD)
+                           && current_scope == file_scope)
+                         pedwarn (input_location, 0,
+                                  "variably modified %qE at file scope",
+                                  name);
+                       else
+                         this_size_varies = size_varies = 1;
+                       warn_variable_length_array (name, size);
+                     }
                  }
                else if ((decl_context == NORMAL || decl_context == FIELD)
                         && current_scope == file_scope)
                  {
-                   error ("variably modified %qs at file scope", name);
+                   error ("variably modified %qE at file scope", name);
                    size = integer_one_node;
                  }
                else
@@ -4345,11 +4600,11 @@ grokdeclarator (const struct c_declarator *declarator,
                    /* Make sure the array size remains visibly
                       nonconstant even if it is (eg) a const variable
                       with known value.  */
-                   size_varies = 1;
-                   warn_variable_length_array (orig_name, size);
+                   this_size_varies = size_varies = 1;
+                   warn_variable_length_array (name, size);
                  }
 
-               if (integer_zerop (size))
+               if (integer_zerop (size) && !this_size_varies)
                  {
                    /* A zero-length array cannot be represented with
                       an unsigned index type, which is what we'll
@@ -4363,7 +4618,10 @@ grokdeclarator (const struct c_declarator *declarator,
                       MINUS_EXPR, which allows the -1 to get folded
                       with the +1 that happens when building TYPE_SIZE.  */
                    if (size_varies)
-                     size = variable_size (size);
+                     size = c_variable_size (size);
+                   if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+                     size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+                                    integer_zero_node, size);
 
                    /* Compute the maximum valid index, that is, size
                       - 1.  Do the calculation in index_type, so that
@@ -4384,34 +4642,58 @@ grokdeclarator (const struct c_declarator *declarator,
                    if (TREE_CODE (itype) == INTEGER_CST
                        && TREE_OVERFLOW (itype))
                      {
-                       error ("size of array %qs is too large", name);
+                       if (name)
+                         error ("size of array %qE is too large", name);
+                       else
+                         error ("size of unnamed array is too large");
                        type = error_mark_node;
                        continue;
                      }
 
                    itype = build_index_type (itype);
                  }
+               if (this_size_varies)
+                 {
+                   if (*expr)
+                     *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+                                     *expr, size);
+                   else
+                     *expr = size;
+                   *expr_const_operands &= size_maybe_const;
+                 }
              }
            else if (decl_context == FIELD)
              {
-               if (pedantic && !flag_isoc99 && !in_system_header)
+               bool flexible_array_member = false;
+               if (array_parm_vla_unspec_p)
+                 /* Field names can in fact have function prototype
+                    scope so [*] is disallowed here through making
+                    the field variably modified, not through being
+                    something other than a declaration with function
+                    prototype scope.  */
+                 size_varies = 1;
+               else
+                 {
+                   const struct c_declarator *t = declarator;
+                   while (t->kind == cdk_attrs)
+                     t = t->declarator;
+                   flexible_array_member = (t->kind == cdk_id);
+                 }
+               if (flexible_array_member
+                   && pedantic && !flag_isoc99 && !in_system_header)
                  pedwarn (input_location, OPT_pedantic,
                           "ISO C90 does not support flexible array members");
 
                /* ISO C99 Flexible array members are effectively
                   identical to GCC's zero-length array extension.  */
-               itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+               if (flexible_array_member || array_parm_vla_unspec_p)
+                 itype = build_range_type (sizetype, size_zero_node,
+                                           NULL_TREE);
              }
            else if (decl_context == PARM)
              {
                if (array_parm_vla_unspec_p)
                  {
-                   if (! orig_name)
-                     {
-                       /* C99 6.7.5.2p4 */
-                       error ("%<[*]%> not allowed in other than a declaration");
-                     }
-
                    itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
                    size_varies = 1;
                  }
@@ -4420,12 +4702,14 @@ grokdeclarator (const struct c_declarator *declarator,
              {
                if (array_parm_vla_unspec_p)
                  {
-                   /* The error is printed elsewhere.  We use this to
-                      avoid messing up with incomplete array types of
-                      the same type, that would otherwise be modified
-                      below.  */
+                   /* C99 6.7.5.2p4 */
+                   warning (0, "%<[*]%> not in a declaration");
+                   /* We use this to avoid messing up with incomplete
+                      array types of the same type, that would
+                      otherwise be modified below.  */
                    itype = build_range_type (sizetype, size_zero_node,
                                              NULL_TREE);
+                   size_varies = 1;
                  }
              }
 
@@ -4514,12 +4798,20 @@ grokdeclarator (const struct c_declarator *declarator,
            /* Warn about some types functions can't return.  */
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
-               error ("%qs declared as function returning a function", name);
+               if (name)
+                 error ("%qE declared as function returning a function",
+                        name);
+               else
+                 error ("type name declared as function "
+                        "returning a function");
                type = integer_type_node;
              }
            if (TREE_CODE (type) == ARRAY_TYPE)
              {
-               error ("%qs declared as function returning an array", name);
+               if (name)
+                 error ("%qE declared as function returning an array", name);
+               else
+                 error ("type name declared as function returning an array");
                type = integer_type_node;
              }
 
@@ -4610,7 +4902,7 @@ grokdeclarator (const struct c_declarator *declarator,
                tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
                DECL_ARTIFICIAL (decl) = 1;
                pushdecl (decl);
-               finish_decl (decl, NULL_TREE, NULL_TREE);
+               finish_decl (decl, NULL_TREE, NULL_TREE, NULL_TREE);
                TYPE_NAME (type) = decl;
              }
 
@@ -4634,7 +4926,7 @@ grokdeclarator (const struct c_declarator *declarator,
 
   /* Check the type and width of a bit-field.  */
   if (bitfield)
-    check_bitfield_type_and_width (&type, width, orig_name);
+    check_bitfield_type_and_width (&type, width, name);
 
   /* Did array size calculations overflow?  */
 
@@ -4643,7 +4935,10 @@ grokdeclarator (const struct c_declarator *declarator,
       && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
       && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
     {
-      error ("size of array %qs is too large", name);
+      if (name)
+       error ("size of array %qE is too large", name);
+      else
+       error ("size of unnamed array is too large");
       /* If we proceed with the array type as it is, we'll eventually
         crash in tree_low_cst().  */
       type = error_mark_node;
@@ -4708,7 +5003,7 @@ grokdeclarator (const struct c_declarator *declarator,
                    && !(storage_class == csc_static
                         || storage_class == csc_register)))))
     {
-      error ("variable or field %qs declared void", name);
+      error ("variable or field %qE declared void", name);
       type = integer_type_node;
     }
 
@@ -4786,13 +5081,16 @@ grokdeclarator (const struct c_declarator *declarator,
 
        if (TREE_CODE (type) == FUNCTION_TYPE)
          {
-           error ("field %qs declared as a function", name);
+           error ("field %qE declared as a function", name);
            type = build_pointer_type (type);
          }
        else if (TREE_CODE (type) != ERROR_MARK
                 && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
          {
-           error ("field %qs has incomplete type", name);
+           if (name)
+             error ("field %qE has incomplete type", name);
+           else
+             error ("unnamed field has incomplete type");
            type = error_mark_node;
          }
        type = c_build_qualified_type (type, type_quals);
@@ -4809,7 +5107,7 @@ grokdeclarator (const struct c_declarator *declarator,
       {
        if (storage_class == csc_register || threadp)
          {
-           error ("invalid storage class for function %qs", name);
+           error ("invalid storage class for function %qE", name);
           }
        else if (current_scope != file_scope)
          {
@@ -4819,10 +5117,11 @@ grokdeclarator (const struct c_declarator *declarator,
               GCC allows 'auto', perhaps with 'inline', to support
               nested functions.  */
            if (storage_class == csc_auto)
-               pedwarn (input_location, OPT_pedantic, "invalid storage class for function %qs", name);
+               pedwarn (input_location, OPT_pedantic,
+                        "invalid storage class for function %qE", name);
            else if (storage_class == csc_static)
              {
-               error ("invalid storage class for function %qs", name);
+               error ("invalid storage class for function %qE", name);
                if (funcdef_flag)
                  storage_class = declspecs->storage_class = csc_none;
                else
@@ -4944,11 +5243,17 @@ grokdeclarator (const struct c_declarator *declarator,
          DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
       }
 
-    if (storage_class == csc_extern
+    if ((storage_class == csc_extern
+        || (storage_class == csc_none
+            && TREE_CODE (type) == FUNCTION_TYPE
+            && !funcdef_flag))
        && variably_modified_type_p (type, NULL_TREE))
       {
        /* C99 6.7.5.2p2 */
-       error ("object with variably modified type must have no linkage");
+       if (TREE_CODE (type) == FUNCTION_TYPE)
+         error ("non-nested function with variably modified type");
+       else
+         error ("object with variably modified type must have no linkage");
       }
 
     /* Record `register' declaration for warnings on &
@@ -5276,13 +5581,19 @@ get_parm_info (bool ellipsis)
    Return a c_typespec structure for the type specifier.  */
 
 struct c_typespec
-parser_xref_tag (enum tree_code code, tree name)
+parser_xref_tag (enum tree_code code, tree name, location_t loc)
 {
   struct c_typespec ret;
+  tree ref;
+  location_t refloc;
+
+  ret.expr = NULL_TREE;
+  ret.expr_const_operands = true;
+
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
-  tree ref = lookup_tag (code, name, 0);
+  ref = lookup_tag (code, name, 0, &refloc);
   /* If this is the right type of tag, return what we found.
      (This reference will be shadowed by shadow_tag later if appropriate.)
      If this is the wrong type of tag, do not return it.  If it was the
@@ -5297,6 +5608,35 @@ parser_xref_tag (enum tree_code code, tree name)
   ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
   if (ref && TREE_CODE (ref) == code)
     {
+      if (C_TYPE_DEFINED_IN_STRUCT (ref)
+         && loc != UNKNOWN_LOCATION
+         && warn_cxx_compat)
+       {
+         switch (code)
+           {
+           case ENUMERAL_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("enum type defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "enum type defined here");
+             break;
+           case RECORD_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("struct defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "struct defined here");
+             break;
+           case UNION_TYPE:
+             warning_at (loc, OPT_Wc___compat,
+                         ("union defined in struct or union "
+                          "is not visible in C++"));
+             inform (refloc, "union defined here");
+             break;
+           default:
+             gcc_unreachable();
+           }
+       }
+
       ret.spec = ref;
       return ret;
     }
@@ -5311,7 +5651,7 @@ parser_xref_tag (enum tree_code code, tree name)
     {
       /* Give the type a default layout like unsigned int
         to avoid crashing if it does not get defined.  */
-      TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
+      SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
       TYPE_USER_ALIGN (ref) = 0;
       TYPE_UNSIGNED (ref) = 1;
@@ -5320,7 +5660,7 @@ parser_xref_tag (enum tree_code code, tree name)
       TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
     }
 
-  pushtag (name, ref);
+  pushtag (name, ref, loc);
 
   ret.spec = ref;
   return ret;
@@ -5333,38 +5673,53 @@ parser_xref_tag (enum tree_code code, tree name)
 tree
 xref_tag (enum tree_code code, tree name)
 {
-  return parser_xref_tag (code, name).spec;
+  return parser_xref_tag (code, name, UNKNOWN_LOCATION).spec;
 }
 \f
 /* Make sure that the tag NAME is defined *in the current scope*
    at least as a forward reference.
-   CODE says which kind of tag NAME ought to be.  */
+   CODE says which kind of tag NAME ought to be.
+
+   This stores the current value of the file static IN_STRUCT in
+   *ENCLOSING_IN_STRUCT, and sets IN_STRUCT to true.  Similarly, this
+   sets STRUCT_TYPES in *ENCLOSING_STRUCT_TYPES, and sets STRUCT_TYPES
+   to an empty vector.  The old values are restored in
+   finish_struct.  */
 
 tree
-start_struct (enum tree_code code, tree name)
+start_struct (enum tree_code code, tree name, bool *enclosing_in_struct,
+             VEC(tree,heap) **enclosing_struct_types, location_t loc)
 {
   /* If there is already a tag defined at this scope
      (as a forward reference), just return it.  */
 
-  tree ref = 0;
+  tree ref = NULL_TREE;
+  location_t refloc = UNKNOWN_LOCATION;
 
-  if (name != 0)
-    ref = lookup_tag (code, name, 1);
+  if (name != NULL_TREE)
+    ref = lookup_tag (code, name, 1, &refloc);
   if (ref && TREE_CODE (ref) == code)
     {
       if (TYPE_SIZE (ref))
        {
          if (code == UNION_TYPE)
-           error ("redefinition of %<union %E%>", name);
+           error_at (loc, "redefinition of %<union %E%>", name);
          else
-           error ("redefinition of %<struct %E%>", name);
+           error_at (loc, "redefinition of %<struct %E%>", name);
+         if (refloc != UNKNOWN_LOCATION)
+           inform (refloc, "originally defined here");
+         /* Don't create structures using a name already in use.  */
+         ref = NULL_TREE;
        }
       else if (C_TYPE_BEING_DEFINED (ref))
        {
          if (code == UNION_TYPE)
-           error ("nested redefinition of %<union %E%>", name);
+           error_at (loc, "nested redefinition of %<union %E%>", name);
          else
-           error ("nested redefinition of %<struct %E%>", name);
+           error_at (loc, "nested redefinition of %<struct %E%>", name);
+         /* Don't bother to report "originally defined here" for a
+            nested redefinition; the original definition should be
+            obvious.  */
          /* Don't create structures that contain themselves.  */
          ref = NULL_TREE;
        }
@@ -5375,11 +5730,28 @@ start_struct (enum tree_code code, tree name)
   if (ref == NULL_TREE || TREE_CODE (ref) != code)
     {
       ref = make_node (code);
-      pushtag (name, ref);
+      pushtag (name, ref, loc);
     }
 
   C_TYPE_BEING_DEFINED (ref) = 1;
   TYPE_PACKED (ref) = flag_pack_struct;
+
+  *enclosing_in_struct = in_struct;
+  *enclosing_struct_types = struct_types;
+  in_struct = true;
+  struct_types = VEC_alloc(tree, heap, 0);
+
+  /* FIXME: This will issue a warning for a use of a type defined
+     within a statement expr used within sizeof, et. al.  This is not
+     terribly serious as C++ doesn't permit statement exprs within
+     sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+               "defining type in %qs expression is invalid in C++",
+               (in_sizeof
+                ? "sizeof"
+                : (in_typeof ? "typeof" : "alignof")));
+
   return ref;
 }
 
@@ -5449,10 +5821,10 @@ grokfield (location_t loc,
     }
 
   value = grokdeclarator (declarator, declspecs, FIELD, false,
-                         width ? &width : NULL, decl_attrs,
+                         width ? &width : NULL, decl_attrs, NULL, NULL,
                          DEPRECATED_NORMAL);
 
-  finish_decl (value, NULL_TREE, NULL_TREE);
+  finish_decl (value, NULL_TREE, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
   return value;
@@ -5517,14 +5889,22 @@ detect_field_duplicates (tree fieldlist)
 
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
-   ATTRIBUTES are attributes to be applied to the structure.  */
+   ATTRIBUTES are attributes to be applied to the structure.
+
+   ENCLOSING_IN_STRUCT is the value of IN_STRUCT, and
+   ENCLOSING_STRUCT_TYPES is the value of STRUCT_TYPES, when the
+   struct was started.  This sets the C_TYPE_DEFINED_IN_STRUCT flag
+   for any type defined in the current struct.  */
 
 tree
-finish_struct (tree t, tree fieldlist, tree attributes)
+finish_struct (tree t, tree fieldlist, tree attributes,
+              bool enclosing_in_struct,
+              VEC(tree,heap) *enclosing_struct_types)
 {
   tree x;
   bool toplevel = file_scope == current_scope;
   int saw_named_field;
+  unsigned int ix;
 
   /* If this type was previously laid out as a forward reference,
      make sure we lay it out again.  */
@@ -5573,9 +5953,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
       DECL_CONTEXT (x) = t;
 
-      if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
-       DECL_PACKED (x) = 1;
-
       /* If any field is const, the structure type is pseudo-const.  */
       if (TREE_READONLY (x))
        C_TYPE_FIELDS_READONLY (t) = 1;
@@ -5607,6 +5984,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          SET_DECL_C_BIT_FIELD (x);
        }
 
+      if (TYPE_PACKED (t)
+         && (DECL_BIT_FIELD (x)
+             || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+       DECL_PACKED (x) = 1;
+
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -5775,6 +6157,24 @@ finish_struct (tree t, tree fieldlist, tree attributes)
   if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE))
     add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
 
+  /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+     the current struct.  We do this now at the end of the struct
+     because the flag is used to issue visibility warnings when using
+     -Wc++-compat, and we only want to issue those warnings if the
+     type is referenced outside of the struct declaration.  */
+  for (ix = 0; VEC_iterate (tree, struct_types, ix, x); ++ix)
+    C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+  VEC_free (tree, heap, struct_types);
+
+  in_struct = enclosing_in_struct;
+  struct_types = enclosing_struct_types;
+
+  /* If this struct is defined inside a struct, add it to
+     STRUCT_TYPES.  */
+  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_types, t);
+
   return t;
 }
 
@@ -5795,32 +6195,35 @@ layout_array_type (tree t)
    may be used to declare the individual values as they are read.  */
 
 tree
-start_enum (struct c_enum_contents *the_enum, tree name)
+start_enum (struct c_enum_contents *the_enum, tree name, location_t loc)
 {
-  tree enumtype = 0;
+  tree enumtype = NULL_TREE;
+  location_t enumloc = UNKNOWN_LOCATION;
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
      forward reference.  */
 
-  if (name != 0)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1);
+  if (name != NULL_TREE)
+    enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
 
   if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
       enumtype = make_node (ENUMERAL_TYPE);
-      pushtag (name, enumtype);
+      pushtag (name, enumtype, loc);
     }
 
   if (C_TYPE_BEING_DEFINED (enumtype))
-    error ("nested redefinition of %<enum %E%>", name);
+    error_at (loc, "nested redefinition of %<enum %E%>", name);
 
   C_TYPE_BEING_DEFINED (enumtype) = 1;
 
   if (TYPE_VALUES (enumtype) != 0)
     {
       /* This enum is a named one that has been declared already.  */
-      error ("redeclaration of %<enum %E%>", name);
+      error_at (loc, "redeclaration of %<enum %E%>", name);
+      if (enumloc != UNKNOWN_LOCATION)
+       inform (enumloc, "originally defined here");
 
       /* Completely replace its old definition.
         The old enumerators remain defined, however.  */
@@ -5833,6 +6236,16 @@ start_enum (struct c_enum_contents *the_enum, tree name)
   if (flag_short_enums)
     TYPE_PACKED (enumtype) = 1;
 
+  /* FIXME: This will issue a warning for a use of a type defined
+     within sizeof in a statement expr.  This is not terribly serious
+     as C++ doesn't permit statement exprs within sizeof anyhow.  */
+  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+    warning_at (loc, OPT_Wc___compat,
+               "defining type in %qs expression is invalid in C++",
+               (in_sizeof
+                ? "sizeof"
+                : (in_typeof ? "typeof" : "alignof")));
+
   return enumtype;
 }
 
@@ -5875,8 +6288,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
      that normally we only go as narrow as int - and signed iff any of
      the values are negative.  */
   unsign = (tree_int_cst_sgn (minnode) >= 0);
-  precision = MAX (min_precision (minnode, unsign),
-                  min_precision (maxnode, unsign));
+  precision = MAX (tree_int_cst_min_precision (minnode, unsign),
+                  tree_int_cst_min_precision (maxnode, unsign));
 
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
@@ -5926,17 +6339,15 @@ finish_enum (tree enumtype, tree values, tree attributes)
          /* The ISO C Standard mandates enumerators to have type int,
             even though the underlying type of an enum type is
             unspecified.  However, GCC allows enumerators of any
-            integer type as an extensions.  Here we convert any
-            enumerators that fit in an int to type int, to avoid
-            promotions to unsigned types when comparing integers with
-            enumerators that fit in the int range.  When -pedantic is
-            given, build_enumerator() would have already warned about
-            those that don't fit.  */
-         if (int_fits_type_p (ini, integer_type_node))
-           tem = integer_type_node;
-         else
-           tem = enumtype;
-         ini = convert (tem, ini);
+            integer type as an extensions.  build_enumerator()
+            converts any enumerators that fit in an int to type int,
+            to avoid promotions to unsigned types when comparing
+            integers with enumerators that fit in the int range.
+            When -pedantic is given, build_enumerator() would have
+            already warned about those that don't fit. Here we
+            convert the rest to the enumerator type. */
+         if (TREE_TYPE (ini) != integer_type_node)
+           ini = convert (enumtype, ini);
 
          DECL_INITIAL (enu) = ini;
          TREE_PURPOSE (pair) = DECL_NAME (enu);
@@ -5963,7 +6374,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
       TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
       TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
       TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
-      TYPE_MODE (tem) = TYPE_MODE (enumtype);
+      SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
@@ -5974,6 +6385,11 @@ finish_enum (tree enumtype, tree values, tree attributes)
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, toplevel);
 
+  /* If this enum is defined inside a struct, add it to
+     STRUCT_TYPES.  */
+  if (in_struct && !in_sizeof && !in_typeof && !in_alignof)
+    VEC_safe_push (tree, heap, struct_types, enumtype);
+
   return enumtype;
 }
 
@@ -5996,16 +6412,32 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
         undeclared identifier) - just ignore the value expression.  */
       if (value == error_mark_node)
        value = 0;
-      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
-              || TREE_CODE (value) != INTEGER_CST)
+      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
        {
          error ("enumerator value for %qE is not an integer constant", name);
          value = 0;
        }
       else
        {
-         value = default_conversion (value);
-         constant_expression_warning (value);
+         if (TREE_CODE (value) != INTEGER_CST)
+           {
+             value = c_fully_fold (value, false, NULL);
+             if (TREE_CODE (value) == INTEGER_CST)
+               pedwarn (value_loc, OPT_pedantic,
+                        "enumerator value for %qE is not an integer "
+                        "constant expression", name);
+           }
+         if (TREE_CODE (value) != INTEGER_CST)
+           {
+             error ("enumerator value for %qE is not an integer constant",
+                    name);
+             value = 0;
+           }
+         else
+           {
+             value = default_conversion (value);
+             constant_expression_warning (value);
+           }
        }
     }
 
@@ -6026,9 +6458,23 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
     pedwarn (value_loc, OPT_pedantic, 
             "ISO C restricts enumerator values to range of %<int%>");
 
+  /* The ISO C Standard mandates enumerators to have type int, even
+     though the underlying type of an enum type is unspecified.
+     However, GCC allows enumerators of any integer type as an
+     extensions.  Here we convert any enumerators that fit in an int
+     to type int, to avoid promotions to unsigned types when comparing
+     integers with enumerators that fit in the int range.  When
+     -pedantic is given, we would have already warned about those that
+     don't fit. We have to do this here rather than in finish_enum
+     because this value may be used to define more enumerators.  */
+  if (int_fits_type_p (value, integer_type_node))
+    value = convert (integer_type_node, value);
+
   /* Set basis for default for next value.  */
-  the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
-                                              integer_one_node, 0);
+  the_enum->enum_next_value
+    = build_binary_op
+         (EXPR_HAS_LOCATION (value) ? EXPR_LOCATION (value) : input_location,
+        PLUS_EXPR, value, integer_one_node, 0);
   the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 
   /* Now create a declaration for the enum value name.  */
@@ -6094,7 +6540,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
   c_break_label = c_cont_label = size_zero_node;
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
-                         &attributes, DEPRECATED_NORMAL);
+                         &attributes, NULL, NULL, DEPRECATED_NORMAL);
 
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
@@ -6323,7 +6769,8 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
       if (DECL_NAME (decl))
        {
          bind (DECL_NAME (decl), decl, current_scope,
-               /*invisible=*/false, /*nested=*/false);
+               /*invisible=*/false, /*nested=*/false,
+               UNKNOWN_LOCATION);
          if (!TREE_USED (decl))
            warn_if_shadowing (decl);
        }
@@ -6340,14 +6787,14 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
        bind (DECL_NAME (decl), decl, current_scope,
-             /*invisible=*/false, /*nested=*/false);
+             /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
     }
 
   /* And all the tag declarations.  */
   for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
     if (TREE_PURPOSE (decl))
       bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
-           /*invisible=*/false, /*nested=*/false);
+           /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
 }
 
 /* Subroutine of store_parm_decls which handles old-style function
@@ -6724,7 +7171,7 @@ finish_function (void)
       && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
       == integer_type_node && flag_isoc99)
     {
-      tree stmt = c_finish_return (integer_zero_node);
+      tree stmt = c_finish_return (integer_zero_node, NULL_TREE);
       /* Hack.  We don't want the middle-end to warn that this return
         is unreachable, so we mark its location as special.  Using
         UNKNOWN_LOCATION has the problem that it gets clobbered in
@@ -7107,10 +7554,12 @@ build_null_declspecs (void)
 {
   struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
   ret->type = 0;
+  ret->expr = 0;
   ret->decl_attr = 0;
   ret->attrs = 0;
   ret->typespec_word = cts_none;
   ret->storage_class = csc_none;
+  ret->expr_const_operands = true;
   ret->declspecs_seen_p = false;
   ret->type_seen_p = false;
   ret->non_sc_seen_p = false;
@@ -7213,8 +7662,8 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
                             "declaration specifiers");
                      break;
                    }
-                 if (pedantic && !flag_isoc99 && !in_system_header)
-                   pedwarn (input_location, OPT_Wlong_long, "ISO C90 does not support %<long long%>");
+                 pedwarn_c90 (input_location, OPT_Wlong_long, 
+                              "ISO C90 does not support %<long long%>");
                  specs->long_long_p = 1;
                  break;
                }
@@ -7632,7 +8081,18 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
       if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
        specs->tag_defined_p = true;
       if (spec.kind == ctsk_typeof)
-       specs->typedef_p = true;
+       {
+         specs->typedef_p = true;
+         if (spec.expr)
+           {
+             if (specs->expr)
+               specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+                                     specs->expr, spec.expr);
+             else
+               specs->expr = spec.expr;
+             specs->expr_const_operands &= spec.expr_const_operands;
+           }
+       }
       specs->type = type;
     }
 
@@ -7763,6 +8223,8 @@ finish_declspecs (struct c_declspecs *specs)
       if (specs->saturating_p)
        {
          error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+         if (!targetm.fixed_point_supported_p ())
+           error ("fixed-point types not supported for this target");
          specs->typespec_word = cts_fract;
        }
       else if (specs->long_p || specs->short_p
@@ -7885,8 +8347,10 @@ finish_declspecs (struct c_declspecs *specs)
        specs->type = dfloat128_type_node;
       break;
     case cts_fract:
-       gcc_assert (!specs->complex_p);
-       if (specs->saturating_p)
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
        {
          if (specs->long_long_p)
            specs->type = specs->unsigned_p
@@ -7904,7 +8368,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? sat_unsigned_fract_type_node
                          : sat_fract_type_node;
-          }
+       }
       else
        {
          if (specs->long_long_p)
@@ -7923,11 +8387,13 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? unsigned_fract_type_node
                          : fract_type_node;
-          }
+       }
       break;
     case cts_accum:
-       gcc_assert (!specs->complex_p);
-       if (specs->saturating_p)
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
        {
          if (specs->long_long_p)
            specs->type = specs->unsigned_p
@@ -7945,7 +8411,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? sat_unsigned_accum_type_node
                          : sat_accum_type_node;
-          }
+       }
       else
        {
          if (specs->long_long_p)
@@ -7964,7 +8430,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? unsigned_accum_type_node
                          : accum_type_node;
-          }
+       }
       break;
     default:
       gcc_unreachable ();
@@ -8040,7 +8506,7 @@ c_write_global_declarations (void)
 
   /* Don't waste time on further processing if -fsyntax-only or we've
      encountered errors.  */
-  if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+  if (flag_syntax_only || errorcount || sorrycount)
     return;
 
   /* Close the external scope.  */