static void signal_catch PARAMS ((int)) ATTRIBUTE_NORETURN;
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
-static void push_overloaded_decl_1 PARAMS ((tree));
static int ambi_op_p PARAMS ((tree));
static int unary_op_p PARAMS ((tree));
static tree store_bindings PARAMS ((tree, tree));
PARAMS ((tree, tree, struct binding_level *));
static void record_builtin_type PARAMS ((enum rid, const char *, tree));
static void record_unknown_type PARAMS ((tree, const char *));
+static tree build_library_fn_1 PARAMS ((tree, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
int));
static tree get_dso_handle_node PARAMS ((void));
static tree start_cleanup_fn PARAMS ((void));
static void end_cleanup_fn PARAMS ((void));
+static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PARAMS ((void));
Put them into VEC from back to front, then take out from front. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[len - i - 1] = decl;
+ {
+ /* Pretend we've output an unused static variable. This ensures
+ that the toplevel __FUNCTION__ etc won't be emitted, unless
+ needed. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)
+ && !TREE_PUBLIC (decl) && !TREE_USED (decl))
+ {
+ TREE_ASM_WRITTEN (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ }
+ vec[len - i - 1] = decl;
+ }
if (last_time)
{
TYPE_MODE (type) = TYPE_MODE (void_type_node);
}
-/* Push overloaded decl, in global scope, with one argument so it
- can be used as a callback from define_function. */
-
-static void
-push_overloaded_decl_1 (x)
- tree x;
-{
- pushdecl (x);
-}
-
-inline tree
-auto_function (name, type)
- tree name, type;
-{
- return define_function
- (IDENTIFIER_POINTER (name), type, push_overloaded_decl_1,
- IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
- 0)));
-}
-
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *)0).
Initialize the global binding level.
boolean_true_node = build_int_2 (1, 0);
TREE_TYPE (boolean_true_node) = boolean_type_node;
- signed_size_zero_node = build_int_2 (0, 0); record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
+ signed_size_zero_node = build_int_2 (0, 0);
+ record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
record_builtin_type (RID_DOUBLE, NULL_PTR, double_type_node);
record_builtin_type (RID_MAX, "long double", long_double_type_node);
/* Make a type to be the domain of a few array types
whose domains don't really matter.
- 200 is small enough that it always fits in size_t
- and large enough that it can hold most function names for the
- initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
+ 200 is small enough that it always fits in size_t. */
array_domain_type = build_index_type (build_int_2 (200, 0));
/* Make a type for arrays of characters.
newtype = build_exception_variant
(ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
- auto_function (ansi_opname[(int) NEW_EXPR], newtype);
- auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype);
- global_delete_fndecl = auto_function (ansi_opname[(int) DELETE_EXPR],
- deltype);
- auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
+ push_cp_library_fn (ansi_opname[(int) NEW_EXPR], newtype);
+ push_cp_library_fn (ansi_opname[(int) VEC_NEW_EXPR], newtype);
+ global_delete_fndecl = push_cp_library_fn (ansi_opname[(int) DELETE_EXPR],
+ deltype);
+ push_cp_library_fn (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
}
abort_fndecl
- = define_function ("__pure_virtual", void_ftype, 0, 0);
+ = build_library_fn_ptr ("__pure_virtual", void_ftype);
/* Perform other language dependent initializations. */
init_class_processing ();
flag_weak = 0;
/* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
+ make_fname_decl = cp_make_fname_decl;
declare_function_name ();
/* Prepare to check format strings against argument lists. */
ggc_add_tree_root (&static_aggregates, 1);
}
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+ decl, NAME is the initialization string and TYPE_DEP indicates whether
+ NAME depended on the type of the function. We make use of that to detect
+ __PRETTY_FUNCTION__ inside a template fn. Because we build a tree for
+ the function before emitting any of it, we don't need to treat the
+ VAR_DECL specially. We can decide whether to emit it later, if it was
+ used. */
+
+static tree
+cp_make_fname_decl (id, name, type_dep)
+ tree id;
+ const char *name;
+ int type_dep;
+{
+ tree decl, type, init;
+ size_t length = strlen (name);
+ tree domain = NULL_TREE;
+
+ if (!processing_template_decl)
+ type_dep = 0;
+ if (!type_dep)
+ domain = build_index_type (build_int_2 (length, 0));
+
+ type = build_cplus_array_type
+ (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
+ domain);
+
+ decl = build_lang_decl (VAR_DECL, id, type);
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ DECL_SOURCE_LINE (decl) = 0;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IN_SYSTEM_HEADER (decl) = 1;
+ pushdecl (decl);
+ if (processing_template_decl)
+ decl = push_template_decl (decl);
+ if (type_dep)
+ {
+ init = build (FUNCTION_NAME, type);
+ DECL_PRETTY_FUNCTION_P (decl) = 1;
+ }
+ else
+ {
+ init = build_string (length + 1, name);
+ TREE_TYPE (init) = type;
+ }
+ DECL_INITIAL (decl) = init;
+ cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+
+ /* We will have to make sure we only emit this, if it is actually used. */
+ return decl;
+}
+
/* Function to print any language-specific context for an error message. */
static void
maybe_print_template_context ();
}
-/* Make a definition for a builtin function named NAME and whose data type
+/* Entry point for the benefit of c_common_nodes_and_builtins.
+
+ Make a definition for a builtin function named NAME and whose data type
is TYPE. TYPE should be a function type with argument types.
- If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+ CLASS and CODE tell later passes how to compile calls to this function.
+ See tree.h for possible values.
+
+ If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
the name to be called if we can't opencode the function. */
tree
-define_function (name, type, pfn, library_name)
+builtin_function (name, type, code, class, libname)
const char *name;
tree type;
- void (*pfn) PARAMS ((tree));
- const char *library_name;
+ int code;
+ enum built_in_class class;
+ const char *libname;
{
- tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
- DECL_ARTIFICIAL (decl) = 1;
+ tree decl = build_library_fn_1 (get_identifier (name), type);
+ DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_FUNCTION_CODE (decl) = code;
my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
- DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
we cannot change DECL_ASSEMBLER_NAME until we have installed this
function in the namespace. */
- if (pfn) (*pfn) (decl);
- if (library_name)
- DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
+ pushdecl (decl);
+ if (libname)
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (libname);
make_function_rtl (decl);
return decl;
}
+/* Generate a FUNCTION_DECL with the typical flags for a runtime library
+ function. Not called directly. */
+
+static tree
+build_library_fn_1 (name, type)
+ tree name;
+ tree type;
+{
+ tree fn = build_lang_decl (FUNCTION_DECL, name, type);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ TREE_NOTHROW (fn) = 1;
+ return fn;
+}
-/* Wrapper around define_function, for the benefit of
- c_common_nodes_and_builtins.
- FUNCTION_CODE tells later passes how to compile calls to this function.
- See tree.h for its possible values. */
+/* Returns the _DECL for a library function with C linkage.
+ We assume that such functions never throw; if this is incorrect,
+ callers should unset TREE_NOTHROW. */
tree
-builtin_function (name, type, code, class, libname)
+build_library_fn (name, type)
+ tree name;
+ tree type;
+{
+ tree fn = build_library_fn_1 (name, type);
+ make_function_rtl (fn);
+ return fn;
+}
+
+/* Returns the _DECL for a library function with C++ linkage. */
+
+tree
+build_cp_library_fn (name, type)
+ tree name;
+ tree type;
+{
+ tree fn = build_library_fn_1 (name, type);
+ TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
+ set_mangled_name_for_decl (fn);
+ make_function_rtl (fn);
+ return fn;
+}
+
+/* Like build_library_fn, but takes a C string instead of an
+ IDENTIFIER_NODE. */
+
+tree
+build_library_fn_ptr (name, type)
const char *name;
tree type;
- int code;
- enum built_in_class class;
- const char *libname;
{
- tree decl = define_function (name, type, (void (*) PARAMS ((tree)))pushdecl,
- libname);
- DECL_BUILT_IN_CLASS (decl) = class;
- DECL_FUNCTION_CODE (decl) = code;
- return decl;
+ return build_library_fn (get_identifier (name), type);
+}
+
+/* Like build_cp_library_fn, but takes a C string instead of an
+ IDENTIFIER_NODE. */
+
+tree
+build_cp_library_fn_ptr (name, type)
+ const char *name;
+ tree type;
+{
+ return build_cp_library_fn (get_identifier (name), type);
+}
+
+/* Like build_library_fn, but also pushes the function so that we will
+ be able to find it via IDENTIFIER_GLOBAL_VALUE. */
+
+tree
+push_library_fn (name, type)
+ tree name, type;
+{
+ tree fn = build_library_fn (name, type);
+ pushdecl_top_level (fn);
+ return fn;
+}
+
+/* Like build_cp_library_fn, but also pushes the function so that it
+ will be found by normal lookup. */
+
+tree
+push_cp_library_fn (name, type)
+ tree name;
+ tree type;
+{
+ tree fn = build_cp_library_fn (name, type);
+ pushdecl (fn);
+ return fn;
+}
+
+/* Like push_library_fn, but takes a TREE_LIST of parm types rather than
+ a FUNCTION_TYPE. */
+
+tree
+push_void_library_fn (name, parmtypes)
+ tree name, parmtypes;
+{
+ tree type = build_function_type (void_type_node, parmtypes);
+ return push_library_fn (name, type);
+}
+
+/* Like push_library_fn, but also note that this function throws
+ and does not return. Used for __throw_foo and the like. */
+
+tree
+push_throw_library_fn (name, type)
+ tree name, type;
+{
+ tree fn = push_library_fn (name, type);
+ TREE_THIS_VOLATILE (fn) = 1;
+ TREE_NOTHROW (fn) = 0;
+ return fn;
}
\f
/* When we call finish_struct for an anonymous union, we create
linkage. */
if (TREE_STATIC (decl)
/* Don't mess with __FUNCTION__. */
- && ! TREE_ASM_WRITTEN (decl)
+ && ! DECL_ARTIFICIAL (decl)
&& current_function_decl
&& DECL_CONTEXT (decl) == current_function_decl
&& (DECL_THIS_INLINE (current_function_decl)
if (TREE_PUBLIC (decl))
DECL_ASSEMBLER_NAME (decl)
= build_static_name (current_function_decl, DECL_NAME (decl));
- else if (! DECL_ARTIFICIAL (decl))
+ else
{
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
cp_warning_at (" you can work around this by removing the initializer", decl);
return;
}
- /* Handling __FUNCTION__ and its ilk in a template-function requires
- some special processing because we are called from
- language-independent code. */
- if (cfun && processing_template_decl
- && current_function_name_declared == 2)
- {
- /* Since we're in a template function, we need to
- push_template_decl. The language-independent code in
- declare_hidden_char_array doesn't know to do this. */
- retrofit_lang_decl (decl);
- decl = push_template_decl (decl);
-
- if (strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
- "__PRETTY_FUNCTION__") == 0)
- {
- init = build (FUNCTION_NAME, const_string_type_node);
- DECL_PRETTY_FUNCTION_P (decl) = 1;
- }
- }
-
/* If a name was specified, get the string. */
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
/* Now, build the function declaration. */
push_lang_context (lang_name_c);
- atexit_fndecl = define_function (name, fn_type, /*pfn=*/0, NULL_PTR);
+ atexit_fndecl = build_library_fn_ptr (name, fn_type);
mark_used (atexit_fndecl);
pop_lang_context ();
atexit_node = default_conversion (atexit_fndecl);
tentative. error_mark_node is replaced later with the BLOCK. */
DECL_INITIAL (decl) = error_mark_node;
+ if (nothrow_libfn_p (decl))
+ TREE_NOTHROW (decl) = 1;
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
- if (TREE_CODE (t) == VOID_TYPE)
- pedwarn ("void is not a valid type conversion operator");
- else if (! friendp)
+ if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
const char *what = 0;
+
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
- if (t == current_class_type)
+ if (TREE_CODE (t) == VOID_TYPE)
+ what = "void";
+ else if (t == current_class_type)
what = "the same type";
/* Don't force t to be complete here. */
else if (IS_AGGR_TYPE (t)
/* Do the starting of the exception specifications, if we have any. */
if (flag_exceptions && !processing_template_decl
+ && flag_enforce_eh_specs
&& building_stmt_tree ()
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
current_eh_spec_try_block = expand_start_eh_spec ();
/* Finish dealing with exception specifiers. */
if (flag_exceptions && !processing_template_decl
+ && flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),