OSDN Git Service

* ChangeLog: Follow spelling conventions.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 03966a8..62458d6 100644 (file)
@@ -22,6 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "config.h"
 #include "system.h"
 #include "tree.h"
+#include "real.h"
 #include "flags.h"
 #include "toplev.h"
 #include "output.h"
@@ -30,18 +31,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "expr.h"
 #include "c-common.h"
-#include "tree-inline.h"
 #include "diagnostic.h"
 #include "tm_p.h"
 #include "obstack.h"
-#include "c-lex.h"
 #include "cpplib.h"
 #include "target.h"
 #include "langhooks.h"
-cpp_reader *parse_in;          /* Declared in c-lex.h.  */
+#include "except.h"            /* For USING_SJLJ_EXCEPTIONS.  */
+#include "tree-inline.h"
 
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE TYPE_PRECISION (wchar_type_node)
+cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
 /* We let tm.h override the types used here, to handle trivial differences
    such as the choice of unsigned int or long unsigned int for size_t.
@@ -57,6 +56,10 @@ cpp_reader *parse_in;                /* Declared in c-lex.h.  */
 #define WCHAR_TYPE "int"
 #endif
 
+/* WCHAR_TYPE gets overridden by -fshort-wchar.  */
+#define MODIFIED_WCHAR_TYPE \
+       (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
+
 #ifndef PTRDIFF_TYPE
 #define PTRDIFF_TYPE "long int"
 #endif
@@ -81,6 +84,10 @@ cpp_reader *parse_in;                /* Declared in c-lex.h.  */
                        : "long long unsigned int"))
 #endif
 
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+
 /* The variant of the C language being processed.  */
 
 enum c_language_kind c_language;
@@ -181,9 +188,22 @@ enum c_language_kind c_language;
 
 tree c_global_trees[CTI_MAX];
 
+/* Switches common to the C front ends.  */
+
 /* Nonzero if prepreprocessing only.  */
 int flag_preprocess_only;
 
+/* 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;
+
 /* Nonzero means don't recognize the non-ANSI builtin functions.  */
 
 int flag_no_builtin;
@@ -201,6 +221,180 @@ int flag_short_double;
 
 int flag_short_wchar;
 
+/* Nonzero means allow Microsoft extensions without warnings or errors.  */
+int flag_ms_extensions;
+
+/* 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 `$' can be in an identifier.  */
+
+#ifndef DOLLARS_IN_IDENTIFIERS
+#define DOLLARS_IN_IDENTIFIERS 1
+#endif
+int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+
+/* 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.  */
+
+int warn_sign_compare;
+
+/* 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;
+
+/* 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.  */
 
 int warn_sequence_point;
@@ -208,6 +402,239 @@ 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;
+
+/* Nonzero means warn about things that will change when compiling
+   with an ABI-compliant compiler.  */
+
+int warn_abi = 0;
+
+/* 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 = 1;
+
+/* 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;
@@ -320,8 +747,32 @@ static tree handle_deprecated_attribute    PARAMS ((tree *, tree, tree, int,
                                                 bool *));
 static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
                                                  bool *));
+static tree handle_nonnull_attribute   PARAMS ((tree *, tree, tree, int,
+                                                bool *));
+static tree handle_nothrow_attribute   PARAMS ((tree *, tree, tree, int,
+                                                bool *));
 static tree vector_size_helper PARAMS ((tree, tree));
 
+static void check_function_nonnull     PARAMS ((tree, tree));
+static void check_nonnull_arg          PARAMS ((void *, tree,
+                                                unsigned HOST_WIDE_INT));
+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_with_int_value PARAMS ((const char *,
+                                                  HOST_WIDE_INT));
+static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree,
+                                                     int, const char *,
+                                                     const char *));
+static void builtin_define_type_max PARAMS ((const char *, tree, int));
+static void cpp_define_data_format PARAMS ((cpp_reader *));
+static void builtin_define_type_precision PARAMS ((const char *, tree));
+static void builtin_define_float_constants PARAMS ((const char *,
+                                                   const char *, tree));
+
 /* Table of machine-independent attributes common to all C-like languages.  */
 const struct attribute_spec c_common_attribute_table[] =
 {
@@ -382,6 +833,11 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_vector_size_attribute },
   { "visibility",            1, 1, true,  false, false,
                              handle_visibility_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 },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -661,6 +1117,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 = lineno;
+      lineno = 0;
       
       decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
       if (last_tree != saved_last_tree)
@@ -676,6 +1139,7 @@ fname_decl (rid, id)
                                                 saved_function_name_decls);
        }
       *fname_vars[ix].decl = decl;
+      lineno = saved_lineno;
     }
   if (!ix && !current_function_decl)
     pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
@@ -683,105 +1147,17 @@ fname_decl (rid, id)
   return decl;
 }
 
-/* Given a chain of STRING_CST nodes,
-   concatenate them into one STRING_CST
-   and give it a suitable array-of-chars data type.  */
+/* Given a STRING_CST, give it a suitable array-of-chars data type.  */
 
 tree
-combine_strings (strings)
-     tree strings;
+fix_string_type (value)
+      tree value;
 {
-  tree value, t;
-  int length = 1;
-  int wide_length = 0;
-  int wide_flag = 0;
-  int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
-  int nchars;
+  const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+  const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
   const int nchars_max = flag_isoc99 ? 4095 : 509;
-
-  if (TREE_CHAIN (strings))
-    {
-      /* More than one in the chain, so concatenate.  */
-      char *p, *q;
-
-      /* Don't include the \0 at the end of each substring,
-        except for the last one.
-        Count wide strings and ordinary strings separately.  */
-      for (t = strings; t; t = TREE_CHAIN (t))
-       {
-         if (TREE_TYPE (t) == wchar_array_type_node)
-           {
-             wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
-             wide_flag = 1;
-           }
-         else
-           {
-             length += (TREE_STRING_LENGTH (t) - 1);
-             if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
-               warning ("concatenation of string literals with __FUNCTION__ is deprecated.  This feature will be removed in future"); 
-           }
-       }
-
-      /* If anything is wide, the non-wides will be converted,
-        which makes them take more space.  */
-      if (wide_flag)
-       length = length * wchar_bytes + wide_length;
-
-      p = alloca (length);
-
-      /* Copy the individual strings into the new combined string.
-        If the combined string is wide, convert the chars to ints
-        for any individual strings that are not wide.  */
-
-      q = p;
-      for (t = strings; t; t = TREE_CHAIN (t))
-       {
-         int len = (TREE_STRING_LENGTH (t)
-                    - ((TREE_TYPE (t) == wchar_array_type_node)
-                       ? wchar_bytes : 1));
-         if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
-           {
-             memcpy (q, TREE_STRING_POINTER (t), len);
-             q += len;
-           }
-         else
-           {
-             int i, j;
-             for (i = 0; i < len; i++)
-               {
-                 if (BYTES_BIG_ENDIAN)
-                   {
-                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
-                       *q++ = 0;
-                     *q++ = TREE_STRING_POINTER (t)[i];
-                   }
-                 else
-                   {
-                     *q++ = TREE_STRING_POINTER (t)[i];
-                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
-                       *q++ = 0;
-                   }
-               }
-           }
-       }
-      if (wide_flag)
-       {
-         int i;
-         for (i = 0; i < wchar_bytes; i++)
-           *q++ = 0;
-       }
-      else
-       *q = 0;
-
-      value = build_string (length, p);
-    }
-  else
-    {
-      value = strings;
-      length = TREE_STRING_LENGTH (value);
-      if (TREE_TYPE (value) == wchar_array_type_node)
-       wide_flag = 1;
-    }
+  int length = TREE_STRING_LENGTH (value);
+  int nchars;
 
   /* Compute the number of elements, for the array type.  */
   nchars = wide_flag ? length / wchar_bytes : length;
@@ -813,6 +1189,112 @@ combine_strings (strings)
   TREE_STATIC (value) = 1;
   return value;
 }
+
+/* Given a VARRAY of STRING_CST nodes, concatenate them into one
+   STRING_CST.  */
+
+tree
+combine_strings (strings)
+     varray_type strings;
+{
+  const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+  const int nstrings = VARRAY_ACTIVE_SIZE (strings);
+  tree value, t;
+  int length = 1;
+  int wide_length = 0;
+  int wide_flag = 0;
+  int i;
+  char *p, *q;
+
+  /* Don't include the \0 at the end of each substring.  Count wide
+     strings and ordinary strings separately.  */
+  for (i = 0; i < nstrings; ++i)
+    {
+      t = VARRAY_TREE (strings, i);
+
+      if (TREE_TYPE (t) == wchar_array_type_node)
+       {
+         wide_length += TREE_STRING_LENGTH (t) - wchar_bytes;
+         wide_flag = 1;
+       }
+      else
+       {
+         length += (TREE_STRING_LENGTH (t) - 1);
+         if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
+           warning ("concatenation of string literals with __FUNCTION__ is deprecated"); 
+       }
+    }
+
+  /* If anything is wide, the non-wides will be converted,
+     which makes them take more space.  */
+  if (wide_flag)
+    length = length * wchar_bytes + wide_length;
+
+  p = xmalloc (length);
+
+  /* Copy the individual strings into the new combined string.
+     If the combined string is wide, convert the chars to ints
+     for any individual strings that are not wide.  */
+
+  q = p;
+  for (i = 0; i < nstrings; ++i)
+    {
+      int len, this_wide;
+
+      t = VARRAY_TREE (strings, i);
+      this_wide = TREE_TYPE (t) == wchar_array_type_node;
+      len = TREE_STRING_LENGTH (t) - (this_wide ? wchar_bytes : 1);
+      if (this_wide == wide_flag)
+       {
+         memcpy (q, TREE_STRING_POINTER (t), len);
+         q += len;
+       }
+      else
+       {
+         const int nzeros = (TYPE_PRECISION (wchar_type_node)
+                             / BITS_PER_UNIT) - 1;
+         int j, k;
+
+         if (BYTES_BIG_ENDIAN)
+           {
+             for (k = 0; k < len; k++)
+               {
+                 for (j = 0; j < nzeros; j++)
+                   *q++ = 0;
+                 *q++ = TREE_STRING_POINTER (t)[k];
+               }
+           }
+         else
+           {
+             for (k = 0; k < len; k++)
+               {
+                 *q++ = TREE_STRING_POINTER (t)[k];
+                 for (j = 0; j < nzeros; j++)
+                   *q++ = 0;
+               }
+           }
+       }
+    }
+
+  /* Nul terminate the string.  */
+  if (wide_flag)
+    {
+      for (i = 0; i < wchar_bytes; i++)
+       *q++ = 0;
+    }
+  else
+    *q = 0;
+
+  value = build_string (length, p);
+  free (p);
+
+  if (wide_flag)
+    TREE_TYPE (value) = wchar_array_type_node;
+  else
+    TREE_TYPE (value) = char_array_type_node;
+
+  return value;
+}
 \f
 static int is_valid_printf_arglist PARAMS ((tree));
 static rtx c_expand_builtin PARAMS ((tree, rtx, enum machine_mode, enum expand_modifier));
@@ -1344,7 +1826,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
@@ -1531,34 +2013,35 @@ c_common_type_for_mode (mode, unsignedp)
   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
     return build_pointer_type (integer_type_node);
 
-#ifdef VECTOR_MODE_SUPPORTED_P
-  if (VECTOR_MODE_SUPPORTED_P (mode))
-    {
-      switch (mode)
-       {
-       case V16QImode:
-         return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
-       case V8HImode:
-         return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
-       case V4SImode:
-         return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
-       case V2SImode:
-         return unsignedp ? unsigned_V2SI_type_node : V2SI_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 V16SFmode:
-         return V16SF_type_node;
-       case V4SFmode:
-         return V4SF_type_node;
-       case V2SFmode:
-         return V2SF_type_node;
-       default:
-         break;
-       }
+  switch (mode)
+    {
+    case V16QImode:
+      return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
+    case V8HImode:
+      return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
+    case V4SImode:
+      return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
+    case V2DImode:
+      return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
+    case V2SImode:
+      return unsignedp ? unsigned_V2SI_type_node : V2SI_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:
+      return V4SF_type_node;
+    case V2SFmode:
+      return V2SF_type_node;
+    case V2DFmode:
+      return V2DF_type_node;
+    default:
+      break;
     }
-#endif
 
   return 0;
 }
@@ -1999,19 +2482,8 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
          type = c_common_unsigned_type (type);
        }
 
-      if (!max_gt && !unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
+      if (TREE_CODE (primop0) != INTEGER_CST)
        {
-         /* This is the case of (char)x >?< 0x80, which people used to use
-            expecting old C compilers to change the 0x80 into -0x80.  */
-         if (val == boolean_false_node)
-           warning ("comparison is always false due to limited range of data type");
-         if (val == boolean_true_node)
-           warning ("comparison is always true due to limited range of data type");
-       }
-
-      if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
-       {
-         /* This is the case of (unsigned char)x >?< -1 or < 0.  */
          if (val == boolean_false_node)
            warning ("comparison is always false due to limited range of data type");
          if (val == boolean_true_node)
@@ -2308,12 +2780,12 @@ 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.  */
+      /* 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),
@@ -2397,7 +2869,7 @@ c_common_truthvalue_conversion (expr)
 \f
 static tree builtin_function_2 PARAMS ((const char *, const char *, tree, tree,
                                        int, enum built_in_class, int, int,
-                                       int));
+                                       tree));
 
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
@@ -2468,10 +2940,6 @@ c_common_get_alias_set (t)
 {
   tree u;
   
-  /* We know nothing about vector types */
-  if (TREE_CODE (t) == VECTOR_TYPE)
-    return 0;          
-  
   /* Permit type-punning when accessing a union, provided the access
      is directly through the union.  For example, this code does not
      permit taking the address of a union member and then storing
@@ -2485,17 +2953,21 @@ c_common_get_alias_set (t)
        && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
       return 0;
 
-  /* If this is a char *, the ANSI C standard says it can alias
-     anything.  Note that all references need do this.  */
-  if (TREE_CODE_CLASS (TREE_CODE (t)) == 'r'
-      && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
-      && TYPE_PRECISION (TREE_TYPE (t)) == TYPE_PRECISION (char_type_node))
-    return 0;
-
   /* That's all the expressions we handle specially.  */
   if (! TYPE_P (t))
     return -1;
 
+  /* The C standard guarantess that any object may be accessed via an
+     lvalue that has character type.  */
+  if (t == char_type_node
+      || t == signed_char_type_node
+      || t == unsigned_char_type_node)
+    return 0;
+
+  /* If it has the may_alias attribute, it can alias anything.  */
+  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))
+    return 0;
+
   /* The C standard specifically allows aliasing between signed and
      unsigned variants of the same type.  We treat the signed
      variant as canonical.  */
@@ -2542,36 +3014,66 @@ c_common_get_alias_set (t)
   return -1;
 }
 \f
-/* Implement the __alignof keyword: Return the minimum required
-   alignment of TYPE, measured in bytes.  */
-
+/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
+   second parameter indicates which OPERATOR is being applied.  The COMPLAIN
+   flag controls whether we should diagnose possibly ill-formed
+   constructs or not.  */
 tree
-c_alignof (type)
+c_sizeof_or_alignof_type (type, op, complain)
      tree type;
+     enum tree_code op;
+     int complain;
 {
-  enum tree_code code = TREE_CODE (type);
-  tree t;
-
-  /* In C++, sizeof applies to the referent.  Handle alignof the same way.  */
-  if (code == REFERENCE_TYPE)
+  const char *op_name;
+  tree value = NULL;
+  enum tree_code type_code = TREE_CODE (type);
+  
+  my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
+  op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
+  
+  if (type_code == FUNCTION_TYPE)
     {
-      type = TREE_TYPE (type);
-      code = TREE_CODE (type);
+      if (op == SIZEOF_EXPR)
+       {
+         if (complain && (pedantic || warn_pointer_arith))
+           pedwarn ("invalid application of `sizeof' to a function type");
+         value = size_one_node;
+       }
+      else
+       value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+    }
+  else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
+    {
+      if (type_code == VOID_TYPE 
+         && complain && (pedantic || warn_pointer_arith))
+       pedwarn ("invalid application of `%s' to a void type", op_name);
+      value = size_one_node;
     }
-
-  if (code == FUNCTION_TYPE)
-    t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-  else if (code == VOID_TYPE || code == ERROR_MARK)
-    t = size_one_node;
   else if (!COMPLETE_TYPE_P (type))
     {
-      error ("__alignof__ applied to an incomplete type");
-      t = size_zero_node;
+      if (complain)
+       error ("invalid application of `%s' to an incomplete type", op_name);
+      value = size_zero_node;
     }
   else
-    t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+    {
+      if (op == SIZEOF_EXPR)
+       /* Convert in case a char is more than one unit.  */
+       value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                           size_int (TYPE_PRECISION (char_type_node)
+                                     / BITS_PER_UNIT));
+      else
+       value = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+    }
 
-  return fold (build1 (NOP_EXPR, c_size_type_node, t));
+  /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
+     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));
+  my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
+  
+  return value;
 }
 
 /* Implement the __alignof keyword: Return the minimum required
@@ -2622,6 +3124,30 @@ c_alignof_expr (expr)
   return fold (build1 (NOP_EXPR, c_size_type_node, t));
 }
 \f
+/* Handle C and C++ default attributes.  */
+
+enum built_in_attribute
+{
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum.  */
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+  ATTR_LAST
+};
+
+static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
+
+static bool c_attrs_initialized = false;
+
+static void c_init_attributes PARAMS ((void));
+
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
 
@@ -2847,9 +3373,7 @@ c_common_nodes_and_builtins ()
   (*targetm.init_builtins) ();
 
   /* This is special for C++ so functions can be overloaded.  */
-  wchar_type_node = get_identifier (flag_short_wchar
-                                   ? "short unsigned int"
-                                   : WCHAR_TYPE);
+  wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
   wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
   if (c_language == clk_cplusplus)
@@ -2984,8 +3508,11 @@ c_common_nodes_and_builtins ()
 #undef DEF_FUNCTION_TYPE_VAR_1
 #undef DEF_POINTER_TYPE
 
-#define DEF_BUILTIN(ENUM, NAME, CLASS,                                 \
-                    TYPE, LIBTYPE, BOTH_P, FALLBACK_P, NONANSI_P)      \
+  if (!c_attrs_initialized)
+    c_init_attributes ();
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE,                  \
+                   BOTH_P, FALLBACK_P, NONANSI_P, ATTRS)               \
   if (NAME)                                                            \
     {                                                                  \
       tree decl;                                                       \
@@ -2998,7 +3525,8 @@ c_common_nodes_and_builtins ()
                                 CLASS,                                 \
                                 (FALLBACK_P                            \
                                  ? (NAME + strlen ("__builtin_"))      \
-                                 : NULL));                             \
+                                 : NULL),                              \
+                                built_in_attributes[(int) ATTRS]);     \
       else                                                             \
        decl = builtin_function_2 (NAME,                                \
                                   NAME + strlen ("__builtin_"),        \
@@ -3008,35 +3536,13 @@ c_common_nodes_and_builtins ()
                                   CLASS,                               \
                                   FALLBACK_P,                          \
                                   NONANSI_P,                           \
-                                  /*noreturn_p=*/0);                   \
+                                  built_in_attributes[(int) ATTRS]);   \
                                                                        \
       built_in_decls[(int) ENUM] = decl;                               \
     }                                                                  
 #include "builtins.def"
 #undef DEF_BUILTIN
 
-  /* Declare _exit and _Exit just to mark them as non-returning.  */
-  builtin_function_2 (NULL, "_exit", NULL_TREE, 
-                     builtin_types[BT_FN_VOID_INT],
-                     0, NOT_BUILT_IN, 0, 1, 1);
-  builtin_function_2 (NULL, "_Exit", NULL_TREE, 
-                     builtin_types[BT_FN_VOID_INT],
-                     0, NOT_BUILT_IN, 0, !flag_isoc99, 1);
-
-  /* Declare these functions non-returning
-     to avoid spurious "control drops through" warnings.  */
-  builtin_function_2 (NULL, "abort",
-                     NULL_TREE, ((c_language == clk_cplusplus)
-                                 ? builtin_types[BT_FN_VOID]
-                                 : builtin_types[BT_FN_VOID_VAR]),
-                     0, NOT_BUILT_IN, 0, 0, 1);
-
-  builtin_function_2 (NULL, "exit",
-                     NULL_TREE, ((c_language == clk_cplusplus)
-                                 ? builtin_types[BT_FN_VOID_INT]
-                                 : builtin_types[BT_FN_VOID_VAR]),
-                     0, NOT_BUILT_IN, 0, 0, 1);
-
   main_identifier_node = get_identifier ("main");
 }
 
@@ -3104,15 +3610,15 @@ builtin_function_disabled_p (name)
    conflicts with headers.  FUNCTION_CODE and CLASS are as for
    builtin_function.  If LIBRARY_NAME_P is nonzero, NAME is passed as
    the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
-   If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name; if
-   NORETURN_P is nonzero, the function is marked as non-returning.
+   If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name;
+   ATTRS is the tree list representing the builtin's function attributes.
    Returns the declaration of BUILTIN_NAME, if any, otherwise
    the declaration of NAME.  Does not declare NAME if flag_no_builtin,
    or if NONANSI_P and flag_no_nonansi_builtin.  */
 
 static tree
 builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
-                   class, library_name_p, nonansi_p, noreturn_p)
+                   class, library_name_p, nonansi_p, attrs)
      const char *builtin_name;
      const char *name;
      tree builtin_type;
@@ -3121,31 +3627,23 @@ builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
      enum built_in_class class;
      int library_name_p;
      int nonansi_p;
-     int noreturn_p;
+     tree attrs;
 {
   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);
-      if (noreturn_p)
-       {
-         TREE_THIS_VOLATILE (bdecl) = 1;
-         TREE_SIDE_EFFECTS (bdecl) = 1;
-       }
+                               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);
+      decl = builtin_function (name, type, function_code, class, NULL,
+                              attrs);
       if (nonansi_p)
        DECL_BUILT_IN_NONANSI (decl) = 1;
-      if (noreturn_p)
-       {
-         TREE_THIS_VOLATILE (decl) = 1;
-         TREE_SIDE_EFFECTS (decl) = 1;
-       }
     }
   return (bdecl != 0 ? bdecl : decl);
 }
@@ -3370,7 +3868,7 @@ expand_tree_builtin (function, params, coerced_params)
   return NULL_TREE;
 }
 
-/* Returns non-zero if CODE is the code for a statement.  */
+/* Returns nonzero if CODE is the code for a statement.  */
 
 int
 statement_code_p (code)
@@ -3688,41 +4186,6 @@ finish_label_address_expr (label)
   return result;
 }
 
-/* Mark P (a stmt_tree) for GC.  The use of a `void *' for the
-   parameter allows this function to be used as a GC-marking
-   function.  */
-
-void
-mark_stmt_tree (p)
-     void *p;
-{
-  stmt_tree st = (stmt_tree) p;
-
-  ggc_mark_tree (st->x_last_stmt);
-  ggc_mark_tree (st->x_last_expr_type);
-}
-
-/* Mark LD for GC.  */
-
-void
-c_mark_lang_decl (c)
-     struct c_lang_decl *c ATTRIBUTE_UNUSED;
-{
-}
-
-/* Mark F for GC.  */
-
-void
-mark_c_language_function (f)
-     struct language_function *f;
-{
-  if (!f)
-    return;
-
-  mark_stmt_tree (&f->x_stmt_tree);
-  ggc_mark_tree (f->x_scope_stmt_stack);
-}
-
 /* Hook used by expand_expr to expand language-specific tree codes.  */
 
 rtx
@@ -3739,6 +4202,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.
@@ -3766,8 +4230,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;
+                 }
              }
          }
 
@@ -3775,7 +4251,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);
@@ -4069,7 +4547,7 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked)
          memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1);
          newstr[newlen - 1] = 0;
          
-         arglist = combine_strings (build_string (newlen, newstr));
+         arglist = fix_string_type (build_string (newlen, newstr));
          arglist = build_tree_list (NULL_TREE, arglist);
          fn = fn_puts;
        }
@@ -4208,115 +4686,499 @@ boolean_increment (code, arg)
   return val;
 }
 \f
-/* Handle C and C++ default attributes.  */
-
-enum built_in_attribute
+/* Define macros necessary to describe fundamental data type formats.  */
+static void
+cpp_define_data_format (pfile)
+    cpp_reader *pfile;
 {
-#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
-#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
-#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum.  */
-#include "builtin-attrs.def"
-#undef DEF_ATTR_NULL_TREE
-#undef DEF_ATTR_INT
-#undef DEF_ATTR_IDENT
-#undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
-  ATTR_LAST
-};
+  const char *format;
+
+  /* Define supported floating-point format enumeration values.  */
+  cpp_define (pfile, "__UNKNOWN_FORMAT__=0");
+  cpp_define (pfile, "__IEEE_FORMAT__=1");
+  cpp_define (pfile, "__IBM_FORMAT__=2");
+  cpp_define (pfile, "__C4X_FORMAT__=3");
+  cpp_define (pfile, "__VAX_FORMAT__=4");
+  
+  switch (TARGET_FLOAT_FORMAT)
+    {
+    case UNKNOWN_FLOAT_FORMAT:
+      format = "__UNKNOWN_FORMAT__";
+      break;
+    case IEEE_FLOAT_FORMAT:
+      format = "__IEEE_FORMAT__";
+      break;
+    case VAX_FLOAT_FORMAT:
+      format = "__VAX_FORMAT__";
+      break;
+    case IBM_FLOAT_FORMAT:
+      format = "__IBM_FORMAT__";
+      break;
+    case C4X_FLOAT_FORMAT:
+      format = "__C4X_FORMAT__";
+      break;
+    default:
+      abort();
+    }
 
-static tree built_in_attributes[(int) ATTR_LAST];
+  builtin_define_with_value ("__GCC_FLOAT_FORMAT__", format, 0);
+}
 
-static bool c_attrs_initialized = false;
+/* Define NAME with value TYPE precision.  */
+static void
+builtin_define_type_precision (name, type)
+     const char *name;
+     tree type;
+{
+  builtin_define_with_int_value (name, TYPE_PRECISION (type));
+}
 
-static void c_init_attributes PARAMS ((void));
+/* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX.  */
+static void
+builtin_define_float_constants (name_prefix, fp_suffix, type)
+     const char *name_prefix;
+     const char *fp_suffix;
+     tree type;
+{
+  /* Used to convert radix-based values to base 10 values in several cases.
+
+     In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
+     least 6 significant digits for correct results.  Using the fraction
+     formed by (log(2)*1e6)/(log(10)*1e6) overflows a 32-bit integer as an
+     intermediate; perhaps someone can find a better approximation, in the
+     mean time, I suspect using doubles won't harm the bootstrap here.  */
+
+  const double log10_2 = .30102999566398119521;
+  double log10_b;
+  const struct real_format *fmt;
+
+  char name[64], buf[128];
+  int dig, min_10_exp, max_10_exp;
+  int decimal_dig;
+
+  fmt = real_format_for_mode[TYPE_MODE (type) - QFmode];
+
+  /* The radix of the exponent representation.  */
+  if (type == float_type_node)
+    builtin_define_with_int_value ("__FLT_RADIX__", fmt->b);
+  log10_b = log10_2 * fmt->log2_b;
+
+  /* The number of radix digits, p, in the floating-point significand.  */
+  sprintf (name, "__%s_MANT_DIG__", name_prefix);
+  builtin_define_with_int_value (name, fmt->p);
+
+  /* The number of decimal digits, q, such that any floating-point number
+     with q decimal digits can be rounded into a floating-point number with
+     p radix b digits and back again without change to the q decimal digits,
+
+       p log10 b                       if b is a power of 10
+       floor((p - 1) log10 b)          otherwise
+  */
+  dig = (fmt->p - 1) * log10_b;
+  sprintf (name, "__%s_DIG__", name_prefix);
+  builtin_define_with_int_value (name, dig);
+
+  /* The minimum negative int x such that b**(x-1) is a normalized float.  */
+  sprintf (name, "__%s_MIN_EXP__", name_prefix);
+  sprintf (buf, "(%d)", fmt->emin);
+  builtin_define_with_value (name, buf, 0);
+
+  /* The minimum negative int x such that 10**x is a normalized float,
+
+         ceil (log10 (b ** (emin - 1)))
+       = ceil (log10 (b) * (emin - 1))
+
+     Recall that emin is negative, so the integer truncation calculates
+     the ceiling, not the floor, in this case.  */
+  min_10_exp = (fmt->emin - 1) * log10_b;
+  sprintf (name, "__%s_MIN_10_EXP__", name_prefix);
+  sprintf (buf, "(%d)", min_10_exp);
+  builtin_define_with_value (name, buf, 0);
+
+  /* The maximum int x such that b**(x-1) is a representable float.  */
+  sprintf (name, "__%s_MAX_EXP__", name_prefix);
+  builtin_define_with_int_value (name, fmt->emax);
+
+  /* The maximum int x such that 10**x is in the range of representable
+     finite floating-point numbers,
+
+         floor (log10((1 - b**-p) * b**emax))
+       = floor (log10(1 - b**-p) + log10(b**emax))
+       = floor (log10(1 - b**-p) + log10(b)*emax)
+
+     The safest thing to do here is to just compute this number.  But since
+     we don't link cc1 with libm, we cannot.  We could implement log10 here
+     a series expansion, but that seems too much effort because:
+
+     Note that the first term, for all extant p, is a number exceedingly close
+     to zero, but slightly negative.  Note that the second term is an integer
+     scaling an irrational number, and that because of the floor we are only
+     interested in its integral portion.
+
+     In order for the first term to have any effect on the integral portion
+     of the second term, the second term has to be exceedingly close to an
+     integer itself (e.g. 123.000000000001 or something).  Getting a result
+     that close to an integer requires that the irrational multiplicand have
+     a long series of zeros in its expansion, which doesn't occur in the
+     first 20 digits or so of log10(b).
+
+     Hand-waving aside, crunching all of the sets of constants above by hand
+     does not yield a case for which the first term is significant, which
+     in the end is all that matters.  */
+  max_10_exp = fmt->emax * log10_b;
+  sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
+  builtin_define_with_int_value (name, max_10_exp);
+
+  /* The number of decimal digits, n, such that any floating-point number
+     can be rounded to n decimal digits and back again without change to
+     the value. 
+
+       p * log10(b)                    if b is a power of 10
+       ceil(1 + p * log10(b))          otherwise
+
+     The only macro we care about is this number for the widest supported
+     floating type, but we want this value for rendering constants below.  */
+  {
+    double d_decimal_dig = 1 + fmt->p * log10_b;
+    decimal_dig = d_decimal_dig;
+    if (decimal_dig < d_decimal_dig)
+      decimal_dig++;
+  }
+  if (type == long_double_type_node)
+    builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
+
+  /* Since, for the supported formats, B is always a power of 2, we
+     construct the following numbers directly as a hexadecimal
+     constants.  */
+
+  /* The maximum representable finite floating-point number,
+     (1 - b**-p) * b**emax  */
+  {
+    int i, n;
+    char *p;
+
+    strcpy (buf, "0x0.");
+    n = fmt->p * fmt->log2_b;
+    for (i = 0, p = buf + 4; i + 3 < n; i += 4)
+      *p++ = 'f';
+    if (i < n)
+      *p++ = "08ce"[n - i];
+    sprintf (p, "p%d", fmt->emax * fmt->log2_b);
+  }
+  sprintf (name, "__%s_MAX__", name_prefix);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+  /* The minimum normalized positive floating-point number,
+     b**(emin-1).  */
+  sprintf (name, "__%s_MIN__", name_prefix);
+  sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+  /* The difference between 1 and the least value greater than 1 that is
+     representable in the given floating point type, b**(1-p).  */
+  sprintf (name, "__%s_EPSILON__", name_prefix);
+  sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+  /* For C++ std::numeric_limits<T>::denorm_min.  The minimum denormalized
+     positive floating-point number, b**(emin-p).  Zero for formats that
+     don't support denormals.  */
+  sprintf (name, "__%s_DENORM_MIN__", name_prefix);
+  if (fmt->has_denorm)
+    {
+      sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
+      builtin_define_with_hex_fp_value (name, type, decimal_dig,
+                                       buf, fp_suffix);
+    }
+  else
+    {
+      sprintf (buf, "0.0%s", fp_suffix);
+      builtin_define_with_value (name, buf, 0);
+    }
+}
 
-/* Common initialization before parsing options.  */
+/* Hook that registers front end and target-specific built-ins.  */
 void
-c_common_init_options (lang)
-     enum c_language_kind lang;
+cb_register_builtins (pfile)
+     cpp_reader *pfile;
 {
-  c_language = lang;
-  parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89:
-                               lang == clk_cplusplus ? CLK_GNUCXX: CLK_OBJC);
+  /* -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");
+      if (flag_exceptions)
+       cpp_define (pfile, "__EXCEPTIONS");
+      if (warn_deprecated)
+       cpp_define (pfile, "__DEPRECATED");
+    }
+
+  /* represents the C++ ABI version, always defined so it can be used while
+     preprocessing C and assembler.  */
+  cpp_define (pfile, "__GXX_ABI_VERSION=102");
+
+  /* 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);
+
+  builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
+  builtin_define_type_precision ("__WCHAR_BIT__", wchar_type_node);
+  builtin_define_type_precision ("__SHRT_BIT__", short_integer_type_node);
+  builtin_define_type_precision ("__INT_BIT__", integer_type_node);
+  builtin_define_type_precision ("__LONG_BIT__", long_integer_type_node);
+  builtin_define_type_precision ("__LONG_LONG_BIT__",
+                                 long_long_integer_type_node);
+  builtin_define_type_precision ("__FLOAT_BIT__", float_type_node);
+  builtin_define_type_precision ("__DOUBLE_BIT__", double_type_node);
+  builtin_define_type_precision ("__LONG_DOUBLE_BIT__", long_double_type_node);
+
+  /* float.h needs to know these.  */
+
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+                                TARGET_FLT_EVAL_METHOD);
+
+  builtin_define_float_constants ("FLT", "F", float_type_node);
+  builtin_define_float_constants ("DBL", "", double_type_node);
+  builtin_define_float_constants ("LDBL", "L", long_double_type_node);
+
+  /* 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__=1");
+  else
+    cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
 
-  /* Mark as "unspecified" (see c_common_post_options).  */
-  flag_bounds_check = -1;
+  if (flag_iso)
+    cpp_define (pfile, "__STRICT_ANSI__");
+
+  if (!flag_signed_char)
+    cpp_define (pfile, "__CHAR_UNSIGNED__");
+
+  if (c_language == clk_cplusplus && TREE_UNSIGNED (wchar_type_node))
+    cpp_define (pfile, "__WCHAR_UNSIGNED__");
+
+  cpp_define_data_format (pfile);
+  
+  /* Make the choice of ObjC runtime visible to source code.  */
+  if (flag_objc && flag_next_runtime)
+    cpp_define (pfile, "__NEXT_RUNTIME__");
+
+  /* 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 ();
 }
 
-/* Post-switch processing.  */
+/* 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
-c_common_post_options ()
+builtin_define_std (macro)
+     const char *macro;
 {
-  cpp_post_options (parse_in);
+  size_t len = strlen (macro);
+  char *buff = alloca (len + 5);
+  char *p = buff + 2;
+  char *q = p + len;
 
-  flag_inline_trees = 1;
+  /* 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);
 
-  /* 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 it was in user's namespace...  */
+  if (p != buff + 2)
     {
-      if (!flag_no_inline)
-       flag_no_inline = 1;
-      if (flag_inline_functions)
-       {
-         flag_inline_trees = 2;
-         flag_inline_functions = 0;
-       }
+      /* 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);
 
-  /* 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_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");
+  cpp_define (parse_in, buf);
 }
 
-/* Front end initialization common to C, ObjC and C++.  */
-const char *
-c_common_init (filename)
-     const char *filename;
+/* Pass an object-like macro and an integer value to define it to.  */
+static void
+builtin_define_with_int_value (macro, value)
+     const char *macro;
+     HOST_WIDE_INT value;
 {
-  /* NULL is passed up to toplev.c and we exit quickly.  */
-  if (flag_preprocess_only)
-    {
-      cpp_preprocess_file (parse_in);
-      return NULL;
-    }
+  char *buf;
+  size_t mlen = strlen (macro);
+  size_t vlen = 18;
+  size_t extra = 2; /* space for = and NUL.  */
 
-  /* Do this before initializing pragmas, as then cpplib's hash table
-     has been set up.  */
-  filename = init_c_lex (filename);
+  buf = alloca (mlen + vlen + extra);
+  memcpy (buf, macro, mlen);
+  buf[mlen] = '=';
+  sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
 
-  init_pragma ();
+  cpp_define (parse_in, buf);
+}
 
-  if (!c_attrs_initialized)
-    c_init_attributes ();
+/* Pass an object-like macro a hexadecimal floating-point value.  */
+static void
+builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
+     const char *macro;
+     tree type ATTRIBUTE_UNUSED;
+     int digits;
+     const char *hex_str;
+     const char *fp_suffix;
+{
+  REAL_VALUE_TYPE real;
+  char dec_str[64], buf[256];
+
+  /* Hex values are really cool and convenient, except that they're
+     not supported in strict ISO C90 mode.  First, the "p-" sequence
+     is not valid as part of a preprocessor number.  Second, we get a
+     pedwarn from the preprocessor, which has no context, so we can't
+     suppress the warning with __extension__.
+
+     So instead what we do is construct the number in hex (because 
+     it's easy to get the exact correct value), parse it as a real,
+     then print it back out as decimal.  */
 
-  return filename;
+  real_from_string (&real, hex_str);
+  real_to_decimal (dec_str, &real, digits);
+
+  sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+  cpp_define (parse_in, buf);
 }
 
-/* Common finish hook for the C, ObjC and C++ front ends.  */
-void
-c_common_finish ()
+/* 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;
 {
-  cpp_finish (parse_in);
+  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);
 
-  /* For performance, avoid tearing down cpplib's internal structures.
-     Call cpp_errors () instead of cpp_destroy ().  */
-  errorcount += cpp_errors (parse_in);
+  sprintf (buf, "%s=%s%s", macro, value,
+          (is_long == 1 ? "L" : is_long == 2 ? "LL" : ""));
+
+  cpp_define (parse_in, buf);
 }
 
 static void
@@ -4341,7 +5203,6 @@ c_init_attributes ()
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
 #undef DEF_FN_ATTR
-  ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST);
   c_attrs_initialized = true;
 }
 
@@ -4800,8 +5661,20 @@ handle_mode_attribute (node, name, args, flags, no_add_attrs)
                     (mode, TREE_UNSIGNED (type))))
        error ("no data type for mode `%s'", p);
       else
-       *node = typefm;
-        /* No need to layout the type here.  The caller should do this.  */
+       {
+         /* If this is a vector, make sure we either have hardware
+            support, or we can emulate it.  */
+         if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+              || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+             && !vector_mode_valid_p (mode))
+           {
+             error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+             return NULL_TREE;
+           }
+
+         *node = typefm;
+         /* No need to layout the type here.  The caller should do this.  */
+       }
     }
 
   return NULL_TREE;
@@ -5346,6 +6219,16 @@ handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
 
       new_type = build_type_copy (new_type);
 
+      /* If this is a vector, make sure we either have hardware
+         support, or we can emulate it.  */
+      if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+          || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+         && !vector_mode_valid_p (mode))
+       {
+         error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+         return NULL_TREE;
+       }
+
       /* Set the debug information here, because this is the only
         place where we know the underlying type for a vector made
         with vector_size.  For debugging purposes we pretend a vector
@@ -5409,3 +6292,305 @@ vector_size_helper (type, bottom)
 
   return outer;
 }
+
+/* Handle the "nonnull" attribute.  */
+static tree
+handle_nonnull_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name ATTRIBUTE_UNUSED;
+     tree args;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  tree type = *node;
+  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
+     will have the correct types when we actually check them later.  */
+  if (! args)
+    {
+      if (! TYPE_ARG_TYPES (type))
+       {
+         error ("nonnull attribute without arguments on a non-prototype");
+          *no_add_attrs = true;
+       }
+      return NULL_TREE;
+    }
+
+  /* Argument list specified.  Verify that each argument number references
+     a pointer argument.  */
+  for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
+    {
+      tree argument;
+      unsigned HOST_WIDE_INT arg_num, ck_num;
+
+      if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
+       {
+         error ("nonnull argument has invalid operand number (arg %lu)",
+                (unsigned long) attr_arg_num);
+         *no_add_attrs = true;
+         return NULL_TREE;
+       }
+
+      argument = TYPE_ARG_TYPES (type);
+      if (argument)
+       {
+         for (ck_num = 1; ; ck_num++)
+           {
+             if (! argument || ck_num == arg_num)
+               break;
+             argument = TREE_CHAIN (argument);
+           }
+
+          if (! argument
+             || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
+           {
+             error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
+                    (unsigned long) attr_arg_num, (unsigned long) arg_num);
+             *no_add_attrs = true;
+             return NULL_TREE;
+           }
+
+          if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
+           {
+             error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
+                  (unsigned long) attr_arg_num, (unsigned long) arg_num);
+             *no_add_attrs = true;
+             return NULL_TREE;
+           }
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Check the argument list of a function call for null in argument slots
+   that are marked as requiring a non-null pointer argument.  */
+
+static void
+check_function_nonnull (attrs, params)
+     tree attrs;
+     tree params;
+{
+  tree a, args, param;
+  int param_num;
+
+  for (a = attrs; a; a = TREE_CHAIN (a))
+    {
+      if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
+       {
+          args = TREE_VALUE (a);
+
+          /* Walk the argument list.  If we encounter an argument number we
+             should check for non-null, do it.  If the attribute has no args,
+             then every pointer argument is checked (in which case the check
+            for pointer type is done in check_nonnull_arg).  */
+          for (param = params, param_num = 1; ;
+               param_num++, param = TREE_CHAIN (param))
+            {
+              if (! param)
+               break;
+              if (! args || nonnull_check_p (args, param_num))
+               check_function_arguments_recurse (check_nonnull_arg, NULL,
+                                                 TREE_VALUE (param),
+                                                 param_num);
+            }
+       }
+    }
+}
+
+/* Helper for check_function_nonnull; given a list of operands which
+   must be non-null in ARGS, determine if operand PARAM_NUM should be
+   checked.  */
+
+static bool
+nonnull_check_p (args, param_num)
+     tree args;
+     unsigned HOST_WIDE_INT param_num;
+{
+  unsigned HOST_WIDE_INT arg_num;
+
+  for (; args; args = TREE_CHAIN (args))
+    {
+      if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
+        abort ();
+
+      if (arg_num == param_num)
+       return true;
+    }
+  return false;
+}
+
+/* Check that the function argument PARAM (which is operand number
+   PARAM_NUM) is non-null.  This is called by check_function_nonnull
+   via check_function_arguments_recurse.  */
+
+static void
+check_nonnull_arg (ctx, param, param_num)
+     void *ctx ATTRIBUTE_UNUSED;
+     tree param;
+     unsigned HOST_WIDE_INT param_num;
+{
+  /* Just skip checking the argument if it's not a pointer.  This can
+     happen if the "nonnull" attribute was given without an operand
+     list (which means to check every pointer argument).  */
+
+  if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
+    return;
+
+  if (integer_zerop (param))
+    warning ("null argument where non-null required (arg %lu)",
+             (unsigned long) param_num);
+}
+
+/* Helper for nonnull attribute handling; fetch the operand number
+   from the attribute argument list.  */
+
+static bool
+get_nonnull_operand (arg_num_expr, valp)
+     tree arg_num_expr;
+     unsigned HOST_WIDE_INT *valp;
+{
+  /* Strip any conversions from the arg number and verify they
+     are constants.  */
+  while (TREE_CODE (arg_num_expr) == NOP_EXPR
+        || TREE_CODE (arg_num_expr) == CONVERT_EXPR
+        || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
+    arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
+
+  if (TREE_CODE (arg_num_expr) != INTEGER_CST
+      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+    return false;
+
+  *valp = TREE_INT_CST_LOW (arg_num_expr);
+  return true;
+}
+
+/* Handle a "nothrow" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_nothrow_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args ATTRIBUTE_UNUSED;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_NOTHROW (*node) = 1;
+  /* ??? TODO: Support types.  */
+  else
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+\f
+/* Check for valid arguments being passed to a function.  */
+void
+check_function_arguments (attrs, params)
+     tree attrs;
+     tree params;
+{
+  /* Check for null being passed in a pointer argument that must be
+     non-null.  We also need to do this if format checking is enabled.  */
+
+  if (warn_nonnull)
+    check_function_nonnull (attrs, params);
+
+  /* Check for errors in format strings.  */
+
+  if (warn_format)
+    check_function_format (NULL, attrs, params);
+}
+
+/* Generic argument checking recursion routine.  PARAM is the argument to
+   be checked.  PARAM_NUM is the number of the argument.  CALLBACK is invoked
+   once the argument is resolved.  CTX is context for the callback.  */
+void
+check_function_arguments_recurse (callback, ctx, param, param_num)
+     void (*callback) PARAMS ((void *, tree, unsigned HOST_WIDE_INT));
+     void *ctx;
+     tree param;
+     unsigned HOST_WIDE_INT param_num;
+{
+  if (TREE_CODE (param) == NOP_EXPR)
+    {
+      /* Strip coercion.  */
+      check_function_arguments_recurse (callback, ctx,
+                                       TREE_OPERAND (param, 0), param_num);
+      return;
+    }
+
+  if (TREE_CODE (param) == CALL_EXPR)
+    {
+      tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
+      tree attrs;
+      bool found_format_arg = false;
+
+      /* See if this is a call to a known internationalization function
+        that modifies a format arg.  Such a function may have multiple
+        format_arg attributes (for example, ngettext).  */
+
+      for (attrs = TYPE_ATTRIBUTES (type);
+          attrs;
+          attrs = TREE_CHAIN (attrs))
+       if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
+         {
+           tree inner_args;
+           tree format_num_expr;
+           int format_num;
+           int i;
+
+           /* Extract the argument number, which was previously checked
+              to be valid.  */
+           format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
+           while (TREE_CODE (format_num_expr) == NOP_EXPR
+                  || TREE_CODE (format_num_expr) == CONVERT_EXPR
+                  || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
+             format_num_expr = TREE_OPERAND (format_num_expr, 0);
+
+           if (TREE_CODE (format_num_expr) != INTEGER_CST
+               || TREE_INT_CST_HIGH (format_num_expr) != 0)
+             abort ();
+
+           format_num = TREE_INT_CST_LOW (format_num_expr);
+
+           for (inner_args = TREE_OPERAND (param, 1), i = 1;
+                inner_args != 0;
+                inner_args = TREE_CHAIN (inner_args), i++)
+             if (i == format_num)
+               {
+                 check_function_arguments_recurse (callback, ctx,
+                                                   TREE_VALUE (inner_args),
+                                                   param_num);
+                 found_format_arg = true;
+                 break;
+               }
+         }
+
+      /* If we found a format_arg attribute and did a recursive check,
+        we are done with checking this argument.  Otherwise, we continue
+        and this will be considered a non-literal.  */
+      if (found_format_arg)
+       return;
+    }
+
+  if (TREE_CODE (param) == COND_EXPR)
+    {
+      /* Check both halves of the conditional expression.  */
+      check_function_arguments_recurse (callback, ctx,
+                                       TREE_OPERAND (param, 1), param_num);
+      check_function_arguments_recurse (callback, ctx,
+                                       TREE_OPERAND (param, 2), param_num);
+      return;
+    }
+
+  (*callback) (ctx, param, param_num);
+}
+
+#include "gt-c-common.h"