OSDN Git Service

2003-06-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 0d81341..d194012 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002 Free Software Foundation, Inc.
+   2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,24 +21,27 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "intl.h"
 #include "tree.h"
-#include "real.h"
 #include "flags.h"
 #include "toplev.h"
 #include "output.h"
 #include "c-pragma.h"
 #include "rtl.h"
 #include "ggc.h"
+#include "varray.h"
 #include "expr.h"
 #include "c-common.h"
-#include "tree-inline.h"
 #include "diagnostic.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "cpplib.h"
 #include "target.h"
 #include "langhooks.h"
-#include "except.h"            /* For USING_SJLJ_EXCEPTIONS.  */
+#include "tree-inline.h"
+#include "c-tree.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -84,14 +87,6 @@ cpp_reader *parse_in;                /* Declared in c-pragma.h.  */
                        : "long long unsigned int"))
 #endif
 
-#ifndef STDC_0_IN_SYSTEM_HEADERS
-#define STDC_0_IN_SYSTEM_HEADERS 0
-#endif
-
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-
 /* The variant of the C language being processed.  */
 
 enum c_language_kind c_language;
@@ -192,13 +187,50 @@ enum c_language_kind c_language;
 
 tree c_global_trees[CTI_MAX];
 
+/* TRUE if a code represents a statement.  The front end init
+   langhook should take care of initialization of this array.  */
+
+bool statement_code_p[MAX_TREE_CODES];
+
+/* Nonzero if we can read a PCH file now.  */
+
+int allow_pch = 1;
+\f
+/* Switches common to the C front ends.  */
+
 /* Nonzero if prepreprocessing only.  */
+
 int flag_preprocess_only;
 
+/* Nonzero means don't output line number information.  */
+
+char flag_no_line_commands;
+
+/* Nonzero causes -E output not to be done, but directives such as
+   #define that have side effects are still obeyed.  */
+
+char flag_no_output;
+
+/* Nonzero means dump macros in some fashion.  */
+
+char flag_dump_macros;
+
+/* Nonzero means pass #include lines through to the output.  */
+
+char flag_dump_includes;
+
+/* The file name to which we should write a precompiled header, or
+   NULL if no header will be written in this compile.  */
+
+const char *pch_file;
+
 /* Nonzero if an ISO standard was selected.  It rejects macros in the
    user's namespace.  */
 int flag_iso;
 
+/* Nonzero whenever Objective-C functionality is being used.  */
+int flag_objc;
+
 /* Nonzero if -undef was given.  It suppresses target built-in macros
    and assertions.  */
 int flag_undef;
@@ -223,9 +255,170 @@ int flag_short_wchar;
 /* Nonzero means allow Microsoft extensions without warnings or errors.  */
 int flag_ms_extensions;
 
-/* Nonzero means warn about use of multicharacter literals.  */
+/* Nonzero means don't recognize the keyword `asm'.  */
+
+int flag_no_asm;
+
+/* Nonzero means give string constants the type `const char *', as mandated
+   by the standard.  */
+
+int flag_const_strings;
+
+/* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
+
+int flag_signed_bitfields = 1;
+int explicit_flag_signed_bitfields;
+
+/* Nonzero means warn about pointer casts that can drop a type qualifier
+   from the pointer target type.  */
+
+int warn_cast_qual;
+
+/* Warn about functions which might be candidates for format attributes.  */
+
+int warn_missing_format_attribute;
+
+/* Nonzero means warn about sizeof(function) or addition/subtraction
+   of function pointers.  */
+
+int warn_pointer_arith;
+
+/* Nonzero means warn for any global function def
+   without separate previous prototype decl.  */
+
+int warn_missing_prototypes;
+
+/* Warn if adding () is suggested.  */
+
+int warn_parentheses;
+
+/* Warn if initializer is not completely bracketed.  */
+
+int warn_missing_braces;
+
+/* Warn about comparison of signed and unsigned values.
+   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified
+   (in which case -Wextra gets to decide).  */
+
+int warn_sign_compare = -1;
+
+/* Nonzero means warn about usage of long long when `-pedantic'.  */
+
+int warn_long_long = 1;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+   `char *'.  */
+
+int warn_write_strings;
+
+/* Nonzero means warn about multiple (redundant) decls for the same single
+   variable or function.  */
+
+int warn_redundant_decls;
+
+/* Warn about testing equality of floating point numbers.  */
+
+int warn_float_equal;
 
-int warn_multichar = 1;
+/* Warn about a subscript that has type char.  */
+
+int warn_char_subscripts;
+
+/* Warn if a type conversion is done that might have confusing results.  */
+
+int warn_conversion;
+
+/* Warn about #pragma directives that are not recognized.  */      
+
+int warn_unknown_pragmas; /* Tri state variable.  */  
+
+/* Warn about format/argument anomalies in calls to formatted I/O functions
+   (*printf, *scanf, strftime, strfmon, etc.).  */
+
+int warn_format;
+
+/* Warn about Y2K problems with strftime formats.  */
+
+int warn_format_y2k;
+
+/* Warn about excess arguments to formats.  */
+
+int warn_format_extra_args;
+
+/* Warn about zero-length formats.  */
+
+int warn_format_zero_length;
+
+/* Warn about non-literal format arguments.  */
+
+int warn_format_nonliteral;
+
+/* Warn about possible security problems with calls to format functions.  */
+
+int warn_format_security;
+
+
+/* C/ObjC language option variables.  */
+
+
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error.  */
+
+int mesg_implicit_function_declaration = -1;
+
+/* Nonzero means allow type mismatches in conditional expressions;
+   just make their values `void'.  */
+
+int flag_cond_mismatch;
+
+/* Nonzero means enable C89 Amendment 1 features.  */
+
+int flag_isoc94;
+
+/* Nonzero means use the ISO C99 dialect of C.  */
+
+int flag_isoc99;
+
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
+/* Nonzero means add default format_arg attributes for functions not
+   in ISO C.  */
+
+int flag_noniso_default_format_attributes = 1;
+
+/* Nonzero means warn when casting a function call to a type that does
+   not match the return type (e.g. (float)sqrt() or (anything*)malloc()
+   when there is no previous declaration of sqrt or malloc.  */
+
+int warn_bad_function_cast;
+
+/* Warn about traditional constructs whose meanings changed in ANSI C.  */
+
+int warn_traditional;
+
+/* Nonzero means warn for non-prototype function decls
+   or non-prototyped defs without previous prototype.  */
+
+int warn_strict_prototypes;
+
+/* Nonzero means warn for any global function def
+   without separate previous decl.  */
+
+int warn_missing_declarations;
+
+/* Nonzero means warn about declarations of objects not at
+   file-scope level and about *all* declarations of functions (whether
+   or static) not at file-scope level.  Note that we exclude
+   implicit function declarations.  To get warnings about those, use
+   -Wimplicit.  */
+
+int warn_nested_externs;
+
+/* Warn if main is suspicious.  */
+
+int warn_main;
 
 /* Nonzero means warn about possible violations of sequence point rules.  */
 
@@ -234,21 +427,264 @@ int warn_sequence_point;
 /* Nonzero means to warn about compile-time division by zero.  */
 int warn_div_by_zero = 1;
 
+/* Nonzero means warn about use of implicit int.  */
+
+int warn_implicit_int;
+
 /* Warn about NULL being passed to argument slots marked as requiring
    non-NULL.  */ 
       
 int warn_nonnull;
 
+
+/* ObjC language option variables.  */
+
+
+/* Open and close the file for outputting class declarations, if
+   requested (ObjC).  */
+
+int flag_gen_declaration;
+
+/* Generate code for GNU or NeXT runtime environment.  */
+
+#ifdef NEXT_OBJC_RUNTIME
+int flag_next_runtime = 1;
+#else
+int flag_next_runtime = 0;
+#endif
+
+/* Tells the compiler that this is a special run.  Do not perform any
+   compiling, instead we are to test some platform dependent features
+   and output a C header file with appropriate definitions.  */
+
+int print_struct_values;
+
+/* ???.  Undocumented.  */
+
+const char *constant_string_class_name;
+
+/* Warn if multiple methods are seen for the same selector, but with
+   different argument types.  Performs the check on the whole selector
+   table at the end of compilation.  */
+
+int warn_selector;
+
+/* Warn if a @selector() is found, and no method with that selector
+   has been previously declared.  The check is done on each
+   @selector() as soon as it is found - so it warns about forward
+   declarations.  */
+
+int warn_undeclared_selector;
+
+/* Warn if methods required by a protocol are not implemented in the 
+   class adopting it.  When turned off, methods inherited to that
+   class are also considered implemented.  */
+
+int warn_protocol = 1;
+
+
+/* C++ language option variables.  */
+
+
+/* Nonzero means don't recognize any extension keywords.  */
+
+int flag_no_gnu_keywords;
+
+/* Nonzero means do emit exported implementations of functions even if
+   they can be inlined.  */
+
+int flag_implement_inlines = 1;
+
+/* Nonzero means do emit exported implementations of templates, instead of
+   multiple static copies in each file that needs a definition.  */
+
+int flag_external_templates;
+
+/* Nonzero means that the decision to emit or not emit the implementation of a
+   template depends on where the template is instantiated, rather than where
+   it is defined.  */
+
+int flag_alt_external_templates;
+
+/* Nonzero means that implicit instantiations will be emitted if needed.  */
+
+int flag_implicit_templates = 1;
+
+/* Nonzero means that implicit instantiations of inline templates will be
+   emitted if needed, even if instantiations of non-inline templates
+   aren't.  */
+
+int flag_implicit_inline_templates = 1;
+
+/* Nonzero means generate separate instantiation control files and
+   juggle them at link time.  */
+
+int flag_use_repository;
+
+/* Nonzero if we want to issue diagnostics that the standard says are not
+   required.  */
+
+int flag_optional_diags = 1;
+
+/* Nonzero means we should attempt to elide constructors when possible.  */
+
+int flag_elide_constructors = 1;
+
+/* Nonzero means that member functions defined in class scope are
+   inline by default.  */
+
+int flag_default_inline = 1;
+
+/* Controls whether compiler generates 'type descriptor' that give
+   run-time type information.  */
+
+int flag_rtti = 1;
+
+/* Nonzero if we want to conserve space in the .o files.  We do this
+   by putting uninitialized data and runtime initialized data into
+   .common instead of .data at the expense of not flagging multiple
+   definitions.  */
+
+int flag_conserve_space;
+
+/* Nonzero if we want to obey access control semantics.  */
+
+int flag_access_control = 1;
+
+/* Nonzero if we want to check the return value of new and avoid calling
+   constructors if it is a null pointer.  */
+
+int flag_check_new;
+
+/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
+   initialization variables.
+   0: Old rules, set by -fno-for-scope.
+   2: New ISO rules, set by -ffor-scope.
+   1: Try to implement new ISO rules, but with backup compatibility
+   (and warnings).  This is the default, for now.  */
+
+int flag_new_for_scope = 1;
+
+/* Nonzero if we want to emit defined symbols with common-like linkage as
+   weak symbols where possible, in order to conform to C++ semantics.
+   Otherwise, emit them as local symbols.  */
+
+int flag_weak = 1;
+
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+   destructors for local statics and global objects.  */
+
+int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc.  */
+
+int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+   The value of this flag is ignored if -pedantic is specified.  */
+
+int flag_permissive;
+
+/* Nonzero means to implement standard semantics for exception
+   specifications, calling unexpected if an exception is thrown that
+   doesn't match the specification.  Zero means to treat them as
+   assertions and optimize accordingly, but not check them.  */
+
+int flag_enforce_eh_specs = 1;
+
+/*  The version of the C++ ABI in use.  The following values are
+    allowed:
+
+    0: The version of the ABI believed most conformant with the 
+       C++ ABI specification.  This ABI may change as bugs are
+       discovered and fixed.  Therefore, 0 will not necessarily
+       indicate the same ABI in different versions of G++.
+
+    1: The version of the ABI first used in G++ 3.2.
+
+    Additional positive integers will be assigned as new versions of
+    the ABI become the default version of the ABI.  */
+
+int flag_abi_version = 1;
+
+/* Nonzero means warn about things that will change when compiling
+   with an ABI-compliant compiler.  */
+
+int warn_abi = 0;
+
+/* Nonzero means warn about invalid uses of offsetof. */
+int warn_invalid_offsetof = 1;
+
+/* Nonzero means warn about implicit declarations.  */
+
+int warn_implicit = 1;
+
+/* Nonzero means warn when all ctors or dtors are private, and the class
+   has no friends.  */
+
+int warn_ctor_dtor_privacy = 0;
+
+/* Nonzero means warn in function declared in derived class has the
+   same name as a virtual in the base class, but fails to match the
+   type signature of any virtual function in the base class.  */
+
+int warn_overloaded_virtual;
+
+/* Nonzero means warn when declaring a class that has a non virtual
+   destructor, when it really ought to have a virtual one.  */
+
+int warn_nonvdtor;
+
+/* Nonzero means warn when the compiler will reorder code.  */
+
+int warn_reorder;
+
+/* Nonzero means warn when synthesis behavior differs from Cfront's.  */
+
+int warn_synth;
+
+/* Nonzero means warn when we convert a pointer to member function
+   into a pointer to (void or function).  */
+
+int warn_pmf2ptr = 1;
+
+/* Nonzero means warn about violation of some Effective C++ style rules.  */
+
+int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+   unsigned to signed over a conversion to an unsigned of the same size.  */
+
+int warn_sign_promo;
+
+/* Nonzero means warn when an old-style cast is used.  */
+
+int warn_old_style_cast;
+
+/* Nonzero means warn when non-templatized friend functions are
+   declared within a template */
+
+int warn_nontemplate_friend = 1;
+
+/* Nonzero means complain about deprecated features.  */
+
+int warn_deprecated = 1;
+
+/* Maximum template instantiation depth.  This limit is rather
+   arbitrary, but it exists to limit the time it takes to notice
+   infinite template instantiations.  */
+
+int max_tinst_depth = 500;
+
+
+
 /* The elements of `ridpointers' are identifier nodes for the reserved
    type names and storage classes.  It is indexed by a RID_... value.  */
 tree *ridpointers;
 
 tree (*make_fname_decl)                PARAMS ((tree, int));
 
-/* If non-NULL, the address of a language-specific function that
-   returns 1 for language-specific statement codes.  */
-int (*lang_statement_code_p)           PARAMS ((enum tree_code));
-
 /* If non-NULL, the address of a language-specific function that takes
    any action required right before expand_function_end is called.  */
 void (*lang_expand_function_end)       PARAMS ((void));
@@ -288,8 +724,7 @@ static int constant_fits_type_p             PARAMS ((tree, tree));
 typedef struct
 {
   int compstmt_count;
-  int line;
-  const char *file;
+  location_t locus;
   int needs_warning;
   tree if_stmt;
 } if_elt;
@@ -302,8 +737,6 @@ static int if_stack_space = 0;
 /* Stack pointer.  */
 static int if_stack_pointer = 0;
 
-static void cb_register_builtins PARAMS ((cpp_reader *));
-
 static tree handle_packed_attribute    PARAMS ((tree *, tree, tree, int,
                                                 bool *));
 static tree handle_nocommon_attribute  PARAMS ((tree *, tree, tree, int,
@@ -340,6 +773,8 @@ static tree handle_alias_attribute  PARAMS ((tree *, tree, tree, int,
                                                 bool *));
 static tree handle_visibility_attribute        PARAMS ((tree *, tree, tree, int,
                                                 bool *));
+static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int,
+                                                bool *));
 static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
                                                             tree, int,
                                                             bool *));
@@ -357,6 +792,8 @@ static tree handle_nonnull_attribute        PARAMS ((tree *, tree, tree, int,
                                                 bool *));
 static tree handle_nothrow_attribute   PARAMS ((tree *, tree, tree, int,
                                                 bool *));
+static tree handle_cleanup_attribute   PARAMS ((tree *, tree, tree, int,
+                                                bool *));
 static tree vector_size_helper PARAMS ((tree, tree));
 
 static void check_function_nonnull     PARAMS ((tree, tree));
@@ -365,10 +802,6 @@ static void check_nonnull_arg              PARAMS ((void *, tree,
 static bool nonnull_check_p            PARAMS ((tree, unsigned HOST_WIDE_INT));
 static bool get_nonnull_operand                PARAMS ((tree,
                                                 unsigned HOST_WIDE_INT *));
-void builtin_define_std PARAMS ((const char *));
-static void builtin_define_with_value PARAMS ((const char *, const char *,
-                                              int));
-static void builtin_define_type_max PARAMS ((const char *, tree, int));
 
 /* Table of machine-independent attributes common to all C-like languages.  */
 const struct attribute_spec c_common_attribute_table[] =
@@ -430,16 +863,20 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_vector_size_attribute },
   { "visibility",            1, 1, true,  false, false,
                              handle_visibility_attribute },
+  { "tls_model",             1, 1, true,  false, false,
+                             handle_tls_model_attribute },
   { "nonnull",                0, -1, false, true, true,
                              handle_nonnull_attribute },
   { "nothrow",                0, 0, true,  false, false,
                              handle_nothrow_attribute },
   { "may_alias",             0, 0, false, true, false, NULL },
+  { "cleanup",               1, 1, true, false, false,
+                             handle_cleanup_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
 /* Give the specifications for the format attributes, used by C and all
-   descendents.  */
+   descendants.  */
 
 const struct attribute_spec c_common_format_attribute_table[] =
 {
@@ -483,8 +920,7 @@ c_expand_start_cond (cond, compstmt_count, if_stmt)
 
   /* Record this if statement.  */
   if_stack[if_stack_pointer].compstmt_count = compstmt_count;
-  if_stack[if_stack_pointer].file = input_filename;
-  if_stack[if_stack_pointer].line = lineno;
+  if_stack[if_stack_pointer].locus = input_location;
   if_stack[if_stack_pointer].needs_warning = 0;
   if_stack[if_stack_pointer].if_stmt = if_stmt;
   if_stack_pointer++;
@@ -507,9 +943,8 @@ c_expand_end_cond ()
 {
   if_stack_pointer--;
   if (if_stack[if_stack_pointer].needs_warning)
-    warning_with_file_and_line (if_stack[if_stack_pointer].file,
-                               if_stack[if_stack_pointer].line,
-                               "suggest explicit braces to avoid ambiguous `else'");
+    warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
+             &if_stack[if_stack_pointer].locus);
   last_expr_type = NULL_TREE;
 }
 
@@ -627,13 +1062,18 @@ finish_fname_decls ()
   
   if (body)
     {
-      /* They were called into existence, so add to statement tree.  */
-      body = chainon (body,
-                     TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
-      body = build_stmt (COMPOUND_STMT, body);
-      
-      COMPOUND_STMT_NO_SCOPE (body) = 1;
-      TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)) = body;
+      /* They were called into existence, so add to statement tree.  Add
+        the DECL_STMTs inside the outermost scope.  */
+      tree *p = &DECL_SAVED_TREE (current_function_decl);
+      /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK.  */
+      while (TREE_CODE (*p) != COMPOUND_STMT)
+       p = &TREE_CHAIN (*p);
+      p = &COMPOUND_BODY (*p);
+      if (TREE_CODE (*p) == SCOPE_STMT)
+       p = &TREE_CHAIN (*p);
+
+      body = chainon (body, *p);
+      *p = body;
     }
   
   for (ix = 0; fname_vars[ix].decl; ix++)
@@ -656,7 +1096,7 @@ finish_fname_decls ()
   saved_function_name_decls = stack;
 }
 
-/* Return the text name of the current function, suitable prettified
+/* Return the text name of the current function, suitably prettified
    by PRETTY_P.  */
 
 const char *
@@ -714,6 +1154,13 @@ fname_decl (rid, id)
   if (!decl)
     {
       tree saved_last_tree = last_tree;
+      /* If a tree is built here, it would normally have the lineno of
+        the current statement.  Later this tree will be moved to the
+        beginning of the function and this line number will be wrong.
+        To avoid this problem set the lineno to 0 here; that prevents
+        it from appearing in the RTL.  */
+      int saved_lineno = input_line;
+      input_line = 0;
       
       decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
       if (last_tree != saved_last_tree)
@@ -729,10 +1176,11 @@ fname_decl (rid, id)
                                                 saved_function_name_decls);
        }
       *fname_vars[ix].decl = decl;
+      input_line = saved_lineno;
     }
   if (!ix && !current_function_decl)
     pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
-  
+
   return decl;
 }
 
@@ -1415,7 +1863,7 @@ verify_tree (x, pbefore_sp, pno_sp, writer)
     }
 }
 
-/* Try to warn for undefined behaviour in EXPR due to missing sequence
+/* Try to warn for undefined behavior in EXPR due to missing sequence
    points.  */
 
 static void
@@ -1614,10 +2062,14 @@ c_common_type_for_mode (mode, unsignedp)
       return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
     case V2SImode:
       return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+    case V2HImode:
+      return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
     case V4HImode:
       return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
     case V8QImode:
       return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+    case V1DImode:
+      return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
     case V16SFmode:
       return V16SF_type_node;
     case V4SFmode:
@@ -2367,12 +2819,13 @@ c_common_truthvalue_conversion (expr)
     case ABS_EXPR:
     case FLOAT_EXPR:
     case FFS_EXPR:
-      /* These don't change whether an object is non-zero or zero.  */
+    case POPCOUNT_EXPR:
+      /* These don't change whether an object is nonzero or zero.  */
       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
-      /* These don't change whether an object is zero or non-zero, but
+      /* These don't change whether an object is zero or nonzero, but
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),
@@ -2544,7 +2997,7 @@ c_common_get_alias_set (t)
   if (! TYPE_P (t))
     return -1;
 
-  /* The C standard guarantess that any object may be accessed via an
+  /* The C standard guarantees that any object may be accessed via an
      lvalue that has character type.  */
   if (t == char_type_node
       || t == signed_char_type_node
@@ -2657,7 +3110,7 @@ c_sizeof_or_alignof_type (type, op, complain)
      TYPE_IS_SIZETYPE means that certain things (like overflow) will
      never happen.  However, this node should really have type
      `size_t', which is just a typedef for an ordinary integer type.  */
-  value = fold (build1 (NOP_EXPR, c_size_type_node, value));
+  value = fold (build1 (NOP_EXPR, size_type_node, value));
   my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
   
   return value;
@@ -2708,7 +3161,7 @@ c_alignof_expr (expr)
   else
     return c_alignof (TREE_TYPE (expr));
 
-  return fold (build1 (NOP_EXPR, c_size_type_node, t));
+  return fold (build1 (NOP_EXPR, size_type_node, t));
 }
 \f
 /* Handle C and C++ default attributes.  */
@@ -2752,6 +3205,7 @@ c_common_nodes_and_builtins ()
 #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
 #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
 #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
 #define DEF_POINTER_TYPE(NAME, TYPE) NAME,
 #include "builtin-types.def"
 #undef DEF_PRIMITIVE_TYPE
@@ -2763,6 +3217,7 @@ c_common_nodes_and_builtins ()
 #undef DEF_FUNCTION_TYPE_VAR_0
 #undef DEF_FUNCTION_TYPE_VAR_1
 #undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
 #undef DEF_POINTER_TYPE
     BT_LAST
   };
@@ -2851,10 +3306,10 @@ c_common_nodes_and_builtins ()
   /* `unsigned long' is the standard type for sizeof.
      Note that stddef.h uses `unsigned long',
      and this must agree, even if long and int are the same size.  */
-  c_size_type_node =
+  size_type_node =
     TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
-  signed_size_type_node = c_common_signed_type (c_size_type_node);
-  set_sizetype (c_size_type_node);
+  signed_size_type_node = c_common_signed_type (size_type_node);
+  set_sizetype (size_type_node);
 
   build_common_tree_nodes_2 (flag_short_double);
 
@@ -2957,8 +3412,6 @@ c_common_nodes_and_builtins ()
     = build_pointer_type (build_qualified_type
                          (char_type_node, TYPE_QUAL_CONST));
 
-  (*targetm.init_builtins) ();
-
   /* This is special for C++ so functions can be overloaded.  */
   wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
   wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
@@ -3082,6 +3535,19 @@ c_common_nodes_and_builtins ()
                  tree_cons (NULL_TREE,                         \
                             builtin_types[(int) ARG2],         \
                             NULL_TREE)));
+
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3)                \
+   builtin_types[(int) ENUM]                                           \
+    = build_function_type                                              \
+      (builtin_types[(int) RETURN],                                    \
+       tree_cons (NULL_TREE,                                           \
+                 builtin_types[(int) ARG1],                            \
+                 tree_cons (NULL_TREE,                                 \
+                            builtin_types[(int) ARG2],                 \
+                            tree_cons (NULL_TREE,                      \
+                                       builtin_types[(int) ARG3],      \
+                                       NULL_TREE))));
+
 #define DEF_POINTER_TYPE(ENUM, TYPE)                   \
   builtin_types[(int) ENUM]                            \
     = build_pointer_type (builtin_types[(int) TYPE]);
@@ -3093,13 +3559,15 @@ c_common_nodes_and_builtins ()
 #undef DEF_FUNCTION_TYPE_4
 #undef DEF_FUNCTION_TYPE_VAR_0
 #undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
 #undef DEF_POINTER_TYPE
 
   if (!c_attrs_initialized)
     c_init_attributes ();
 
 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE,                  \
-                   BOTH_P, FALLBACK_P, NONANSI_P, ATTRS)               \
+                   BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT)     \
   if (NAME)                                                            \
     {                                                                  \
       tree decl;                                                       \
@@ -3126,10 +3594,14 @@ c_common_nodes_and_builtins ()
                                   built_in_attributes[(int) ATTRS]);   \
                                                                        \
       built_in_decls[(int) ENUM] = decl;                               \
+      if (IMPLICIT)                                                    \
+        implicit_built_in_decls[(int) ENUM] = decl;                    \
     }                                                                  
 #include "builtins.def"
 #undef DEF_BUILTIN
 
+  (*targetm.init_builtins) ();
+
   main_identifier_node = get_identifier ("main");
 }
 
@@ -3218,20 +3690,15 @@ builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
 {
   tree bdecl = NULL_TREE;
   tree decl = NULL_TREE;
+
   if (builtin_name != 0)
-    {
-      bdecl = builtin_function (builtin_name, builtin_type, function_code,
-                               class, library_name_p ? name : NULL,
-                               attrs);
-    }
+    bdecl = builtin_function (builtin_name, builtin_type, function_code,
+                             class, library_name_p ? name : NULL, attrs);
+
   if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
       && !(nonansi_p && flag_no_nonansi_builtin))
-    {
-      decl = builtin_function (name, type, function_code, class, NULL,
-                              attrs);
-      if (nonansi_p)
-       DECL_BUILT_IN_NONANSI (decl) = 1;
-    }
+    decl = builtin_function (name, type, function_code, class, NULL, attrs);
+
   return (bdecl != 0 ? bdecl : decl);
 }
 \f
@@ -3455,41 +3922,6 @@ expand_tree_builtin (function, params, coerced_params)
   return NULL_TREE;
 }
 
-/* Returns non-zero if CODE is the code for a statement.  */
-
-int
-statement_code_p (code)
-     enum tree_code code;
-{
-  switch (code)
-    {
-    case CLEANUP_STMT:
-    case EXPR_STMT:
-    case COMPOUND_STMT:
-    case DECL_STMT:
-    case IF_STMT:
-    case FOR_STMT:
-    case WHILE_STMT:
-    case DO_STMT:
-    case RETURN_STMT:
-    case BREAK_STMT:
-    case CONTINUE_STMT:
-    case SCOPE_STMT:
-    case SWITCH_STMT:
-    case GOTO_STMT:
-    case LABEL_STMT:
-    case ASM_STMT:
-    case FILE_STMT:
-    case CASE_LABEL:
-      return 1;
-
-    default:
-      if (lang_statement_code_p)
-       return (*lang_statement_code_p) (code);
-      return 0;
-    }
-}
-
 /* Walk the statement tree, rooted at *tp.  Apply FUNC to all the
    sub-trees of *TP in a pre-order traversal.  FUNC is called with the
    DATA and the address of each sub-tree.  If FUNC returns a non-NULL
@@ -3525,7 +3957,7 @@ walk_stmt_tree (tp, func, data)
     return NULL_TREE;
 
   /* Skip subtrees below non-statement nodes.  */
-  if (!statement_code_p (TREE_CODE (*tp)))
+  if (!STATEMENT_CODE_P (TREE_CODE (*tp)))
     return NULL_TREE;
 
   /* Call the function.  */
@@ -3539,7 +3971,7 @@ walk_stmt_tree (tp, func, data)
   /* FUNC may have modified the tree, recheck that we're looking at a
      statement node.  */
   code = TREE_CODE (*tp);
-  if (!statement_code_p (code))
+  if (!STATEMENT_CODE_P (code))
     return NULL_TREE;
 
   /* Visit the subtrees unless FUNC decided that there was nothing
@@ -3740,8 +4172,8 @@ c_add_case_label (cases, cond, low_value, high_value)
   return case_label;
 }
 
-/* Finish an expression taking the address of LABEL.  Returns an
-   expression for the address.  */
+/* Finish an expression taking the address of LABEL (an
+   IDENTIFIER_NODE).  Returns an expression for the address.  */
 
 tree 
 finish_label_address_expr (label)
@@ -3757,6 +4189,9 @@ finish_label_address_expr (label)
        pedwarn ("ISO C forbids taking the address of a label");
     }
 
+  if (label == error_mark_node)
+    return error_mark_node;
+
   label = lookup_label (label);
   if (label == NULL_TREE)
     result = null_pointer_node;
@@ -3789,6 +4224,7 @@ c_expand_expr (exp, target, tmode, modifier)
        tree rtl_expr;
        rtx result;
        bool preserve_result = false;
+       bool return_target = false;
 
        /* Since expand_expr_stmt calls free_temp_slots after every
           expression statement, we must call push_temp_slots here.
@@ -3816,8 +4252,20 @@ c_expand_expr (exp, target, tmode, modifier)
            if (TREE_CODE (last) == SCOPE_STMT
                && TREE_CODE (expr) == EXPR_STMT)
              {
-               TREE_ADDRESSABLE (expr) = 1;
-               preserve_result = true;
+               if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
+                   && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
+                 /* If the last expression is a variable whose RTL is the
+                    same as our target, just return the target; if it
+                    isn't valid expanding the decl would produce different
+                    RTL, and store_expr would try to do a copy.  */
+                 return_target = true;
+               else
+                 {
+                   /* Otherwise, note that we want the value from the last
+                      expression.  */
+                   TREE_ADDRESSABLE (expr) = 1;
+                   preserve_result = true;
+                 }
              }
          }
 
@@ -3825,7 +4273,9 @@ c_expand_expr (exp, target, tmode, modifier)
        expand_end_stmt_expr (rtl_expr);
 
        result = expand_expr (rtl_expr, target, tmode, modifier);
-       if (preserve_result && GET_CODE (result) == MEM)
+       if (return_target)
+         result = target;
+       else if (preserve_result && GET_CODE (result) == MEM)
          {
            if (GET_MODE (result) != BLKmode)
              result = copy_to_reg (result);
@@ -3896,7 +4346,7 @@ c_safe_from_p (target, exp)
     }
 
   /* For any statement, we must follow the statement-chain.  */
-  if (statement_code_p (TREE_CODE (exp)) && TREE_CHAIN (exp))
+  if (STATEMENT_CODE_P (TREE_CODE (exp)) && TREE_CHAIN (exp))
     return safe_from_p (target, TREE_CHAIN (exp), /*top_p=*/0);
 
   /* Assume everything else is safe.  */
@@ -4042,9 +4492,9 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked)
      int unlocked;
 {
   tree fn_putchar = unlocked ?
-    built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : built_in_decls[BUILT_IN_PUTCHAR];
+    implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR];
   tree fn_puts = unlocked ?
-    built_in_decls[BUILT_IN_PUTS_UNLOCKED] : built_in_decls[BUILT_IN_PUTS];
+    implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTS];
   tree fn, format_arg, stripped_string;
 
   /* If the return value is used, or the replacement _DECL isn't
@@ -4146,9 +4596,9 @@ c_expand_builtin_fprintf (arglist, target, tmode, modifier, ignore, unlocked)
      int unlocked;
 {
   tree fn_fputc = unlocked ?
-    built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : built_in_decls[BUILT_IN_FPUTC];
+    implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC];
   tree fn_fputs = unlocked ?
-    built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : built_in_decls[BUILT_IN_FPUTS];
+    implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTS];
   tree fn, format_arg, stripped_string;
 
   /* If the return value is used, or the replacement _DECL isn't
@@ -4258,325 +4708,15 @@ boolean_increment (code, arg)
   return val;
 }
 \f
-/* Common initialization before parsing options.  */
+/* Built-in macros for stddef.h, that require macros defined in this
+   file.  */
 void
-c_common_init_options (lang)
-     enum c_language_kind lang;
-{
-  c_language = lang;
-  parse_in = cpp_create_reader (lang == clk_c || lang == clk_objective_c
-                               ? CLK_GNUC89 : CLK_GNUCXX);
-  if (lang == clk_objective_c)
-    cpp_get_options (parse_in)->objc = 1;
-
-  /* Mark as "unspecified" (see c_common_post_options).  */
-  flag_bounds_check = -1;
-}
-
-/* Post-switch processing.  */
-bool
-c_common_post_options ()
-{
-  cpp_post_options (parse_in);
-
-  flag_inline_trees = 1;
-
-  /* Use tree inlining if possible.  Function instrumentation is only
-     done in the RTL level, so we disable tree inlining.  */
-  if (! flag_instrument_function_entry_exit)
-    {
-      if (!flag_no_inline)
-       flag_no_inline = 1;
-      if (flag_inline_functions)
-       {
-         flag_inline_trees = 2;
-         flag_inline_functions = 0;
-       }
-    }
-
-  /* If still "unspecified", make it match -fbounded-pointers.  */
-  if (flag_bounds_check == -1)
-    flag_bounds_check = flag_bounded_pointers;
-
-  /* Special format checking options don't work without -Wformat; warn if
-     they are used.  */
-  if (warn_format_y2k && !warn_format)
-    warning ("-Wformat-y2k ignored without -Wformat");
-  if (warn_format_extra_args && !warn_format)
-    warning ("-Wformat-extra-args ignored without -Wformat");
-  if (warn_format_zero_length && !warn_format)
-    warning ("-Wformat-zero-length ignored without -Wformat");
-  if (warn_format_nonliteral && !warn_format)
-    warning ("-Wformat-nonliteral ignored without -Wformat");
-  if (warn_format_security && !warn_format)
-    warning ("-Wformat-security ignored without -Wformat");
-  if (warn_missing_format_attribute && !warn_format)
-    warning ("-Wmissing-format-attribute ignored without -Wformat");
-
-  /* If an error has occurred in cpplib, note it so we fail
-     immediately.  */
-  errorcount += cpp_errors (parse_in);
-
-  return flag_preprocess_only;
-}
-
-/* Hook that registers front end and target-specific built-ins.  */
-static void
-cb_register_builtins (pfile)
-     cpp_reader *pfile;
+c_stddef_cpp_builtins()
 {
-  /* -undef turns off target-specific built-ins.  */
-  if (flag_undef)
-    return;
-
-  if (c_language == clk_cplusplus)
-    {
-      if (SUPPORTS_ONE_ONLY)
-       cpp_define (pfile, "__GXX_WEAK__=1");
-      else
-       cpp_define (pfile, "__GXX_WEAK__=0");
-    }
-
-  /* libgcc needs to know this.  */
-  if (USING_SJLJ_EXCEPTIONS)
-    cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
-
-  /* stddef.h needs to know these.  */
   builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);
   builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
   builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
   builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
-
-  /* limits.h needs to know these.  */
-  builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0);
-  builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0);
-  builtin_define_type_max ("__INT_MAX__", integer_type_node, 0);
-  builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1);
-  builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2);
-
-  {
-    char buf[8];
-    sprintf (buf, "%d", (int) TYPE_PRECISION (signed_char_type_node));
-    builtin_define_with_value ("__CHAR_BIT__", buf, 0);
-  }
-
-  /* For use in assembly language.  */
-  builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
-  builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
-
-  /* Misc.  */
-  builtin_define_with_value ("__VERSION__", version_string, 1);
-
-  /* Other target-independent built-ins determined by command-line
-     options.  */
-  if (optimize_size)
-    cpp_define (pfile, "__OPTIMIZE_SIZE__");
-  if (optimize)
-    cpp_define (pfile, "__OPTIMIZE__");
-
-  if (flag_hosted)
-    cpp_define (pfile, "__STDC_HOSTED__=1");
-  else
-    cpp_define (pfile, "__STDC_HOSTED__=0");
-
-  if (fast_math_flags_set_p ())
-    cpp_define (pfile, "__FAST_MATH__");
-  if (flag_no_inline)
-    cpp_define (pfile, "__NO_INLINE__");
-  if (flag_signaling_nans)
-    cpp_define (pfile, "__SUPPORT_SNAN__");
-  if (flag_finite_math_only)
-    cpp_define (pfile, "__FINITE_MATH_ONLY__");
-
-  if (flag_iso)
-    cpp_define (pfile, "__STRICT_ANSI__");
-
-  if (!flag_signed_char)
-    cpp_define (pfile, "__CHAR_UNSIGNED__");
-
-  /* A straightforward target hook doesn't work, because of problems
-     linking that hook's body when part of non-C front ends.  */
-# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
-# define builtin_define(TXT) cpp_define (pfile, TXT)
-# define builtin_assert(TXT) cpp_assert (pfile, TXT)
-  TARGET_CPU_CPP_BUILTINS ();
-  TARGET_OS_CPP_BUILTINS ();
-}
-
-/* Pass an object-like macro.  If it doesn't lie in the user's
-   namespace, defines it unconditionally.  Otherwise define a version
-   with two leading underscores, and another version with two leading
-   and trailing underscores, and define the original only if an ISO
-   standard was not nominated.
-
-   e.g. passing "unix" defines "__unix", "__unix__" and possibly
-   "unix".  Passing "_mips" defines "__mips", "__mips__" and possibly
-   "_mips".  */
-void
-builtin_define_std (macro)
-     const char *macro;
-{
-  size_t len = strlen (macro);
-  char *buff = alloca (len + 5);
-  char *p = buff + 2;
-  char *q = p + len;
-
-  /* prepend __ (or maybe just _) if in user's namespace.  */
-  memcpy (p, macro, len + 1);
-  if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))
-    {
-      if (*p != '_')
-       *--p = '_';
-      if (p[1] != '_')
-       *--p = '_';
-    }
-  cpp_define (parse_in, p);
-
-  /* If it was in user's namespace...  */
-  if (p != buff + 2)
-    {
-      /* Define the macro with leading and following __.  */
-      if (q[-1] != '_')
-       *q++ = '_';
-      if (q[-2] != '_')
-       *q++ = '_';
-      *q = '\0';
-      cpp_define (parse_in, p);
-
-      /* Finally, define the original macro if permitted.  */
-      if (!flag_iso)
-       cpp_define (parse_in, macro);
-    }
-}
-
-/* Pass an object-like macro and a value to define it to.  The third
-   parameter says whether or not to turn the value into a string
-   constant.  */
-static void
-builtin_define_with_value (macro, expansion, is_str)
-     const char *macro;
-     const char *expansion;
-     int is_str;
-{
-  char *buf;
-  size_t mlen = strlen (macro);
-  size_t elen = strlen (expansion);
-  size_t extra = 2;  /* space for an = and a NUL */
-
-  if (is_str)
-    extra += 2;  /* space for two quote marks */
-
-  buf = alloca (mlen + elen + extra);
-  if (is_str)
-    sprintf (buf, "%s=\"%s\"", macro, expansion);
-  else
-    sprintf (buf, "%s=%s", macro, expansion);
-
-  cpp_define (parse_in, buf);
-}
-
-/* Define MAX for TYPE based on the precision of the type, which is assumed
-   to be signed.  IS_LONG is 1 for type "long" and 2 for "long long".  */
-
-static void
-builtin_define_type_max (macro, type, is_long)
-     const char *macro;
-     tree type;
-     int is_long;
-{
-  const char *value;
-  char *buf;
-  size_t mlen, vlen, extra;
-
-  /* Pre-rendering the values mean we don't have to futz with printing a
-     multi-word decimal value.  There are also a very limited number of
-     precisions that we support, so it's really a waste of time.  */
-  switch (TYPE_PRECISION (type))
-    {
-    case 8:
-      value = "127";
-      break;
-    case 16:
-      value = "32767";
-      break;
-    case 32:
-      value = "2147483647";
-      break;
-    case 64:
-      value = "9223372036854775807";
-      break;
-    case 128:
-      value = "170141183460469231731687303715884105727";
-      break;
-    default:
-      abort ();
-    }
-
-  mlen = strlen (macro);
-  vlen = strlen (value);
-  extra = 2 + is_long;
-  buf = alloca (mlen + vlen + extra);
-
-  sprintf (buf, "%s=%s%s", macro, value,
-          (is_long == 1 ? "L" : is_long == 2 ? "LL" : ""));
-
-  cpp_define (parse_in, buf);
-}
-
-/* Front end initialization common to C, ObjC and C++.  */
-const char *
-c_common_init (filename)
-     const char *filename;
-{
-  cpp_options *options = cpp_get_options (parse_in);
-
-  /* Set up preprocessor arithmetic.  Must be done after call to
-     c_common_nodes_and_builtins for wchar_type_node to be good.  */
-  options->precision = TYPE_PRECISION (intmax_type_node);
-  options->char_precision = TYPE_PRECISION (char_type_node);
-  options->int_precision = TYPE_PRECISION (integer_type_node);
-  options->wchar_precision = TYPE_PRECISION (wchar_type_node);
-  options->unsigned_wchar = TREE_UNSIGNED (wchar_type_node);
-  options->unsigned_char = !flag_signed_char;
-  options->warn_multichar = warn_multichar;
-  options->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
-
-  /* We want -Wno-long-long to override -pedantic -std=non-c99
-     whatever the ordering.  */
-  options->warn_long_long = warn_long_long && !flag_isoc99 && pedantic;
-
-  /* Register preprocessor built-ins before calls to
-     cpp_main_file.  */
-  cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins;
-
-  /* NULL is passed up to toplev.c and we exit quickly.  */
-  if (flag_preprocess_only)
-    {
-      cpp_preprocess_file (parse_in);
-      return NULL;
-    }
-
-  /* Do this before initializing pragmas, as then cpplib's hash table
-     has been set up.  */
-  filename = init_c_lex (filename);
-
-  init_pragma ();
-
-  if (!c_attrs_initialized)
-    c_init_attributes ();
-
-  return filename;
-}
-
-/* Common finish hook for the C, ObjC and C++ front ends.  */
-void
-c_common_finish ()
-{
-  cpp_finish (parse_in);
-
-  /* For performance, avoid tearing down cpplib's internal structures.
-     Call cpp_errors () instead of cpp_destroy ().  */
-  errorcount += cpp_errors (parse_in);
 }
 
 static void
@@ -4631,17 +4771,22 @@ c_common_insert_default_attributes (decl)
 #undef DEF_FN_ATTR
 }
 
-/* Output a -Wshadow warning MSGID about NAME, an IDENTIFIER_NODE, and
-   additionally give the location of the previous declaration DECL.  */
+/* Output a -Wshadow warning MSGCODE about NAME, and give the location
+   of the previous declaration DECL.  */
 void
-shadow_warning (msgid, name, decl)
-     const char *msgid;
-     tree name, decl;
+shadow_warning (msgcode, name, decl)
+     enum sw_kind msgcode;
+     const char *name;
+     tree decl;
 {
-  warning ("declaration of `%s' shadows %s", IDENTIFIER_POINTER (name), msgid);
-  warning_with_file_and_line (DECL_SOURCE_FILE (decl),
-                             DECL_SOURCE_LINE (decl),
-                             "shadowed declaration is here");
+  static const char *const msgs[] = {
+    /* SW_PARAM  */ N_("declaration of \"%s\" shadows a parameter"),
+    /* SW_LOCAL  */ N_("declaration of \"%s\" shadows a previous local"),
+    /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
+  };
+
+  warning (msgs[msgcode], name);
+  warning ("%Hshadowed declaration is here", &DECL_SOURCE_LOCATION (decl));
 }
 
 /* Attribute handlers common to C front ends.  */
@@ -4811,16 +4956,19 @@ handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
    struct attribute_spec.handler.  */
 
 static tree
-handle_used_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
+handle_used_attribute (pnode, name, args, flags, no_add_attrs)
+     tree *pnode;
      tree name;
      tree args ATTRIBUTE_UNUSED;
      int flags ATTRIBUTE_UNUSED;
      bool *no_add_attrs;
 {
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
-      = TREE_USED (*node) = 1;
+  tree node = *pnode;
+
+  if (TREE_CODE (node) == FUNCTION_DECL
+      || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (node))
+      = TREE_USED (node) = 1;
   else
     {
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
@@ -5029,6 +5177,7 @@ handle_mode_attribute (node, name, args, flags, no_add_attrs)
       int len = strlen (p);
       enum machine_mode mode = VOIDmode;
       tree typefm;
+      tree ptr_type;
 
       if (len > 4 && p[0] == '_' && p[1] == '_'
          && p[len - 1] == '_' && p[len - 2] == '_')
@@ -5058,6 +5207,10 @@ handle_mode_attribute (node, name, args, flags, no_add_attrs)
       else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
                     (mode, TREE_UNSIGNED (type))))
        error ("no data type for mode `%s'", p);
+      else if ((TREE_CODE (type) == POINTER_TYPE
+               || TREE_CODE (type) == REFERENCE_TYPE)
+              && !(*targetm.valid_pointer_mode) (mode))
+       error ("invalid pointer mode `%s'", p);
       else
        {
          /* If this is a vector, make sure we either have hardware
@@ -5070,6 +5223,19 @@ handle_mode_attribute (node, name, args, flags, no_add_attrs)
              return NULL_TREE;
            }
 
+         if (TREE_CODE (type) == POINTER_TYPE)
+           {
+             ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
+                                                     mode);
+             *node = ptr_type;
+           }
+         else if (TREE_CODE (type) == REFERENCE_TYPE)
+           {
+             ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
+                                                       mode);
+             *node = ptr_type;
+           }
+         else
          *node = typefm;
          /* No need to layout the type here.  The caller should do this.  */
        }
@@ -5316,9 +5482,53 @@ handle_visibility_attribute (node, name, args, flags, no_add_attrs)
        }
       if (strcmp (TREE_STRING_POINTER (id), "hidden")
          && strcmp (TREE_STRING_POINTER (id), "protected")
-         && strcmp (TREE_STRING_POINTER (id), "internal"))
+         && strcmp (TREE_STRING_POINTER (id), "internal")
+         && strcmp (TREE_STRING_POINTER (id), "default"))
        {
-         error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
+         error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+         *no_add_attrs = true;
+         return NULL_TREE;
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle an "tls_model" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_tls_model_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  tree decl = *node;
+
+  if (! DECL_THREAD_LOCAL (decl))
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else
+    {
+      tree id;
+
+      id = TREE_VALUE (args);
+      if (TREE_CODE (id) != STRING_CST)
+       {
+         error ("tls_model arg not a string");
+         *no_add_attrs = true;
+         return NULL_TREE;
+       }
+      if (strcmp (TREE_STRING_POINTER (id), "local-exec")
+         && strcmp (TREE_STRING_POINTER (id), "initial-exec")
+         && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
+         && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+       {
+         error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
          *no_add_attrs = true;
          return NULL_TREE;
        }
@@ -5505,7 +5715,7 @@ handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
    The normal mechanism to prevent duplicates is to use type_hash_canon, but
    since we want to distinguish types that are essentially identical (except
    for their debug representation), we use a local list here.  */
-static tree vector_type_node_list = 0;
+static GTY(()) tree vector_type_node_list = 0;
 
 /* Handle a "vector_size" attribute; arguments as in
    struct attribute_spec.handler.  */
@@ -5704,7 +5914,7 @@ handle_nonnull_attribute (node, name, args, flags, no_add_attrs)
   unsigned HOST_WIDE_INT attr_arg_num;
 
   /* If no arguments are specified, all pointer arguments should be
-     non-null.  Veryify a full prototype is given so that the arguments
+     non-null.  Verify a full prototype is given so that the arguments
      will have the correct types when we actually check them later.  */
   if (! args)
     {
@@ -5887,6 +6097,55 @@ handle_nothrow_attribute (node, name, args, flags, no_add_attrs)
 
   return NULL_TREE;
 }
+
+/* Handle a "cleanup" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_cleanup_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  tree decl = *node;
+  tree cleanup_id, cleanup_decl;
+
+  /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
+     for global destructors in C++.  This requires infrastructure that
+     we don't have generically at the moment.  It's also not a feature
+     we'd be missing too much, since we do have attribute constructor.  */
+  if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* Verify that the argument is a function in scope.  */
+  /* ??? We could support pointers to functions here as well, if
+     that was considered desirable.  */
+  cleanup_id = TREE_VALUE (args);
+  if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
+    {
+      error ("cleanup arg not an identifier");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+  cleanup_decl = lookup_name (cleanup_id);
+  if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
+    {
+      error ("cleanup arg not a function");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* That the function has proper type is checked with the 
+     eventual call to build_function_call.  */
+
+  return NULL_TREE;
+}
 \f
 /* Check for valid arguments being passed to a function.  */
 void