#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "real.h"
#include "flags.h"
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
+#include "varray.h"
#include "expr.h"
#include "c-common.h"
#include "diagnostic.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
tree c_global_trees[CTI_MAX];
+/* Nonzero if we can read a PCH file now. */
+
+int allow_pch = 1;
+\f
/* Switches common to the C front ends. */
/* Nonzero if prepreprocessing only. */
int flag_preprocess_only;
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
int flag_iso;
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;
+/* The version of the C++ ABI in use. The following values are
+ allowed:
+
+ 0: The version of the ABI believed most conformant with the
+ C++ ABI specification. This ABI may change as bugs are
+ discovered and fixed. Therefore, 0 will not necessarily
+ indicate the same ABI in different versions of G++.
+
+ 1: The version of the ABI first used in G++ 3.2.
+
+ Additional positive integers will be assigned as new versions of
+ the ABI become the default version of the ABI. */
+
+int flag_abi_version = 1;
+
+/* Nonzero means warn about things that will change when compiling
+ with an ABI-compliant compiler. */
+
+int warn_abi = 0;
+
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
int warn_ctor_dtor_privacy = 1;
-/* Non-zero means warn in function declared in derived class has the
+/* 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;
-/* Non-zero means warn when declaring a class that has a non 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;
-/* Non-zero means warn when the compiler will reorder code. */
+/* Nonzero means warn when the compiler will reorder code. */
int warn_reorder;
-/* Non-zero means warn when synthesis behavior differs from Cfront's. */
+/* Nonzero means warn when synthesis behavior differs from Cfront's. */
int warn_synth;
-/* Non-zero means warn when we convert a pointer to member function
+/* Nonzero means warn when we convert a pointer to member function
into a pointer to (void or function). */
int warn_pmf2ptr = 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,
bool *));
static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int,
bool *));
+static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
tree, int,
bool *));
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 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[] =
handle_vector_size_attribute },
{ "visibility", 1, 1, true, false, false,
handle_visibility_attribute },
+ { "tls_model", 1, 1, true, false, false,
+ handle_tls_model_attribute },
{ "nonnull", 0, -1, false, true, true,
handle_nonnull_attribute },
{ "nothrow", 0, 0, true, false, false,
};
/* Give the specifications for the format attributes, used by C and all
- descendents. */
+ descendants. */
const struct attribute_spec c_common_format_attribute_table[] =
{
if (body)
{
- /* They were called into existence, so add to statement tree. */
- body = chainon (body,
- TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
- body = build_stmt (COMPOUND_STMT, body);
-
- COMPOUND_STMT_NO_SCOPE (body) = 1;
- TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)) = body;
+ /* They were called into existence, so add to statement tree. Add
+ the DECL_STMTs inside the outermost scope. */
+ tree *p = &DECL_SAVED_TREE (current_function_decl);
+ /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */
+ while (TREE_CODE (*p) != COMPOUND_STMT)
+ p = &TREE_CHAIN (*p);
+ p = &COMPOUND_BODY (*p);
+ if (TREE_CODE (*p) == SCOPE_STMT)
+ p = &TREE_CHAIN (*p);
+
+ body = chainon (body, *p);
+ *p = body;
}
for (ix = 0; fname_vars[ix].decl; ix++)
saved_function_name_decls = stack;
}
-/* Return the text name of the current function, suitable prettified
+/* Return the text name of the current function, suitably prettified
by PRETTY_P. */
const char *
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. */
+ it from appearing in the RTL. */
int saved_lineno = lineno;
lineno = 0;
}
if (!ix && !current_function_decl)
pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
-
+
return decl;
}
}
}
-/* 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
return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
case V2SImode:
return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+ case V2HImode:
+ return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
case V4HImode:
return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
case V8QImode:
return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+ case V1DImode:
+ return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
case V16SFmode:
return V16SF_type_node;
case V4SFmode:
case ABS_EXPR:
case FLOAT_EXPR:
case FFS_EXPR:
- /* These don't change whether an object is non-zero or zero. */
+ case POPCOUNT_EXPR:
+ /* These don't change whether an object is nonzero or zero. */
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
- /* These don't change whether an object is zero or non-zero, but
+ /* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),
if (! TYPE_P (t))
return -1;
- /* The C standard guarantess that any object may be accessed via an
+ /* The C standard guarantees that any object may be accessed via an
lvalue that has character type. */
if (t == char_type_node
|| t == signed_char_type_node
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- value = fold (build1 (NOP_EXPR, c_size_type_node, value));
+ value = fold (build1 (NOP_EXPR, size_type_node, value));
my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
return value;
else
return c_alignof (TREE_TYPE (expr));
- return fold (build1 (NOP_EXPR, c_size_type_node, t));
+ return fold (build1 (NOP_EXPR, size_type_node, t));
}
\f
/* Handle C and C++ default attributes. */
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
BT_LAST
};
/* `unsigned long' is the standard type for sizeof.
Note that stddef.h uses `unsigned long',
and this must agree, even if long and int are the same size. */
- c_size_type_node =
+ size_type_node =
TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
- signed_size_type_node = c_common_signed_type (c_size_type_node);
- set_sizetype (c_size_type_node);
+ signed_size_type_node = c_common_signed_type (size_type_node);
+ set_sizetype (size_type_node);
build_common_tree_nodes_2 (flag_short_double);
tree_cons (NULL_TREE, \
builtin_types[(int) ARG2], \
NULL_TREE)));
+
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ builtin_types[(int) ENUM] \
+ = build_function_type \
+ (builtin_types[(int) RETURN], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG1], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG2], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG3], \
+ NULL_TREE))));
+
#define DEF_POINTER_TYPE(ENUM, TYPE) \
builtin_types[(int) ENUM] \
= build_pointer_type (builtin_types[(int) TYPE]);
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
if (!c_attrs_initialized)
c_init_attributes ();
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
- BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \
+ BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
if (NAME) \
{ \
tree decl; \
built_in_attributes[(int) ATTRS]); \
\
built_in_decls[(int) ENUM] = decl; \
+ if (IMPLICIT) \
+ implicit_built_in_decls[(int) ENUM] = decl; \
}
#include "builtins.def"
#undef DEF_BUILTIN
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)
int unlocked;
{
tree fn_putchar = unlocked ?
- built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : built_in_decls[BUILT_IN_PUTCHAR];
+ implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR];
tree fn_puts = unlocked ?
- built_in_decls[BUILT_IN_PUTS_UNLOCKED] : built_in_decls[BUILT_IN_PUTS];
+ implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTS];
tree fn, format_arg, stripped_string;
/* If the return value is used, or the replacement _DECL isn't
int unlocked;
{
tree fn_fputc = unlocked ?
- built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : built_in_decls[BUILT_IN_FPUTC];
+ implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC];
tree fn_fputs = unlocked ?
- built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : built_in_decls[BUILT_IN_FPUTS];
+ implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTS];
tree fn, format_arg, stripped_string;
/* If the return value is used, or the replacement _DECL isn't
return val;
}
\f
-/* Hook that registers front end and target-specific built-ins. */
+/* 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));
+}
+
+/* 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);
+ }
+
+ /* For C++ std::numeric_limits<T>::has_infinity. */
+ sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
+ builtin_define_with_int_value (name,
+ MODE_HAS_INFINITIES (TYPE_MODE (type)));
+ /* For C++ std::numeric_limits<T>::has_quiet_NaN. We do not have a
+ predicate to distinguish a target that has both quiet and
+ signalling NaNs from a target that has only quiet NaNs or only
+ signalling NaNs, so we assume that a target that has any kind of
+ NaN has quiet NaNs. */
+ sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
+ builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
+}
+
+/* Hook that registers front end and target-specific built-ins. */
+void
cb_register_builtins (pfile)
cpp_reader *pfile;
{
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_max ("__WCHAR_MAX__", wchar_type_node, 0);
- {
- 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);
+
+ /* 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);
if (fast_math_flags_set_p ())
cpp_define (pfile, "__FAST_MATH__");
- if (flag_no_inline)
+ if (flag_really_no_inline)
cpp_define (pfile, "__NO_INLINE__");
if (flag_signaling_nans)
cpp_define (pfile, "__SUPPORT_SNAN__");
if (!flag_signed_char)
cpp_define (pfile, "__CHAR_UNSIGNED__");
+ if (c_language == clk_cplusplus && TREE_UNSIGNED (wchar_type_node))
+ cpp_define (pfile, "__WCHAR_UNSIGNED__");
+
+ /* 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 preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
# define builtin_define(TXT) cpp_define (pfile, TXT)
# define builtin_assert(TXT) cpp_assert (pfile, TXT)
TARGET_CPU_CPP_BUILTINS ();
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". */
-
+/* Pass an object-like macro and an integer value to define it to. */
static void
-builtin_define_type_max (macro, type, is_long)
+builtin_define_with_int_value (macro, value)
const char *macro;
- tree type;
- int is_long;
+ HOST_WIDE_INT value;
{
- 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 ();
- }
+ size_t mlen = strlen (macro);
+ size_t vlen = 18;
+ size_t extra = 2; /* space for = and NUL. */
- mlen = strlen (macro);
- vlen = strlen (value);
- extra = 2 + is_long;
buf = alloca (mlen + vlen + extra);
-
- sprintf (buf, "%s=%s%s", macro, value,
- (is_long == 1 ? "L" : is_long == 2 ? "LL" : ""));
+ memcpy (buf, macro, mlen);
+ buf[mlen] = '=';
+ sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
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 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;
{
- cpp_options *options = cpp_get_options (parse_in);
+ REAL_VALUE_TYPE real;
+ char dec_str[64], buf[256];
- /* 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;
+ /* 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__.
- /* We want -Wno-long-long to override -pedantic -std=non-c99
- and/or -Wtraditional, whatever the ordering. */
- options->warn_long_long
- = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
+ 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. */
- /* Register preprocessor built-ins before calls to
- cpp_main_file. */
- cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins;
+ real_from_string (&real, hex_str);
+ real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
- /* NULL is passed up to toplev.c and we exit quickly. */
- if (flag_preprocess_only)
- {
- cpp_preprocess_file (parse_in);
- return NULL;
- }
+ sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+ cpp_define (parse_in, buf);
+}
- /* Do this before initializing pragmas, as then cpplib's hash table
- has been set up. */
- filename = init_c_lex (filename);
+/* Define MAX for TYPE based on the precision of the type. IS_LONG is
+ 1 for type "long" and 2 for "long long". We have to handle
+ unsigned types, since wchar_t might be unsigned. */
- init_pragma ();
+static void
+builtin_define_type_max (macro, type, is_long)
+ const char *macro;
+ tree type;
+ int is_long;
+{
+ static const char *const values[]
+ = { "127", "255",
+ "32767", "65535",
+ "2147483647", "4294967295",
+ "9223372036854775807", "18446744073709551615",
+ "170141183460469231731687303715884105727",
+ "340282366920938463463374607431768211455" };
+ static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
+
+ const char *value, *suffix;
+ char *buf;
+ size_t idx;
- if (!c_attrs_initialized)
- c_init_attributes ();
+ /* 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: idx = 0; break;
+ case 16: idx = 2; break;
+ case 32: idx = 4; break;
+ case 64: idx = 6; break;
+ case 128: idx = 8; break;
+ default: abort ();
+ }
- return filename;
-}
+ value = values[idx + TREE_UNSIGNED (type)];
+ suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)];
-/* Common finish hook for the C, ObjC and C++ front ends. */
-void
-c_common_finish ()
-{
- cpp_finish (parse_in);
+ buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1);
+ sprintf (buf, "%s=%s%s", macro, value, suffix);
- /* For performance, avoid tearing down cpplib's internal structures.
- Call cpp_errors () instead of cpp_destroy (). */
- errorcount += cpp_errors (parse_in);
+ cpp_define (parse_in, buf);
}
static void
struct attribute_spec.handler. */
static tree
-handle_used_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
+handle_used_attribute (pnode, name, args, flags, no_add_attrs)
+ tree *pnode;
tree name;
tree args ATTRIBUTE_UNUSED;
int flags ATTRIBUTE_UNUSED;
bool *no_add_attrs;
{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
- = TREE_USED (*node) = 1;
+ tree node = *pnode;
+
+ if (TREE_CODE (node) == FUNCTION_DECL
+ || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (node))
+ = TREE_USED (node) = 1;
else
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
+ tree ptr_type;
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
(mode, TREE_UNSIGNED (type))))
error ("no data type for mode `%s'", p);
+ else if ((TREE_CODE (type) == POINTER_TYPE
+ || TREE_CODE (type) == REFERENCE_TYPE)
+ && !(*targetm.valid_pointer_mode) (mode))
+ error ("invalid pointer mode `%s'", p);
else
{
/* If this is a vector, make sure we either have hardware
return NULL_TREE;
}
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
+ mode);
+ *node = ptr_type;
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
+ mode);
+ *node = ptr_type;
+ }
+ else
*node = typefm;
/* No need to layout the type here. The caller should do this. */
}
}
if (strcmp (TREE_STRING_POINTER (id), "hidden")
&& strcmp (TREE_STRING_POINTER (id), "protected")
- && strcmp (TREE_STRING_POINTER (id), "internal"))
+ && strcmp (TREE_STRING_POINTER (id), "internal")
+ && strcmp (TREE_STRING_POINTER (id), "default"))
+ {
+ error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "tls_model" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_tls_model_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (! DECL_THREAD_LOCAL (decl))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ tree id;
+
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("tls_model arg not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ if (strcmp (TREE_STRING_POINTER (id), "local-exec")
+ && strcmp (TREE_STRING_POINTER (id), "initial-exec")
+ && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
+ && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
{
- error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
+ error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
*no_add_attrs = true;
return NULL_TREE;
}
The normal mechanism to prevent duplicates is to use type_hash_canon, but
since we want to distinguish types that are essentially identical (except
for their debug representation), we use a local list here. */
-static tree vector_type_node_list = 0;
+static GTY(()) tree vector_type_node_list = 0;
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
unsigned HOST_WIDE_INT attr_arg_num;
/* If no arguments are specified, all pointer arguments should be
- non-null. Veryify a full prototype is given so that the arguments
+ non-null. Verify a full prototype is given so that the arguments
will have the correct types when we actually check them later. */
if (! args)
{