#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 "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. */
: "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
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;
int warn_redundant_decls;
-/* Warn about testing equality of floating point numbers. */
+/* Warn about testing equality of floating point numbers. */
int warn_float_equal;
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.). */
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. */
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;
/* 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,
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[] =
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)
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");
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.
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;
+ }
}
}
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);
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;
{
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__");
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);
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)
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". */
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 ()
{