#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"
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;
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 *));
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));
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 *
}
if (!ix && !current_function_decl)
pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
-
+
return decl;
}
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:
case ABS_EXPR:
case FLOAT_EXPR:
case FFS_EXPR:
+ case POPCOUNT_EXPR:
/* These don't change whether an object is nonzero or zero. */
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
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
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
-/* Define macros necessary to describe fundamental data type formats. */
-static void
-cpp_define_data_format (pfile)
- cpp_reader *pfile;
-{
- 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();
- }
-
- builtin_define_with_value ("__GCC_FLOAT_FORMAT__", format, 0);
-}
-
/* Define NAME with value TYPE precision. */
static void
builtin_define_type_precision (name, type)
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. */
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);
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. */
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 (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__");
then print it back out as decimal. */
real_from_string (&real, hex_str);
- real_to_decimal (dec_str, &real, digits);
+ real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
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". */
+/* 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. */
static void
builtin_define_type_max (macro, type, is_long)
tree type;
int is_long;
{
- const char *value;
+ 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 mlen, vlen, extra;
+ size_t idx;
/* 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 ();
+ 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 ();
}
- mlen = strlen (macro);
- vlen = strlen (value);
- extra = 2 + is_long;
- buf = alloca (mlen + vlen + extra);
+ value = values[idx + TREE_UNSIGNED (type)];
+ suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)];
- sprintf (buf, "%s=%s%s", macro, value,
- (is_long == 1 ? "L" : is_long == 2 ? "LL" : ""));
+ buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1);
+ sprintf (buf, "%s=%s%s", macro, value, suffix);
cpp_define (parse_in, buf);
}
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)
{