OSDN Git Service

* ChangeLog: Follow spelling conventions.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 85a0e38..a9ed096 100644 (file)
@@ -31,7 +31,6 @@ 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"
@@ -39,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "langhooks.h"
 #include "except.h"            /* For USING_SJLJ_EXCEPTIONS.  */
+#include "tree-inline.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -84,10 +84,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
@@ -201,6 +197,9 @@ int flag_preprocess_only;
    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;
@@ -292,7 +291,7 @@ int warn_write_strings;
 
 int warn_redundant_decls;
 
-/* Warn about testing equality of floating point numbers. */
+/* Warn about testing equality of floating point numbers.  */
 
 int warn_float_equal;
 
@@ -304,14 +303,10 @@ int warn_char_subscripts;
 
 int warn_conversion;
 
-/* Warn about #pragma directives that are not recognised.  */      
+/* Warn about #pragma directives that are not recognized.  */      
 
 int warn_unknown_pragmas; /* Tri state variable.  */  
 
-/* Nonzero means warn about use of multicharacter literals.  */
-
-int warn_multichar = 1;
-
 /* Warn about format/argument anomalies in calls to formatted I/O functions
    (*printf, *scanf, strftime, strfmon, etc.).  */
 
@@ -444,10 +439,18 @@ int print_struct_values;
 const char *constant_string_class_name;
 
 /* Warn if multiple methods are seen for the same selector, but with
-   different argument types.  */
+   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.  */
@@ -564,6 +567,11 @@ int flag_permissive;
 
 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;
@@ -690,8 +698,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,
@@ -755,8 +761,17 @@ 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));
+                                               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[] =
@@ -1102,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)
@@ -1117,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");
@@ -4177,6 +4200,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.
@@ -4204,8 +4228,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;
+                 }
              }
          }
 
@@ -4213,7 +4249,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);
@@ -4646,75 +4684,374 @@ boolean_increment (code, arg)
   return val;
 }
 \f
-/* Common initialization before parsing options.  */
-void
-c_common_init_options (lang)
-     enum c_language_kind lang;
+/* Define macros necessary to describe fundamental data type formats.  */
+static void
+cpp_define_data_format (pfile)
+    cpp_reader *pfile;
+{
+  const char *format;
+
+  /* Define endianness enumeration values.  */
+  cpp_define (pfile, "__GCC_LITTLE_ENDIAN__=0");
+  cpp_define (pfile, "__GCC_BIG_ENDIAN__=1");
+
+  /* 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");
+  
+  /* Define target endianness:
+       - bit order
+       - byte order
+       - word order in an integer that spans a multi-word
+       - word order in a floating-poing that spans a multi-word  */
+  if (BITS_BIG_ENDIAN)
+    cpp_define (pfile, "__TARGET_BITS_ORDER__=__GCC_BIG_ENDIAN__");
+  else
+    cpp_define (pfile, "__TARGET_BITS_ORDER__=__GCC_BIG_ENDIAN__");
+  if (BYTES_BIG_ENDIAN)
+    cpp_define (pfile, "__TARGET_BYTES_ORDER__=__GCC_BIG_ENDIAN__");
+  else
+    cpp_define (pfile, "__TARGET_BYTES_ORDER__=__GCC_LITTLE_ENDIAN__");
+  /* Define words order in a multi-word integer.  */
+  if (WORDS_BIG_ENDIAN)
+    cpp_define (pfile, "__TARGET_INT_WORDS_ORDER__=__GCC_BIG_ENDIAN__");
+  else
+    cpp_define (pfile, "__TARGET_INT_WORDS_ORDER__=__GCC_LITTLE_ENDIAN__");
+  /* Define words order in a multi-word floating point.  */
+  if (FLOAT_WORDS_BIG_ENDIAN)
+    cpp_define (pfile, "__TARGET_FLOAT_WORDS_ORDER__=__GCC_BIG_ENDIAN__");
+  else
+    cpp_define (pfile, "__TARGET_FLOAT_WORDS_ORDER__=__GCC_LITTLE_ENDIAN__");
+
+  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__";
+      cpp_define (pfile, "__TARGET_USES_VAX_F_FLOAT__=1");
+#ifdef TARGET_G_FLOAT      
+      if (TARGET_G_FLOAT)
+        {
+          cpp_define (pfile, "__TARGET_USES_VAX_D_FLOAT__=0");
+          cpp_define (pfile, "__TARGET_USES_VAX_G_FLOAT__=1");
+        }
+      else
+        {
+          cpp_define (pfile, "__TARGET_USES_VAX_D_FLOAT__=1");
+          cpp_define (pfile, "__TARGET_USES_VAX_G_FLOAT__=0");
+        }
+#endif       
+      cpp_define (pfile, "__TARGET_USES_VAX_H_FLOAT__=1");
+      break;
+
+    case IBM_FLOAT_FORMAT:
+      format = "__IBM_FORMAT__";
+      break;
+
+    case C4X_FLOAT_FORMAT:
+      format = "__C4X_FORMAT__";
+      break;
+
+    default:
+      abort();
+    }
+  if (TARGET_FLOAT_FORMAT != VAX_FLOAT_FORMAT)
+    {
+      cpp_define (pfile, "__TARGET_USES_VAX_F_FLOAT__=0");
+      cpp_define (pfile, "__TARGET_USES_VAX_D_FLOAT__=0");
+      cpp_define (pfile, "__TARGET_USES_VAX_G_FLOAT__=0");
+      cpp_define (pfile, "__TARGET_USES_VAX_H_FLOAT__=0");
+    }
+  builtin_define_with_value ("__GCC_FLOAT_FORMAT__", format, 0);
+}
+
+/* Define NAME with value TYPE precision.  */
+static void
+builtin_define_type_precision (name, type)
+     const char *name;
+     tree type;
 {
-  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;
-
-  flag_const_strings = (lang == clk_cplusplus);
-  warn_pointer_arith = (lang == clk_cplusplus);
-  if (lang == clk_c)
-    warn_sign_compare = -1;
-
-  /* Mark as "unspecified" (see c_common_post_options).  */
-  flag_bounds_check = -1;
+  builtin_define_with_int_value (name, TYPE_PRECISION (type));
 }
 
-/* Post-switch processing.  */
-bool
-c_common_post_options ()
+/* 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;
 {
-  cpp_post_options (parse_in);
+  /* 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.  */
 
-  flag_inline_trees = 1;
+  const double log10_2 = .30102999566398119521;
+  const double log10_16 = 1.20411998265592478085;
+  const double log10_b
+    = TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT ? log10_16 : log10_2;
 
-  /* 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)
+  const int log2_b = TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT ? 4 : 1;
+
+  char name[64], buf[128];
+  int mant_dig, max_exp, min_exp;
+  int dig, min_10_exp, max_10_exp;
+  int decimal_dig;
+
+  /* ??? This information should be shared with real.c.  */
+
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+#define INTEL_EXTENDED_IEEE_FORMAT 0
+#endif
+#ifndef TARGET_G_FLOAT
+#define TARGET_G_FLOAT 0
+#endif
+
+  switch (TARGET_FLOAT_FORMAT)
     {
-      if (!flag_no_inline)
-       flag_no_inline = 1;
-      if (flag_inline_functions)
+    case IEEE_FLOAT_FORMAT:
+      switch (TYPE_PRECISION (type))
+       {
+       case 32:
+         /* ??? Handle MIPS r5900, which doesn't implement Inf or NaN,
+            but rather reuses the largest exponent as a normal number.  */
+         mant_dig = 24;
+         min_exp = -125;
+         max_exp = 128;
+         break;
+       case 64:
+         mant_dig = 53;
+         min_exp = -1021;
+         max_exp = 1024;
+         break;
+       case 128:
+         if (!INTEL_EXTENDED_IEEE_FORMAT)
+           {
+             mant_dig = 113;
+             min_exp = -16381;
+             max_exp = 16384;
+             break;
+           }
+         /* FALLTHRU */
+       case 96:
+         mant_dig = 64;
+         max_exp = 16384;
+         if (INTEL_EXTENDED_IEEE_FORMAT)
+           min_exp = -16381;
+         else
+           /* ??? Otherwise assume m68k.  */
+           min_exp = -16382;
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case VAX_FLOAT_FORMAT:
+      switch (TYPE_PRECISION (type))
+       {
+       case 32: /* F_FLOAT */
+         mant_dig = 24;
+         min_exp = -127;
+         max_exp = 127;
+         break;
+       case 64: /* G_FLOAT or D_FLOAT */
+         if (TARGET_G_FLOAT)
+           {
+             mant_dig = 53;
+             min_exp = -1023;
+             max_exp = 1023;
+           }
+         else
+           {
+             mant_dig = 56;
+             min_exp = -127;
+             max_exp = 127;
+           }
+         break;
+       case 128: /* H_FLOAT */
+         mant_dig = 113;
+         min_exp = -16383;
+         max_exp = 16383;
+         break;
+       default:
+         abort ();
+       }
+      break;
+
+    case IBM_FLOAT_FORMAT:
+      switch (TYPE_PRECISION (type))
+       {
+       case 32:
+         mant_dig = 6;
+         min_exp = -64;
+         max_exp = 63;
+         break;
+       case 64:
+         mant_dig = 14;
+         min_exp = -64;
+         max_exp = 63;
+         break;
+       default:
+         abort ();
+       }
+      break;
+      
+    case C4X_FLOAT_FORMAT:
+      switch (TYPE_PRECISION (type))
        {
-         flag_inline_trees = 2;
-         flag_inline_functions = 0;
+       case 32:
+         mant_dig = 24;
+         min_exp = -126;
+         max_exp = 128;
+         break;
+       case 64:
+         mant_dig = 32;
+         min_exp = -126;
+         max_exp = 128;
+         break;
+       default:
+         abort ();
        }
+      break;
+
+    default:
+      abort ();
     }
 
-  /* 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;
+  /* The number of radix digits, p, in the floating-point significand.  */
+  sprintf (name, "__%s_MANT_DIG__", name_prefix);
+  builtin_define_with_int_value (name, mant_dig);
+
+  /* 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 = (mant_dig - 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)", min_exp);
+  builtin_define_with_value (name, buf, 0);
+
+  /* The minimum negative int x such that 10**x is a normalized float,
+
+         ceil (log10 (b ** (min_exp - 1)))
+       = ceil (log10 (b) * (min_exp - 1))
+
+     Recall that min_exp is negative, so the integer truncation calculates
+     the ceiling, not the floor, in this case.  */
+  min_10_exp = (min_exp - 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, max_exp);
+
+  /* The maximum int x such that 10**x is in the range of representable
+     finite floating-point numbers,
+
+         floor (log10((1 - b**-p) * b**max_exp))
+       = floor (log10(1 - b**-p) + log10(b**max_exp))
+       = floor (log10(1 - b**-p) + log10(b)*max_exp)
+
+     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 = max_exp * 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 + mant_dig * 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**max_exp  */
+  {
+    int i, n;
+    char *p;
+
+    strcpy (buf, "0x0.");
+    n = mant_dig * 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", max_exp * 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**(min_exp-1).  */
+  sprintf (name, "__%s_MIN__", name_prefix);
+  sprintf (buf, "0x1p%d", (min_exp - 1) * 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 - mant_dig) * log2_b);
+  builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
 }
 
 /* Hook that registers front end and target-specific built-ins.  */
-static void
+void
 cb_register_builtins (pfile)
      cpp_reader *pfile;
 {
@@ -4732,9 +5069,12 @@ cb_register_builtins (pfile)
        cpp_define (pfile, "__EXCEPTIONS");
       if (warn_deprecated)
        cpp_define (pfile, "__DEPRECATED");
-      cpp_define (pfile, "__GXX_ABI_VERSION__=102");
     }
 
+  /* 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__");
@@ -4752,11 +5092,30 @@ cb_register_builtins (pfile)
   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);
-  }
+  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.  */
+
+  /* The radix of the exponent representation.  */
+  builtin_define_with_int_value ("__FLT_RADIX__",
+                                (TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
+                                 ? 16 : 2));
+
+  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);
@@ -4794,6 +5153,15 @@ cb_register_builtins (pfile)
   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)
@@ -4875,6 +5243,54 @@ builtin_define_with_value (macro, expansion, is_str)
   cpp_define (parse_in, buf);
 }
 
+/* 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;
+{
+  char *buf;
+  size_t mlen = strlen (macro);
+  size_t vlen = 18;
+  size_t extra = 2; /* space for = and NUL.  */
+
+  buf = alloca (mlen + vlen + extra);
+  memcpy (buf, macro, mlen);
+  buf[mlen] = '=';
+  sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
+
+  cpp_define (parse_in, buf);
+}
+
+/* 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;
+     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.  */
+
+  real = REAL_VALUE_HTOF (hex_str, TYPE_MODE (type));
+  REAL_VALUE_TO_DECIMAL (real, dec_str, digits);
+
+  sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+  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".  */
 
@@ -4923,62 +5339,6 @@ builtin_define_type_max (macro, type, is_long)
   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
 c_init_attributes ()
 {