OSDN Git Service

* cppfiles.c (cpp_make_system_header): Take 2 booleans,
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index fab3d1d..acc7446 100644 (file)
@@ -53,112 +53,10 @@ extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj));
 
 static void unsave_expr_now_r PARAMS ((tree));
 
-/* Tree nodes of permanent duration are allocated in this obstack.
-   They are the identifier nodes, and everything outside of
-   the bodies and parameters of function definitions.  */
+/* Objects allocated on this obstack last forever.  */
 
 struct obstack permanent_obstack;
 
-/* The initial RTL, and all ..._TYPE nodes, in a function
-   are allocated in this obstack.  Usually they are freed at the
-   end of the function, but if the function is inline they are saved.
-   For top-level functions, this is maybepermanent_obstack.
-   Separate obstacks are made for nested functions.  */
-
-struct obstack *function_maybepermanent_obstack;
-
-/* This is the function_maybepermanent_obstack for top-level functions.  */
-
-struct obstack maybepermanent_obstack;
-
-/* The contents of the current function definition are allocated
-   in this obstack, and all are freed at the end of the function.
-   For top-level functions, this is temporary_obstack.
-   Separate obstacks are made for nested functions.  */
-
-struct obstack *function_obstack;
-
-/* This is used for reading initializers of global variables.  */
-
-struct obstack temporary_obstack;
-
-/* The tree nodes of an expression are allocated
-   in this obstack, and all are freed at the end of the expression.  */
-
-struct obstack momentary_obstack;
-
-/* The tree nodes of a declarator are allocated
-   in this obstack, and all are freed when the declarator
-   has been parsed.  */
-
-static struct obstack temp_decl_obstack;
-
-/* This points at either permanent_obstack
-   or the current function_maybepermanent_obstack.  */
-
-struct obstack *saveable_obstack;
-
-/* This is same as saveable_obstack during parse and expansion phase;
-   it points to the current function's obstack during optimization.
-   This is the obstack to be used for creating rtl objects.  */
-
-struct obstack *rtl_obstack;
-
-/* This points at either permanent_obstack or the current function_obstack.  */
-
-struct obstack *current_obstack;
-
-/* This points at either permanent_obstack or the current function_obstack
-   or momentary_obstack.  */
-
-struct obstack *expression_obstack;
-
-/* Stack of obstack selections for push_obstacks and pop_obstacks.  */
-
-struct obstack_stack
-{
-  struct obstack_stack *next;
-  struct obstack *current;
-  struct obstack *saveable;
-  struct obstack *expression;
-  struct obstack *rtl;
-};
-
-struct obstack_stack *obstack_stack;
-
-/* Obstack for allocating struct obstack_stack entries.  */
-
-static struct obstack obstack_stack_obstack;
-
-/* Addresses of first objects in some obstacks.
-   This is for freeing their entire contents.  */
-char *maybepermanent_firstobj;
-char *temporary_firstobj;
-char *momentary_firstobj;
-char *temp_decl_firstobj;
-
-/* This is used to preserve objects (mainly array initializers) that need to
-   live until the end of the current function, but no further.  */
-char *momentary_function_firstobj;
-
-/* Nonzero means all ..._TYPE nodes should be allocated permanently.  */
-
-int all_types_permanent;
-
-/* Stack of places to restore the momentary obstack back to.  */
-
-struct momentary_level
-{
-  /* Pointer back to previous such level.  */
-  struct momentary_level *prev;
-  /* First object allocated within this level.  */
-  char *base;
-  /* Value of expression_obstack saved at entry to this level.  */
-  struct obstack *obstack;
-};
-
-struct momentary_level *momentary_stack;
-
 /* Table indexed by tree code giving a string containing a character
    classifying the tree code.  Possibilities are
    t, d, s, c, r, <, 1, 2 and e.  See tree.def for details.  */
@@ -233,14 +131,6 @@ static const char * const tree_node_kind_names[] = {
   "lang_type kinds"
 };
 
-/* Hash table for uniquizing IDENTIFIER_NODEs by name.  */
-
-#define MAX_HASH_TABLE 1009
-static tree hash_table[MAX_HASH_TABLE];        /* id hash buckets */
-
-/* 0 while creating built-in identifiers.  */
-static int do_identifier_warnings;
-
 /* Unique id for next decl created.  */
 static int next_decl_uid;
 /* Unique id for next type created.  */
@@ -280,6 +170,7 @@ static unsigned int type_hash_hash PARAMS ((const void*));
 static void print_type_hash_statistics PARAMS((void));
 static int mark_hash_entry PARAMS((void **, void *));
 static void finish_vector_type PARAMS((tree));
+static int mark_tree_hashtable_entry PARAMS((void **, void *));
 
 /* If non-null, these are language-specific helper functions for
    unsave_expr_now.  If present, LANG_UNSAVE is called before its
@@ -289,12 +180,9 @@ static void finish_vector_type PARAMS((tree));
 void (*lang_unsave) PARAMS ((tree *));
 void (*lang_unsave_expr_now) PARAMS ((tree));
 
-/* The string used as a placeholder instead of a source file name for
-   built-in tree nodes.  The variable, which is dynamically allocated,
-   should be used; the macro is only used to initialize it.  */
-
-static char *built_in_filename;
-#define BUILT_IN_FILENAME ("<built-in>")
+/* If non-null, these are language-specific helper functions for
+   unsafe_for_reeval.  Return negative to not handle some tree.  */
+int (*lang_unsafe_for_reeval) PARAMS ((tree));
 \f
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -304,30 +192,8 @@ tree integer_types[itk_none];
 void
 init_obstacks ()
 {
-  gcc_obstack_init (&obstack_stack_obstack);
   gcc_obstack_init (&permanent_obstack);
 
-  gcc_obstack_init (&temporary_obstack);
-  temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
-  gcc_obstack_init (&momentary_obstack);
-  momentary_firstobj = (char *) obstack_alloc (&momentary_obstack, 0);
-  momentary_function_firstobj = momentary_firstobj;
-  gcc_obstack_init (&maybepermanent_obstack);
-  maybepermanent_firstobj
-    = (char *) obstack_alloc (&maybepermanent_obstack, 0);
-  gcc_obstack_init (&temp_decl_obstack);
-  temp_decl_firstobj = (char *) obstack_alloc (&temp_decl_obstack, 0);
-
-  function_obstack = &temporary_obstack;
-  function_maybepermanent_obstack = &maybepermanent_obstack;
-  current_obstack = &permanent_obstack;
-  expression_obstack = &permanent_obstack;
-  rtl_obstack = saveable_obstack = &permanent_obstack;
-
-  /* Init the hash table of identifiers.  */
-  bzero ((char *) hash_table, sizeof hash_table);
-  ggc_add_tree_root (hash_table, sizeof hash_table / sizeof (tree));
-
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                 type_hash_eq, 0);
@@ -356,309 +222,7 @@ gcc_obstack_init (obstack)
                  (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE);
 }
 
-/* Save all variables describing the current status into the structure
-   *P.  This function is called whenever we start compiling one
-   function in the midst of compiling another.  For example, when
-   compiling a nested function, or, in C++, a template instantiation
-   that is required by the function we are currently compiling.
-
-   CONTEXT is the decl_function_context for the function we're about to
-   compile; if it isn't current_function_decl, we have to play some games.  */
-
-void
-save_tree_status (p)
-     struct function *p;
-{
-  p->all_types_permanent = all_types_permanent;
-  p->momentary_stack = momentary_stack;
-  p->maybepermanent_firstobj = maybepermanent_firstobj;
-  p->temporary_firstobj = temporary_firstobj;
-  p->momentary_firstobj = momentary_firstobj;
-  p->momentary_function_firstobj = momentary_function_firstobj;
-  p->function_obstack = function_obstack;
-  p->function_maybepermanent_obstack = function_maybepermanent_obstack;
-  p->current_obstack = current_obstack;
-  p->expression_obstack = expression_obstack;
-  p->saveable_obstack = saveable_obstack;
-  p->rtl_obstack = rtl_obstack;
-
-  function_maybepermanent_obstack
-    = (struct obstack *) xmalloc (sizeof (struct obstack));
-  gcc_obstack_init (function_maybepermanent_obstack);
-  maybepermanent_firstobj
-    = (char *) obstack_finish (function_maybepermanent_obstack);
-
-  function_obstack = (struct obstack *) xmalloc (sizeof (struct obstack));
-  gcc_obstack_init (function_obstack);
-
-  current_obstack = &permanent_obstack;
-  expression_obstack = &permanent_obstack;
-  rtl_obstack = saveable_obstack = &permanent_obstack;
-
-  temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
-  momentary_firstobj = (char *) obstack_finish (&momentary_obstack);
-  momentary_function_firstobj = momentary_firstobj;
-}
-
-/* Restore all variables describing the current status from the structure *P.
-   This is used after a nested function.  */
-
-void
-restore_tree_status (p)
-     struct function *p;
-{
-  all_types_permanent = p->all_types_permanent;
-  momentary_stack = p->momentary_stack;
-
-  obstack_free (&momentary_obstack, momentary_function_firstobj);
-
-  /* Free saveable storage used by the function just compiled and not
-     saved.  */
-  obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
-  if (obstack_empty_p (function_maybepermanent_obstack))
-    {
-      obstack_free (function_maybepermanent_obstack, NULL);
-      free (function_maybepermanent_obstack);
-    }
-
-  obstack_free (&temporary_obstack, temporary_firstobj);
-  obstack_free (&momentary_obstack, momentary_function_firstobj);
-
-  obstack_free (function_obstack, NULL);
-  free (function_obstack);
-
-  temporary_firstobj = p->temporary_firstobj;
-  momentary_firstobj = p->momentary_firstobj;
-  momentary_function_firstobj = p->momentary_function_firstobj;
-  maybepermanent_firstobj = p->maybepermanent_firstobj;
-  function_obstack = p->function_obstack;
-  function_maybepermanent_obstack = p->function_maybepermanent_obstack;
-  current_obstack = p->current_obstack;
-  expression_obstack = p->expression_obstack;
-  saveable_obstack = p->saveable_obstack;
-  rtl_obstack = p->rtl_obstack;
-}
 \f
-/* Start allocating on the temporary (per function) obstack.
-   This is done in start_function before parsing the function body,
-   and before each initialization at top level, and to go back
-   to temporary allocation after doing permanent_allocation.  */
-
-void
-temporary_allocation ()
-{
-  /* Note that function_obstack at top level points to temporary_obstack.
-     But within a nested function context, it is a separate obstack.  */
-  current_obstack = function_obstack;
-  expression_obstack = function_obstack;
-  rtl_obstack = saveable_obstack = function_maybepermanent_obstack;
-  momentary_stack = 0;
-}
-
-/* Start allocating on the permanent obstack but don't
-   free the temporary data.  After calling this, call
-   `permanent_allocation' to fully resume permanent allocation status.  */
-
-void
-end_temporary_allocation ()
-{
-  current_obstack = &permanent_obstack;
-  expression_obstack = &permanent_obstack;
-  rtl_obstack = saveable_obstack = &permanent_obstack;
-}
-
-/* Resume allocating on the temporary obstack, undoing
-   effects of `end_temporary_allocation'.  */
-
-void
-resume_temporary_allocation ()
-{
-  current_obstack = function_obstack;
-  expression_obstack = function_obstack;
-  rtl_obstack = saveable_obstack = function_maybepermanent_obstack;
-}
-
-/* While doing temporary allocation, switch to allocating in such a
-   way as to save all nodes if the function is inlined.  Call
-   resume_temporary_allocation to go back to ordinary temporary
-   allocation.  */
-
-void
-saveable_allocation ()
-{
-  /* Note that function_obstack at top level points to temporary_obstack.
-     But within a nested function context, it is a separate obstack.  */
-  expression_obstack = current_obstack = saveable_obstack;
-}
-
-/* Switch to current obstack CURRENT and maybepermanent obstack SAVEABLE,
-   recording the previously current obstacks on a stack.
-   This does not free any storage in any obstack.  */
-
-void
-push_obstacks (current, saveable)
-     struct obstack *current, *saveable;
-{
-  struct obstack_stack *p;
-
-  p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
-                                             (sizeof (struct obstack_stack)));
-
-  p->current = current_obstack;
-  p->saveable = saveable_obstack;
-  p->expression = expression_obstack;
-  p->rtl = rtl_obstack;
-  p->next = obstack_stack;
-  obstack_stack = p;
-
-  current_obstack = current;
-  expression_obstack = current;
-  rtl_obstack = saveable_obstack = saveable;
-}
-
-/* Save the current set of obstacks, but don't change them.  */
-
-void
-push_obstacks_nochange ()
-{
-  struct obstack_stack *p;
-
-  p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack,
-                                             (sizeof (struct obstack_stack)));
-
-  p->current = current_obstack;
-  p->saveable = saveable_obstack;
-  p->expression = expression_obstack;
-  p->rtl = rtl_obstack;
-  p->next = obstack_stack;
-  obstack_stack = p;
-}
-
-/* Pop the obstack selection stack.  */
-
-void
-pop_obstacks ()
-{
-  struct obstack_stack *p;
-
-  p = obstack_stack;
-  obstack_stack = p->next;
-
-  current_obstack = p->current;
-  saveable_obstack = p->saveable;
-  expression_obstack = p->expression;
-  rtl_obstack = p->rtl;
-
-  obstack_free (&obstack_stack_obstack, p);
-}
-
-/* Nonzero if temporary allocation is currently in effect.
-   Zero if currently doing permanent allocation.  */
-
-int
-allocation_temporary_p ()
-{
-  return current_obstack != &permanent_obstack;
-}
-
-/* Go back to allocating on the permanent obstack
-   and free everything in the temporary obstack.
-
-   FUNCTION_END is true only if we have just finished compiling a function.
-   In that case, we also free preserved initial values on the momentary
-   obstack.  */
-
-void
-permanent_allocation (function_end)
-     int function_end;
-{
-  /* Free up previous temporary obstack data */
-  obstack_free (&temporary_obstack, temporary_firstobj);
-  if (function_end)
-    {
-      obstack_free (&momentary_obstack, momentary_function_firstobj);
-      momentary_firstobj = momentary_function_firstobj;
-    }
-  else
-    obstack_free (&momentary_obstack, momentary_firstobj);
-
-  obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj);
-  obstack_free (&temp_decl_obstack, temp_decl_firstobj);
-
-  current_obstack = &permanent_obstack;
-  expression_obstack = &permanent_obstack;
-  rtl_obstack = saveable_obstack = &permanent_obstack;
-}
-
-/* Save permanently everything on the maybepermanent_obstack.  */
-
-void
-preserve_data ()
-{
-  maybepermanent_firstobj
-    = (char *) obstack_alloc (function_maybepermanent_obstack, 0);
-}
-
-void
-preserve_initializer ()
-{
-  struct momentary_level *tem;
-  char *old_momentary;
-
-  temporary_firstobj
-    = (char *) obstack_alloc (&temporary_obstack, 0);
-  maybepermanent_firstobj
-    = (char *) obstack_alloc (function_maybepermanent_obstack, 0);
-
-  old_momentary = momentary_firstobj;
-  momentary_firstobj
-    = (char *) obstack_alloc (&momentary_obstack, 0);
-  if (momentary_firstobj != old_momentary)
-    for (tem = momentary_stack; tem; tem = tem->prev)
-      tem->base = momentary_firstobj;
-}
-
-/* Start allocating new rtl in current_obstack.
-   Use resume_temporary_allocation
-   to go back to allocating rtl in saveable_obstack.  */
-
-void
-rtl_in_current_obstack ()
-{
-  rtl_obstack = current_obstack;
-}
-
-/* Start allocating rtl from saveable_obstack.  Intended to be used after
-   a call to push_obstacks_nochange.  */
-
-void
-rtl_in_saveable_obstack ()
-{
-  rtl_obstack = saveable_obstack;
-}
-\f
-/* Allocate SIZE bytes in the current obstack
-   and return a pointer to them.
-   In practice the current obstack is always the temporary one.  */
-
-char *
-oballoc (size)
-     int size;
-{
-  return (char *) obstack_alloc (current_obstack, size);
-}
-
-/* Free the object PTR in the current obstack
-   as well as everything allocated since PTR.
-   In practice the current obstack is always the temporary one.  */
-
-void
-obfree (ptr)
-     char *ptr;
-{
-  obstack_free (current_obstack, ptr);
-}
-
 /* Allocate SIZE bytes in the permanent obstack
    and return a pointer to them.  */
 
@@ -679,220 +243,10 @@ perm_calloc (nelem, size)
      long size;
 {
   char *rval = (char *) obstack_alloc (&permanent_obstack, nelem * size);
-  bzero (rval, nelem * size);
+  memset (rval, 0, nelem * size);
   return rval;
 }
 
-/* Allocate SIZE bytes in the saveable obstack
-   and return a pointer to them.  */
-
-char *
-savealloc (size)
-     int size;
-{
-  return (char *) obstack_alloc (saveable_obstack, size);
-}
-
-/* Allocate SIZE bytes in the expression obstack
-   and return a pointer to them.  */
-
-char *
-expralloc (size)
-     int size;
-{
-  return (char *) obstack_alloc (expression_obstack, size);
-}
-\f
-/* Print out which obstack an object is in.  */
-
-void
-print_obstack_name (object, file, prefix)
-     char *object;
-     FILE *file;
-     const char *prefix;
-{
-  struct obstack *obstack = NULL;
-  const char *obstack_name = NULL;
-  struct function *p;
-
-  for (p = outer_function_chain; p; p = p->next)
-    {
-      if (_obstack_allocated_p (p->function_obstack, object))
-       {
-         obstack = p->function_obstack;
-         obstack_name = "containing function obstack";
-       }
-      if (_obstack_allocated_p (p->function_maybepermanent_obstack, object))
-       {
-         obstack = p->function_maybepermanent_obstack;
-         obstack_name = "containing function maybepermanent obstack";
-       }
-    }
-
-  if (_obstack_allocated_p (&obstack_stack_obstack, object))
-    {
-      obstack = &obstack_stack_obstack;
-      obstack_name = "obstack_stack_obstack";
-    }
-  else if (_obstack_allocated_p (function_obstack, object))
-    {
-      obstack = function_obstack;
-      obstack_name = "function obstack";
-    }
-  else if (_obstack_allocated_p (&permanent_obstack, object))
-    {
-      obstack = &permanent_obstack;
-      obstack_name = "permanent_obstack";
-    }
-  else if (_obstack_allocated_p (&momentary_obstack, object))
-    {
-      obstack = &momentary_obstack;
-      obstack_name = "momentary_obstack";
-    }
-  else if (_obstack_allocated_p (function_maybepermanent_obstack, object))
-    {
-      obstack = function_maybepermanent_obstack;
-      obstack_name = "function maybepermanent obstack";
-    }
-  else if (_obstack_allocated_p (&temp_decl_obstack, object))
-    {
-      obstack = &temp_decl_obstack;
-      obstack_name = "temp_decl_obstack";
-    }
-
-  /* Check to see if the object is in the free area of the obstack.  */
-  if (obstack != NULL)
-    {
-      if (object >= obstack->next_free
-         && object < obstack->chunk_limit)
-       fprintf (file, "%s in free portion of obstack %s",
-                prefix, obstack_name);
-      else
-       fprintf (file, "%s allocated from %s", prefix, obstack_name);
-    }
-  else
-    fprintf (file, "%s not allocated from any obstack", prefix);
-}
-
-void
-debug_obstack (object)
-     char *object;
-{
-  print_obstack_name (object, stderr, "object");
-  fprintf (stderr, ".\n");
-}
-
-/* Return 1 if OBJ is in the permanent obstack.
-   This is slow, and should be used only for debugging.
-   Use TREE_PERMANENT for other purposes.  */
-
-int
-object_permanent_p (obj)
-     tree obj;
-{
-  return _obstack_allocated_p (&permanent_obstack, obj);
-}
-\f
-/* Start a level of momentary allocation.
-   In C, each compound statement has its own level
-   and that level is freed at the end of each statement.
-   All expression nodes are allocated in the momentary allocation level.  */
-
-void
-push_momentary ()
-{
-  struct momentary_level *tem
-    = (struct momentary_level *) obstack_alloc (&momentary_obstack,
-                                               sizeof (struct momentary_level));
-  tem->prev = momentary_stack;
-  tem->base = (char *) obstack_base (&momentary_obstack);
-  tem->obstack = expression_obstack;
-  momentary_stack = tem;
-  expression_obstack = &momentary_obstack;
-}
-
-/* Set things up so the next clear_momentary will only clear memory
-   past our present position in momentary_obstack.  */
-
-void
-preserve_momentary ()
-{
-  momentary_stack->base = (char *) obstack_base (&momentary_obstack);
-}
-
-/* Free all the storage in the current momentary-allocation level.
-   In C, this happens at the end of each statement.  */
-
-void
-clear_momentary ()
-{
-  obstack_free (&momentary_obstack, momentary_stack->base);
-}
-
-/* Discard a level of momentary allocation.
-   In C, this happens at the end of each compound statement.
-   Restore the status of expression node allocation
-   that was in effect before this level was created.  */
-
-void
-pop_momentary ()
-{
-  struct momentary_level *tem = momentary_stack;
-  momentary_stack = tem->prev;
-  expression_obstack = tem->obstack;
-  /* We can't free TEM from the momentary_obstack, because there might
-     be objects above it which have been saved.  We can free back to the
-     stack of the level we are popping off though.  */
-  obstack_free (&momentary_obstack, tem->base);
-}
-
-/* Pop back to the previous level of momentary allocation,
-   but don't free any momentary data just yet.  */
-
-void
-pop_momentary_nofree ()
-{
-  struct momentary_level *tem = momentary_stack;
-  momentary_stack = tem->prev;
-  expression_obstack = tem->obstack;
-}
-
-/* Call when starting to parse a declaration:
-   make expressions in the declaration last the length of the function.
-   Returns an argument that should be passed to resume_momentary later.  */
-
-int
-suspend_momentary ()
-{
-  register int tem = expression_obstack == &momentary_obstack;
-  expression_obstack = saveable_obstack;
-  return tem;
-}
-
-/* Call when finished parsing a declaration:
-   restore the treatment of node-allocation that was
-   in effect before the suspension.
-   YES should be the value previously returned by suspend_momentary.  */
-
-void
-resume_momentary (yes)
-     int yes;
-{
-  if (yes)
-    expression_obstack = &momentary_obstack;
-}
-\f
-/* Init the tables indexed by tree code.
-   Note that languages can add to these tables to define their own codes.  */
-
-void
-init_tree_codes ()
-{
-  built_in_filename
-    = ggc_alloc_string (BUILT_IN_FILENAME, sizeof (BUILT_IN_FILENAME));
-  ggc_add_string_root (&built_in_filename, 1);
-}
-
 /* Compute the number of bytes occupied by 'node'.  This routine only
    looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
 size_t
@@ -951,9 +305,6 @@ tree_size (node)
 }
 
 /* Return a newly allocated node of code CODE.
-   Initialize the node's unique id and its TREE_PERMANENT flag.
-   Note that if garbage collection is in use, TREE_PERMANENT will
-   always be zero - we want to eliminate use of TREE_PERMANENT.
    For decl and type nodes, some other fields are initialized.
    The rest of the node is initialized to zero.
 
@@ -1037,7 +388,6 @@ make_node (code)
   memset ((PTR) t, 0, length);
 
   TREE_SET_CODE (t, code);
-  TREE_SET_PERMANENT (t);
 
   switch (type)
     {
@@ -1053,7 +403,7 @@ make_node (code)
       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
       DECL_SOURCE_LINE (t) = lineno;
       DECL_SOURCE_FILE (t) =
-       (input_filename) ? input_filename : built_in_filename;
+       (input_filename) ? input_filename : "<built-in>";
       DECL_UID (t) = next_decl_uid++;
       /* Note that we have not yet computed the alias set for this
         declaration.  */
@@ -1062,7 +412,7 @@ make_node (code)
 
     case 't':
       TYPE_UID (t) = next_type_uid++;
-      TYPE_ALIGN (t) = 1;
+      TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0;
       TYPE_USER_ALIGN (t) = 0;
       TYPE_MAIN_VARIANT (t) = t;
       TYPE_ATTRIBUTES (t) = NULL_TREE;
@@ -1133,10 +483,7 @@ copy_node (node)
   register size_t length;
 
   length = tree_size (node);
-  if (ggc_p)
-    t = ggc_alloc_tree (length);
-  else
-    t = (tree) obstack_alloc (current_obstack, length);
+  t = ggc_alloc_tree (length);
   memcpy (t, node, length);
 
   TREE_CHAIN (t) = 0;
@@ -1147,8 +494,6 @@ copy_node (node)
   else if (TREE_CODE_CLASS (code) == 't')
     {
       TYPE_UID (t) = next_type_uid++;
-      TYPE_OBSTACK (t) = current_obstack;
-
       /* The following is so that the debug code for
         the copy is different from the original type.
         The two statements usually duplicate each other
@@ -1158,8 +503,6 @@ copy_node (node)
       TYPE_SYMTAB_ADDRESS (t) = 0;
     }
 
-  TREE_SET_PERMANENT (t);
-
   return t;
 }
 
@@ -1186,136 +529,7 @@ copy_list (list)
     }
   return head;
 }
-\f
-#define HASHBITS 30
-
-/* Return an IDENTIFIER_NODE whose name is TEXT (a null-terminated string).
-   If an identifier with that name has previously been referred to,
-   the same node is returned this time.  */
-
-tree
-get_identifier (text)
-     register const char *text;
-{
-  register int hi;
-  register int i;
-  register tree idp;
-  register int len, hash_len;
-
-  /* Compute length of text in len.  */
-  len = strlen (text);
-
-  /* Decide how much of that length to hash on */
-  hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
-    hash_len = id_clash_len;
-
-  /* Compute hash code */
-  hi = hash_len * 613 + (unsigned) text[0];
-  for (i = 1; i < hash_len; i += 2)
-    hi = ((hi * 613) + (unsigned) (text[i]));
-
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_HASH_TABLE;
-
-  /* Search table for identifier.  */
-  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-    if (IDENTIFIER_LENGTH (idp) == len
-       && IDENTIFIER_POINTER (idp)[0] == text[0]
-       && !bcmp (IDENTIFIER_POINTER (idp), text, len))
-      /* Return if found.  */
-      return idp;
-
-  /* Not found; optionally warn about a similar identifier.  */
-  if (warn_id_clash && do_identifier_warnings && len >= id_clash_len)
-    for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-      if (!strncmp (IDENTIFIER_POINTER (idp), text, id_clash_len))
-       {
-         warning ("`%s' and `%s' identical in first %d characters",
-                  IDENTIFIER_POINTER (idp), text, id_clash_len);
-         break;
-       }
-
-  if (TREE_CODE_LENGTH (IDENTIFIER_NODE) < 0)
-    abort ();                  /* set_identifier_size hasn't been called.  */
-
-  /* Not found, create one, add to chain */
-  idp = make_node (IDENTIFIER_NODE);
-  IDENTIFIER_LENGTH (idp) = len;
-#ifdef GATHER_STATISTICS
-  id_string_size += len;
-#endif
 
-  if (ggc_p)
-    IDENTIFIER_POINTER (idp) = ggc_alloc_string (text, len);
-  else
-    IDENTIFIER_POINTER (idp) = obstack_copy0 (&permanent_obstack, text, len);
-
-  TREE_CHAIN (idp) = hash_table[hi];
-  hash_table[hi] = idp;
-  return idp;                  /* <-- return if created */
-}
-
-/* If an identifier with the name TEXT (a null-terminated string) has
-   previously been referred to, return that node; otherwise return
-   NULL_TREE.  */
-
-tree
-maybe_get_identifier (text)
-     register const char *text;
-{
-  register int hi;
-  register int i;
-  register tree idp;
-  register int len, hash_len;
-
-  /* Compute length of text in len.  */
-  len = strlen (text);
-
-  /* Decide how much of that length to hash on */
-  hash_len = len;
-  if (warn_id_clash && len > id_clash_len)
-    hash_len = id_clash_len;
-
-  /* Compute hash code */
-  hi = hash_len * 613 + (unsigned) text[0];
-  for (i = 1; i < hash_len; i += 2)
-    hi = ((hi * 613) + (unsigned) (text[i]));
-
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_HASH_TABLE;
-
-  /* Search table for identifier.  */
-  for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
-    if (IDENTIFIER_LENGTH (idp) == len
-       && IDENTIFIER_POINTER (idp)[0] == text[0]
-       && !bcmp (IDENTIFIER_POINTER (idp), text, len))
-      return idp;              /* <-- return if found */
-
-  return NULL_TREE;
-}
-
-/* Enable warnings on similar identifiers (if requested).
-   Done after the built-in identifiers are created.  */
-
-void
-start_identifier_warnings ()
-{
-  do_identifier_warnings = 1;
-}
-
-/* Record the size of an identifier node for the language in use.
-   SIZE is the total size in bytes.
-   This is called by the language-specific files.  This must be
-   called before allocating any identifiers.  */
-
-void
-set_identifier_size (size)
-     int size;
-{
-  tree_code_length[(int) IDENTIFIER_NODE]
-    = (size - sizeof (struct tree_common)) / sizeof (tree);
-}
 \f
 /* Return a newly constructed INTEGER_CST node whose constant value
    is specified by the two ints LOW and HI.
@@ -1373,7 +587,7 @@ real_value_from_int_cst (type, i)
 #ifdef REAL_ARITHMETIC
   /* Clear all bits of the real value type so that we can later do
      bitwise comparisons to see if two values are the same.  */
-  bzero ((char *) &d, sizeof d);
+  memset ((char *) &d, 0, sizeof d);
 
   if (! TREE_UNSIGNED (TREE_TYPE (i)))
     REAL_VALUE_FROM_INT (d, TREE_INT_CST_LOW (i), TREE_INT_CST_HIGH (i),
@@ -1492,17 +706,10 @@ build_string (len, str)
      int len;
      const char *str;
 {
-  /* Put the string in saveable_obstack since it will be placed in the RTL
-     for an "asm" statement and will also be kept around a while if
-     deferring constant output in varasm.c.  */
-
   register tree s = make_node (STRING_CST);
 
   TREE_STRING_LENGTH (s) = len;
-  if (ggc_p)
-    TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
-  else
-    TREE_STRING_POINTER (s) = obstack_copy0 (saveable_obstack, str, len);
+  TREE_STRING_POINTER (s) = ggc_alloc_string (str, len);
 
   return s;
 }
@@ -1536,22 +743,17 @@ make_tree_vec (len)
 {
   register tree t;
   register int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
-  register struct obstack *obstack = current_obstack;
 
 #ifdef GATHER_STATISTICS
   tree_node_counts[(int)vec_kind]++;
   tree_node_sizes[(int)vec_kind] += length;
 #endif
 
-  if (ggc_p)
-    t = ggc_alloc_tree (length);
-  else
-    t = (tree) obstack_alloc (obstack, length);
+  t = ggc_alloc_tree (length);
 
   memset ((PTR) t, 0, length);
   TREE_SET_CODE (t, TREE_VEC);
   TREE_VEC_LENGTH (t) = len;
-  TREE_SET_PERMANENT (t);
 
   return t;
 }
@@ -2062,36 +1264,6 @@ build_tree_list (parm, value)
   return t;
 }
 
-/* Similar, but build on the temp_decl_obstack.  */
-
-tree
-build_decl_list (parm, value)
-     tree parm, value;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = &temp_decl_obstack;
-  node = build_tree_list (parm, value);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
-/* Similar, but build on the expression_obstack.  */
-
-tree
-build_expr_list (parm, value)
-     tree parm, value;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = expression_obstack;
-  node = build_tree_list (parm, value);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
 /* Return a newly created TREE_LIST node whose
    purpose and value fields are PARM and VALUE
    and whose TREE_CHAIN is CHAIN.  */
@@ -2102,10 +1274,7 @@ tree_cons (purpose, value, chain)
 {
   register tree node;
 
-  if (ggc_p)
-    node = ggc_alloc_tree (sizeof (struct tree_list));
-  else
-    node = (tree) obstack_alloc (current_obstack, sizeof (struct tree_list));
+  node = ggc_alloc_tree (sizeof (struct tree_list));
 
   memset (node, 0, sizeof (struct tree_common));
 
@@ -2115,88 +1284,12 @@ tree_cons (purpose, value, chain)
 #endif
 
   TREE_SET_CODE (node, TREE_LIST);
-  TREE_SET_PERMANENT (node);
-
   TREE_CHAIN (node) = chain;
   TREE_PURPOSE (node) = purpose;
   TREE_VALUE (node) = value;
   return node;
 }
 
-/* Similar, but build on the temp_decl_obstack.  */
-
-tree
-decl_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = &temp_decl_obstack;
-  node = tree_cons (purpose, value, chain);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
-/* Similar, but build on the expression_obstack.  */
-
-tree
-expr_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = expression_obstack;
-  node = tree_cons (purpose, value, chain);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
-/* Same as `tree_cons' but make a permanent object.  */
-
-tree
-perm_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = &permanent_obstack;
-  node = tree_cons (purpose, value, chain);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
-/* Same as `tree_cons', but make this node temporary, regardless.  */
-
-tree
-temp_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = &temporary_obstack;
-  node = tree_cons (purpose, value, chain);
-  current_obstack = ambient_obstack;
-  return node;
-}
-
-/* Same as `tree_cons', but save this node if the function's RTL is saved.  */
-
-tree
-saveable_tree_cons (purpose, value, chain)
-     tree purpose, value, chain;
-{
-  register tree node;
-  register struct obstack *ambient_obstack = current_obstack;
-
-  current_obstack = saveable_obstack;
-  node = tree_cons (purpose, value, chain);
-  current_obstack = ambient_obstack;
-  return node;
-}
 \f
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -2482,6 +1575,7 @@ save_expr (expr)
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
+  TREE_READONLY (t) = 1;
   return t;
 }
 
@@ -2518,8 +1612,6 @@ first_rtl_op (code)
     case GOTO_SUBROUTINE_EXPR:
     case RTL_EXPR:
       return 0;
-    case CALL_EXPR:
-      return 2;
     case WITH_CLEANUP_EXPR:
       /* Should be defined to be 2.  */
       return 1;
@@ -2562,10 +1654,6 @@ unsave_expr_1 (expr)
        abort ();
       break;
 
-    case CALL_EXPR:
-      CALL_EXPR_RTL (expr) = 0;
-      break;
-
     default:
       if (lang_unsave_expr_now != 0)
        (*lang_unsave_expr_now) (expr);
@@ -2694,7 +1782,12 @@ unsafe_for_reeval (expr)
       break;
 
     default:
-      /* ??? Add a lang hook if it becomes necessary.  */
+      if (lang_unsafe_for_reeval != 0)
+       {
+         tmp = (*lang_unsafe_for_reeval) (expr);
+         if (tmp >= 0)
+           return tmp;
+       }
       break;
     }
 
@@ -2928,6 +2021,9 @@ substitute_in_expr (exp, f, r)
          if (op0 == TREE_OPERAND (exp, 0))
            return exp;
 
+         if (code == NON_LVALUE_EXPR)
+           return op0;
+
          new = fold (build1 (code, TREE_TYPE (exp), op0));
          break;
 
@@ -3243,10 +2339,10 @@ build VPARAMS ((enum tree_code code, tree tt, ...))
   length = TREE_CODE_LENGTH (code);
   TREE_TYPE (t) = tt;
 
-  /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_RAISED for
-     the result based on those same flags for the arguments.  But, if
-     the arguments aren't really even `tree' expressions, we shouldn't
-     be trying to do this.  */
+  /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
+     result based on those same flags for the arguments.  But if the
+     arguments aren't really even `tree' expressions, we shouldn't be trying
+     to do this.  */
   fro = first_rtl_op (code);
 
   if (length == 2)
@@ -3254,38 +2350,45 @@ build VPARAMS ((enum tree_code code, tree tt, ...))
       /* This is equivalent to the loop below, but faster.  */
       register tree arg0 = va_arg (p, tree);
       register tree arg1 = va_arg (p, tree);
+
       TREE_OPERAND (t, 0) = arg0;
       TREE_OPERAND (t, 1) = arg1;
+      TREE_READONLY (t) = 1;
       if (arg0 && fro > 0)
        {
          if (TREE_SIDE_EFFECTS (arg0))
            TREE_SIDE_EFFECTS (t) = 1;
+         if (!TREE_READONLY (arg0))
+           TREE_READONLY (t) = 0;
        }
+
       if (arg1 && fro > 1)
        {
          if (TREE_SIDE_EFFECTS (arg1))
            TREE_SIDE_EFFECTS (t) = 1;
+         if (!TREE_READONLY (arg1))
+           TREE_READONLY (t) = 0;
        }
     }
   else if (length == 1)
     {
       register tree arg0 = va_arg (p, tree);
 
-      /* Call build1 for this!  */
+      /* The only one-operand cases we handle here are those with side-effects.
+        Others are handled with build1.  So don't bother checked if the
+        arg has side-effects since we'll already have set it.
+
+        ??? This really should use build1 too.  */
       if (TREE_CODE_CLASS (code) != 's')
        abort ();
       TREE_OPERAND (t, 0) = arg0;
-      if (fro > 0)
-       {
-         if (arg0 && TREE_SIDE_EFFECTS (arg0))
-           TREE_SIDE_EFFECTS (t) = 1;
-       }
     }
   else
     {
       for (i = 0; i < length; i++)
        {
          register tree operand = va_arg (p, tree);
+
          TREE_OPERAND (t, i) = operand;
          if (operand && fro > i)
            {
@@ -3308,7 +2411,6 @@ build1 (code, type, node)
      tree type;
      tree node;
 {
-  register struct obstack *obstack = expression_obstack;
   register int length;
 #ifdef GATHER_STATISTICS
   register tree_node_kind kind;
@@ -3324,10 +2426,7 @@ build1 (code, type, node)
 
   length = sizeof (struct tree_exp);
 
-  if (ggc_p)
-    t = ggc_alloc_tree (length);
-  else
-    t = (tree) obstack_alloc (obstack, length);
+  t = ggc_alloc_tree (length);
 
   memset ((PTR) t, 0, sizeof (struct tree_common));
 
@@ -3337,13 +2436,15 @@ build1 (code, type, node)
 #endif
 
   TREE_SET_CODE (t, code);
-  TREE_SET_PERMANENT (t);
 
   TREE_TYPE (t) = type;
   TREE_COMPLEXITY (t) = 0;
   TREE_OPERAND (t, 0) = node;
-  if (node && first_rtl_op (code) != 0 && TREE_SIDE_EFFECTS (node))
-    TREE_SIDE_EFFECTS (t) = 1;
+  if (node && first_rtl_op (code) != 0)
+    {
+      TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
+      TREE_READONLY (t) = TREE_READONLY (node);
+    }
 
   switch (code)
     {
@@ -3358,6 +2459,7 @@ build1 (code, type, node)
       /* All of these have side-effects, no matter what their
         operands are.  */
       TREE_SIDE_EFFECTS (t) = 1;
+      TREE_READONLY (t) = 0;
       break;
 
     default:
@@ -3408,7 +2510,6 @@ build_parse_node VPARAMS ((enum tree_code code, ...))
 #ifndef ANSI_PROTOTYPES
   enum tree_code code;
 #endif
-  register struct obstack *ambient_obstack = expression_obstack;
   va_list p;
   register tree t;
   register int length;
@@ -3420,8 +2521,6 @@ build_parse_node VPARAMS ((enum tree_code code, ...))
   code = va_arg (p, enum tree_code);
 #endif
 
-  expression_obstack = &temp_decl_obstack;
-
   t = make_node (code);
   length = TREE_CODE_LENGTH (code);
 
@@ -3429,7 +2528,6 @@ build_parse_node VPARAMS ((enum tree_code code, ...))
     TREE_OPERAND (t, i) = va_arg (p, tree);
 
   va_end (p);
-  expression_obstack = ambient_obstack;
   return t;
 }
 
@@ -3554,7 +2652,6 @@ build_type_attribute_variant (ttype, attribute)
       unsigned int hashcode;
       tree ntype;
 
-      push_obstacks (TYPE_OBSTACK (ttype), TYPE_OBSTACK (ttype));
       ntype = copy_node (ttype);
 
       TYPE_POINTER_TO (ntype) = 0;
@@ -3590,7 +2687,6 @@ build_type_attribute_variant (ttype, attribute)
 
       ntype = type_hash_canon (hashcode, ntype);
       ttype = build_qualified_type (ntype, TYPE_QUALS (ttype));
-      pop_obstacks ();
     }
 
   return ttype;
@@ -3906,11 +3002,8 @@ build_type_copy (type)
      tree type;
 {
   register tree t, m = TYPE_MAIN_VARIANT (type);
-  register struct obstack *ambient_obstack = current_obstack;
 
-  current_obstack = TYPE_OBSTACK (type);
   t = copy_node (type);
-  current_obstack = ambient_obstack;
 
   TYPE_POINTER_TO (t) = 0;
   TYPE_REFERENCE_TO (t) = 0;
@@ -4053,9 +3146,6 @@ type_hash_canon (hashcode, type)
   t1 = type_hash_lookup (hashcode, type);
   if (t1 != 0)
     {
-      if (!ggc_p)
-       obstack_free (TYPE_OBSTACK (type), type);
-
 #ifdef GATHER_STATISTICS
       tree_node_counts[(int) t_kind]--;
       tree_node_sizes[(int) t_kind] -= sizeof (struct tree_type);
@@ -4064,8 +3154,7 @@ type_hash_canon (hashcode, type)
     }
 
   /* If this is a permanent type, record it for later reuse.  */
-  if (ggc_p || TREE_PERMANENT (type))
-    type_hash_add (hashcode, type);
+  type_hash_add (hashcode, type);
 
   return type;
 }
@@ -4096,6 +3185,29 @@ mark_type_hash (arg)
   htab_traverse (t, mark_hash_entry, 0);
 }
 
+/* Mark the hashtable slot pointed to by ENTRY (which is really a
+   `tree**') for GC.  */
+
+static int
+mark_tree_hashtable_entry (entry, data)
+     void **entry;
+     void *data ATTRIBUTE_UNUSED;
+{
+  ggc_mark_tree ((tree) *entry);
+  return 1;
+}
+
+/* Mark ARG (which is really a htab_t whose slots are trees) for 
+   GC.  */
+
+void
+mark_tree_hashtable (arg)
+     void *arg;
+{
+  htab_t t = *(htab_t *) arg;
+  htab_traverse (t, mark_tree_hashtable_entry, 0);
+}
+
 static void
 print_type_hash_statistics ()
 {
@@ -4389,7 +3501,7 @@ simple_cst_equal (t1, t2)
 
     case STRING_CST:
       return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
-             && ! bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+             && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
                         TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
@@ -4520,10 +3632,8 @@ build_pointer_type (to_type)
   if (t != 0)
     return t;
 
-  /* We need a new one.  Put this in the same obstack as TO_TYPE.   */
-  push_obstacks (TYPE_OBSTACK (to_type), TYPE_OBSTACK (to_type));
+  /* We need a new one.  */
   t = make_node (POINTER_TYPE);
-  pop_obstacks ();
 
   TREE_TYPE (t) = to_type;
 
@@ -4551,10 +3661,8 @@ build_reference_type (to_type)
   if (t)
     return t;
 
-  /* We need a new one.  Put this in the same obstack as TO_TYPE.   */
-  push_obstacks (TYPE_OBSTACK (to_type), TYPE_OBSTACK (to_type));
+  /* We need a new one.  */
   t = make_node (REFERENCE_TYPE);
-  pop_obstacks ();
 
   TREE_TYPE (t) = to_type;
 
@@ -4566,6 +3674,26 @@ build_reference_type (to_type)
   return t;
 }
 
+/* Build a type that is compatible with t but has no cv quals anywhere
+   in its type, thus
+
+   const char *const *const *  ->  char ***.  */
+
+tree
+build_type_no_quals (t)
+  tree t;
+{
+  switch (TREE_CODE (t))
+    {
+    case POINTER_TYPE:
+      return build_pointer_type (build_type_no_quals (TREE_TYPE (t)));
+    case REFERENCE_TYPE:
+      return build_reference_type (build_type_no_quals (TREE_TYPE (t)));
+    default:
+      return TYPE_MAIN_VARIANT (t);
+    }
+}
+
 /* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
    MAXVAL should be the maximum value in the domain
    (one less than the length of the array).
@@ -4584,11 +3712,7 @@ build_index_type (maxval)
   TREE_TYPE (itype) = sizetype;
   TYPE_PRECISION (itype) = TYPE_PRECISION (sizetype);
   TYPE_MIN_VALUE (itype) = size_zero_node;
-
-  push_obstacks (TYPE_OBSTACK (itype), TYPE_OBSTACK (itype));
   TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
-  pop_obstacks ();
-
   TYPE_MODE (itype) = TYPE_MODE (sizetype);
   TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
   TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
@@ -4616,10 +3740,8 @@ build_range_type (type, lowval, highval)
   if (type == NULL_TREE)
     type = sizetype;
 
-  push_obstacks (TYPE_OBSTACK (itype), TYPE_OBSTACK (itype));
   TYPE_MIN_VALUE (itype) = convert (type, lowval);
   TYPE_MAX_VALUE (itype) = highval ? convert (type, highval) : NULL;
-  pop_obstacks ();
 
   TYPE_PRECISION (itype) = TYPE_PRECISION (type);
   TYPE_MODE (itype) = TYPE_MODE (type);
@@ -4969,10 +4091,11 @@ get_unwidened (op, for_type)
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (type) != REAL_TYPE
       /* Don't crash if field not laid out yet.  */
-      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
+      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
+      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
     {
       unsigned int innerprec
-       = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
+       = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
 
       type = type_for_size (innerprec, TREE_UNSIGNED (TREE_OPERAND (op, 1)));
 
@@ -4994,6 +4117,7 @@ get_unwidened (op, for_type)
          TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
        }
     }
+
   return win;
 }
 \f
@@ -5092,22 +4216,32 @@ int
 int_fits_type_p (c, type)
      tree c, type;
 {
-  if (TREE_UNSIGNED (type))
-    return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-              && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c))
-           && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type)))
-           /* Negative ints never fit unsigned types.  */
-           && ! (TREE_INT_CST_HIGH (c) < 0
-                 && ! TREE_UNSIGNED (TREE_TYPE (c))));
+  /* If the bounds of the type are integers, we can check ourselves.
+     Otherwise,. use force_fit_type, which checks against the precision.  */
+  if (TYPE_MAX_VALUE (type) != NULL_TREE
+      && TYPE_MIN_VALUE (type) != NULL_TREE
+      && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+      && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
+    {
+      if (TREE_UNSIGNED (type))
+       return (! INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type), c)
+               && ! INT_CST_LT_UNSIGNED (c, TYPE_MIN_VALUE (type))
+               /* Negative ints never fit unsigned types.  */
+               && ! (TREE_INT_CST_HIGH (c) < 0
+                     && ! TREE_UNSIGNED (TREE_TYPE (c))));
+      else
+       return (! INT_CST_LT (TYPE_MAX_VALUE (type), c)
+               && ! INT_CST_LT (c, TYPE_MIN_VALUE (type))
+               /* Unsigned ints with top bit set never fit signed types.  */
+               && ! (TREE_INT_CST_HIGH (c) < 0
+                     && TREE_UNSIGNED (TREE_TYPE (c))));
+    }
   else
-    return (! (TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
-              && INT_CST_LT (TYPE_MAX_VALUE (type), c))
-           && ! (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
-                 && INT_CST_LT (c, TYPE_MIN_VALUE (type)))
-           /* Unsigned ints with top bit set never fit signed types.  */
-           && ! (TREE_INT_CST_HIGH (c) < 0
-                 && TREE_UNSIGNED (TREE_TYPE (c))));
+    {
+      c = copy_node (c);
+      TREE_TYPE (c) = type;
+      return !force_fit_type (c, 0);
+    }
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or
@@ -5281,10 +4415,6 @@ dump_tree_statistics ()
   fprintf (stderr, "(No per-node statistics)\n");
 #endif
   print_obstack_statistics ("permanent_obstack", &permanent_obstack);
-  print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
-  print_obstack_statistics ("temporary_obstack", &temporary_obstack);
-  print_obstack_statistics ("momentary_obstack", &momentary_obstack);
-  print_obstack_statistics ("temp_decl_obstack", &temp_decl_obstack);
   print_type_hash_statistics ();
   print_lang_statistics ();
 }
@@ -5709,7 +4839,7 @@ build_common_tree_nodes_2 (short_double)
 #ifdef BUILD_VA_LIST_TYPE
   BUILD_VA_LIST_TYPE (va_list_type_node);
 #else
-  va_list_type_node = ptr_type_node;
+  va_list_type_node = build_type_copy (ptr_type_node);
 #endif
 
   V4SF_type_node = make_node (VECTOR_TYPE);