int flag_gen_declaration;
-/* Generate code for GNU or NeXT runtime environment. */
-
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
-
/* Tells the compiler that this is a special run. Do not perform any
compiling, instead we are to test some platform dependent features
and output a C header file with appropriate definitions. */
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int,
bool *);
+static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
static tree handle_used_attribute (tree *, tree, tree, int, bool *);
static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
static tree handle_externally_visible_attribute (tree *, tree, tree, int,
handle_noinline_attribute },
{ "always_inline", 0, 0, true, false, false,
handle_always_inline_attribute },
+ { "flatten", 0, 0, true, false, false,
+ handle_flatten_attribute },
{ "used", 0, 0, true, false, false,
handle_used_attribute },
{ "unused", 0, 0, false, false, false,
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
}
\f
-static tree builtin_function_2 (const char *builtin_name, const char *name,
- tree builtin_type, tree type,
- enum built_in_function function_code,
- enum built_in_class cl, int library_name_p,
- bool nonansi_p,
- tree attrs);
+static void def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p);
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+ NAME,
#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_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+ NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
#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_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_POINTER_TYPE
BT_LAST
};
tree_cons (NULL_TREE, \
builtin_types[(int) ARG4], \
void_list_node)))));
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ 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], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG4], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG5],\
+ void_list_node))))));
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) \
+ 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], \
+ tree_cons \
+ (NULL_TREE, \
+ builtin_types[(int) ARG4], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG5], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG6],\
+ void_list_node)))))));
#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
builtin_types[(int) ENUM] \
= build_function_type (builtin_types[(int) RETURN], NULL_TREE);
builtin_types[(int) ARG3], \
NULL_TREE))));
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ 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], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG4],\
+ NULL_TREE)))));
+
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, \
+ ARG5) \
+ 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], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG4], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG5],\
+ NULL_TREE))))));
+
#define DEF_POINTER_TYPE(ENUM, TYPE) \
builtin_types[(int) ENUM] \
= build_pointer_type (builtin_types[(int) TYPE]);
#undef DEF_FUNCTION_TYPE_2
#undef DEF_FUNCTION_TYPE_3
#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
#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_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
#undef DEF_POINTER_TYPE
c_init_attributes ();
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
NONANSI_P, ATTRS, IMPLICIT, COND) \
if (NAME && COND) \
- { \
- tree decl; \
- \
- gcc_assert ((!BOTH_P && !FALLBACK_P) \
- || !strncmp (NAME, "__builtin_", \
- strlen ("__builtin_"))); \
- \
- if (!BOTH_P) \
- decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE], \
- ENUM, \
- CLASS, \
- (FALLBACK_P \
- ? (NAME + strlen ("__builtin_")) \
- : NULL), \
- built_in_attributes[(int) ATTRS]); \
- else \
- decl = builtin_function_2 (NAME, \
- NAME + strlen ("__builtin_"), \
- builtin_types[TYPE], \
- builtin_types[LIBTYPE], \
- ENUM, \
- CLASS, \
- FALLBACK_P, \
- NONANSI_P, \
- built_in_attributes[(int) ATTRS]); \
- \
- built_in_decls[(int) ENUM] = decl; \
- if (IMPLICIT) \
- implicit_built_in_decls[(int) ENUM] = decl; \
- }
+ def_builtin_1 (ENUM, NAME, CLASS, \
+ builtin_types[(int) TYPE], \
+ builtin_types[(int) LIBTYPE], \
+ BOTH_P, FALLBACK_P, NONANSI_P, \
+ built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
#undef DEF_BUILTIN
}
-/* Possibly define a builtin function with one or two names. BUILTIN_NAME
- is an __builtin_-prefixed name; NAME is the ordinary name; one or both
- of these may be NULL (though both being NULL is useless).
- BUILTIN_TYPE is the type of the __builtin_-prefixed function;
- TYPE is the type of the function with the ordinary name. These
- may differ if the ordinary name is declared with a looser type to avoid
- conflicts with headers. FUNCTION_CODE and CL are as for
- builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as
- the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
- If NONANSI_P is true, the name NAME is treated as a non-ANSI name;
- ATTRS is the tree list representing the builtin's function attributes.
- Returns the declaration of BUILTIN_NAME, if any, otherwise
- the declaration of NAME. Does not declare NAME if flag_no_builtin,
- or if NONANSI_P and flag_no_nonansi_builtin. */
+/* Worker for DEF_BUILTIN.
+ Possibly define a builtin function with one or two names.
+ Does not declare a non-__builtin_ function if flag_no_builtin, or if
+ nonansi_p and flag_no_nonansi_builtin. */
-static tree
-builtin_function_2 (const char *builtin_name, const char *name,
- tree builtin_type, tree type,
- enum built_in_function function_code,
- enum built_in_class cl, int library_name_p,
- bool nonansi_p, tree attrs)
+static void
+def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p)
{
- tree bdecl = NULL_TREE;
- tree decl = NULL_TREE;
-
- if (builtin_name != 0)
- bdecl = lang_hooks.builtin_function (builtin_name, builtin_type,
- function_code, cl,
- library_name_p ? name : NULL, attrs);
-
- if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
+ tree decl;
+ const char *libname;
+
+ gcc_assert ((!both_p && !fallback_p)
+ || !strncmp (name, "__builtin_",
+ strlen ("__builtin_")));
+
+ libname = name + strlen ("__builtin_");
+ decl = lang_hooks.builtin_function (name, fntype, fncode, fnclass,
+ (fallback_p ? libname : NULL),
+ fnattrs);
+ if (both_p
+ && !flag_no_builtin && !builtin_function_disabled_p (libname)
&& !(nonansi_p && flag_no_nonansi_builtin))
- decl = lang_hooks.builtin_function (name, type, function_code, cl,
- NULL, attrs);
+ lang_hooks.builtin_function (libname, libtype, fncode, fnclass,
+ NULL, fnattrs);
- return (bdecl != 0 ? bdecl : decl);
+ built_in_decls[(int) fncode] = decl;
+ if (implicit_p)
+ implicit_built_in_decls[(int) fncode] = decl;
}
\f
/* Nonzero if the type T promotes to int. This is (nearly) the
return NULL_TREE;
}
+/* Handle a "flatten" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_flatten_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Handle a "used" attribute; arguments as in
struct attribute_spec.handler. */
&& strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
{
- error ("%Jsection of %qD conflicts with previous declaration",
- *node, *node);
+ error ("section of %q+D conflicts with previous declaration",
+ *node);
*no_add_attrs = true;
}
else
}
else
{
- error ("%Jsection attribute not allowed for %qD", *node, *node);
+ error ("section attribute not allowed for %q+D", *node);
*no_add_attrs = true;
}
}
else if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FIELD_DECL)
{
- error ("%Jalignment may not be specified for %qD", decl, decl);
+ error ("alignment may not be specified for %q+D", decl);
*no_add_attrs = true;
}
else
if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
|| (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl)))
{
- error ("%J%qD defined both normally and as an alias", decl, decl);
+ error ("%q+D defined both normally and as an alias", decl);
*no_add_attrs = true;
}
handle_tls_model_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags), bool *no_add_attrs)
{
+ tree id;
tree decl = *node;
+ enum tls_model kind;
- if (!DECL_THREAD_LOCAL (decl))
+ *no_add_attrs = true;
+
+ if (!DECL_THREAD_LOCAL_P (decl))
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
- *no_add_attrs = true;
+ return NULL_TREE;
}
- else
- {
- tree id;
- id = TREE_VALUE (args);
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("tls_model argument 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 ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
- *no_add_attrs = true;
- return NULL_TREE;
- }
+ kind = DECL_TLS_MODEL (decl);
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("tls_model argument not a string");
+ return NULL_TREE;
}
+ if (!strcmp (TREE_STRING_POINTER (id), "local-exec"))
+ kind = TLS_MODEL_LOCAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec"))
+ kind = TLS_MODEL_INITIAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic"))
+ kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
+ else if (!strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+ kind = TLS_MODEL_GLOBAL_DYNAMIC;
+ else
+ error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
+
+ DECL_TLS_MODEL (decl) = kind;
return NULL_TREE;
}
from the end) is a (pointer)0. */
static void
-check_function_sentinel (tree attrs, tree params)
+check_function_sentinel (tree attrs, tree params, tree typelist)
{
tree attr = lookup_attribute ("sentinel", attrs);
if (attr)
{
- if (!params)
- warning (0, "missing sentinel in function call");
+ /* Skip over the named arguments. */
+ while (typelist && params)
+ {
+ typelist = TREE_CHAIN (typelist);
+ params = TREE_CHAIN (params);
+ }
+
+ if (typelist || !params)
+ warning (OPT_Wformat,
+ "not enough variable arguments to fit a sentinel");
else
{
tree sentinel, end;
}
if (pos > 0)
{
- warning (0, "not enough arguments to fit a sentinel");
+ warning (OPT_Wformat,
+ "not enough variable arguments to fit a sentinel");
return;
}
We warn with -Wstrict-null-sentinel, though. */
&& (warn_strict_null_sentinel
|| null_node != TREE_VALUE (sentinel)))
- warning (0, "missing sentinel in function call");
+ warning (OPT_Wformat, "missing sentinel in function call");
}
}
}
return;
if (integer_zerop (param))
- warning (0, "null argument where non-null required (argument %lu)",
- (unsigned long) param_num);
+ warning (OPT_Wnonnull, "null argument where non-null required "
+ "(argument %lu)", (unsigned long) param_num);
}
/* Helper for nonnull attribute handling; fetch the operand number
\f
/* Check for valid arguments being passed to a function. */
void
-check_function_arguments (tree attrs, tree params)
+check_function_arguments (tree attrs, tree params, tree typelist)
{
/* Check for null being passed in a pointer argument that must be
non-null. We also need to do this if format checking is enabled. */
/* Check for errors in format strings. */
- if (warn_format)
- {
+ if (warn_format || warn_missing_format_attribute)
check_function_format (attrs, params);
- check_function_sentinel (attrs, params);
- }
+
+ if (warn_format)
+ check_function_sentinel (attrs, params, typelist);
}
/* Generic argument checking recursion routine. PARAM is the argument to
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
- tree elts = CONSTRUCTOR_ELTS (initial_value);
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
- if (elts == NULL)
+ if (VEC_empty (constructor_elt, v))
{
if (pedantic)
failure = 3;
else
{
tree curindex;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
- if (TREE_PURPOSE (elts))
- maxindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+ if (VEC_index (constructor_elt, v, 0)->index)
+ maxindex = fold_convert (sizetype,
+ VEC_index (constructor_elt,
+ v, 0)->index);
curindex = maxindex;
- for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts))
+ for (cnt = 1;
+ VEC_iterate (constructor_elt, v, cnt, ce);
+ cnt++)
{
- if (TREE_PURPOSE (elts))
- curindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+ if (ce->index)
+ curindex = fold_convert (sizetype, ce->index);
else
curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
== lang_hooks.types.signed_type (t2);
}
+/* Check for missing format attributes on function pointers. LTYPE is
+ the new type or left-hand side type. RTYPE is the old type or
+ right-hand side type. Returns TRUE if LTYPE is missing the desired
+ attribute. */
+
+bool
+check_missing_format_attribute (tree ltype, tree rtype)
+{
+ tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+ tree ra;
+
+ for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+ if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+ break;
+ if (ra)
+ {
+ tree la;
+ for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+ if (is_attribute_p ("format", TREE_PURPOSE (la)))
+ break;
+ return !la;
+ }
+ else
+ return false;
+}
+
#include "gt-c-common.h"