Commit 2ce3c6c6 by Jason Merrill Committed by Jason Merrill

tree.h: De-conditionalize init_priority code.

	* tree.h: De-conditionalize init_priority code.
	* mips.h (NM_FLAGS): Change from -Bp to -Bn.
	* collect2.c (NM_FLAGS): Change from -p to -n.
	* configure.in: Turn on collect2 for mipstx39-elf.
	Handle use_collect2=no properly.
	* c-common.c: De-conditionalize init_priority code.
	* collect2.c (extract_init_priority, sort_ids): New fns.
	(main): Call sort_ids.
	Move sequence_number to file scope.
	* configure.in: Handle --enable-init-priority.
	* c-common.c (attrs): Add A_INIT_PRIORITY.
	(init_attributes, decl_attributes): Likewise.
	* tree.h (DEFAULT_INIT_PRIORITY, MAX_INIT_PRIORITY): New macros.
	* tree.c (get_file_function_name_long): Split out...
	(get_file_function_name): ...from here.
cp/:
	* lang-options.h: Add -finit-priority.
	* decl2.c: Likewise.  Check flag_init_priority instead of
	USE_INIT_PRIORITY.
	* decl2.c (setup_initp): New fn.
	(start_objects, finish_objects, do_ctors): Handle init_priority.
	(do_dtors, finish_file): Likewise.

From-SVN: r21701
parent db04386f
Thu Aug 13 17:08:11 1998 Jason Merrill <jason@yorick.cygnus.com>
* tree.h: De-conditionalize init_priority code.
* mips.h (NM_FLAGS): Change from -Bp to -Bn.
* collect2.c (NM_FLAGS): Change from -p to -n.
* configure.in: Turn on collect2 for mipstx39-elf.
Handle use_collect2=no properly.
* c-common.c: De-conditionalize init_priority code.
* collect2.c (extract_init_priority, sort_ids): New fns.
(main): Call sort_ids.
Move sequence_number to file scope.
* configure.in: Handle --enable-init-priority.
* c-common.c (attrs): Add A_INIT_PRIORITY.
(init_attributes, decl_attributes): Likewise.
* tree.h (DEFAULT_INIT_PRIORITY, MAX_INIT_PRIORITY): New macros.
* tree.c (get_file_function_name_long): Split out...
(get_file_function_name): ...from here.
Thu Aug 13 16:09:53 1998 Martin von Loewis <loewis@informatik.hu-berlin.de>
* expr.c (safe_from_p): Change code to ERROR_MARK only when not
......
......@@ -52,7 +52,8 @@ int skip_evaluation;
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
A_NO_INSTRUMENT_FUNCTION,
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS,
A_INIT_PRIORITY};
enum format_type { printf_format_type, scanf_format_type,
strftime_format_type };
......@@ -89,6 +90,12 @@ static int if_stack_pointer = 0;
/* Generate RTL for the start of an if-then, and record the start of it
for ambiguous else detection. */
/* A list of objects which have constructors or destructors which
reside in the global scope, and have an init_priority attribute
associated with them. The decl is stored in the TREE_VALUE slot
and the priority number is stored in the TREE_PURPOSE slot. */
tree static_aggregates_initp;
void
c_expand_start_cond (cond, exitflag, compstmt_count)
tree cond;
......@@ -383,6 +390,7 @@ init_attributes ()
add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);
add_attribute (A_WEAK, "weak", 0, 0, 1);
add_attribute (A_ALIAS, "alias", 1, 1, 1);
add_attribute (A_INIT_PRIORITY, "init_priority", 0, 1, 0);
add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
}
......@@ -859,6 +867,62 @@ decl_attributes (node, attributes, prefix_attributes)
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
break;
case A_INIT_PRIORITY:
{
tree initp_expr = (args ? TREE_VALUE (args): NULL_TREE);
int pri;
if (initp_expr)
STRIP_NOPS (initp_expr);
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
{
error ("requested init_priority is not an integer constant");
continue;
}
pri = TREE_INT_CST_LOW (initp_expr);
if (is_type || TREE_CODE (decl) != VAR_DECL
|| ! TREE_STATIC (decl)
|| DECL_EXTERNAL (decl)
|| (TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
&& TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
/* Static objects in functions are initialized the
first time control passes through that
function. This is not precise enough to pin down an
init_priority value, so don't allow it. */
|| current_function_decl)
{
error ("can only use init_priority attribute on file-scope definitions of objects of class type");
continue;
}
/* Check for init_priorities that are reserved for
implementation. Reserved for language and runtime
support implementations.*/
if ((10 <= pri && pri <= 99)
/* Reserved for standard library implementations. */
|| (500 <= pri && pri <= 999)
/* Reserved for objects with no attributes. */
|| pri > (MAX_INIT_PRIORITY - 50))
{
warning
("requested init_priority is reserved for internal use");
continue;
}
if (pri > MAX_INIT_PRIORITY || pri <= 0)
{
error ("requested init_priority is out of range");
continue;
}
static_aggregates_initp
= perm_tree_cons (initp_expr, decl, static_aggregates_initp);
break;
}
case A_NO_INSTRUMENT_FUNCTION:
if (TREE_CODE (decl) != FUNCTION_DECL)
{
......
......@@ -137,7 +137,7 @@ extern char *make_temp_file PROTO ((char *));
/* Default flags to pass to nm. */
#ifndef NM_FLAGS
#define NM_FLAGS "-p"
#define NM_FLAGS "-n"
#endif
#endif /* OBJECT_FORMAT_NONE */
......@@ -280,6 +280,8 @@ static void do_wait PROTO((char *));
static void fork_execute PROTO((char *, char **));
static void maybe_unlink PROTO((char *));
static void add_to_list PROTO((struct head *, char *));
static int extract_init_priority PROTO((char *));
static void sort_ids PROTO((struct head *));
static void write_list PROTO((FILE *, char *, struct id *));
#ifdef COLLECT_EXPORT_LIST
static void dump_list PROTO((FILE *, char *, struct id *));
......@@ -1483,6 +1485,10 @@ main (argc, argv)
return 0;
}
/* Sort ctor and dtor lists by priority. */
sort_ids (&constructors);
sort_ids (&destructors);
maybe_unlink(output_file);
outf = fopen (c_file, "w");
if (outf == (FILE *) 0)
......@@ -1697,6 +1703,8 @@ maybe_unlink (file)
}
static long sequence_number = 0;
/* Add a name to a linked list. */
static void
......@@ -1707,7 +1715,6 @@ add_to_list (head_ptr, name)
struct id *newid
= (struct id *) xcalloc (sizeof (struct id) + strlen (name), 1);
struct id *p;
static long sequence_number = 0;
strcpy (newid->name, name);
if (head_ptr->first)
......@@ -1732,6 +1739,67 @@ add_to_list (head_ptr, name)
head_ptr->number++;
}
/* Grab the init priority number from an init function name that
looks like "_GLOBAL_.I.12345.foo". */
static int
extract_init_priority (name)
char *name;
{
int pos = 0;
while (name[pos] == '_')
++pos;
pos += 10; /* strlen ("GLOBAL__X_") */
/* Extract init_p number from ctor/dtor name. */
return strtoul(name + pos, NULL, 10);
}
/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order.
ctors will be run from right to left, dtors from left to right. */
static void
sort_ids (head_ptr)
struct head *head_ptr;
{
/* id holds the current element to insert. id_next holds the next
element to insert. id_ptr iterates through the already sorted elements
looking for the place to insert id. */
struct id *id, *id_next, **id_ptr;
int i;
id = head_ptr->first;
/* We don't have any sorted elements yet. */
head_ptr->first = NULL;
for (; id; id = id_next)
{
id_next = id->next;
id->sequence = extract_init_priority (id->name);
for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next))
if (*id_ptr == NULL
/* If the sequence numbers are the same, we put the id from the
file later on the command line later in the list. */
|| id->sequence > (*id_ptr)->sequence
/* Hack: do lexical compare, too.
|| (id->sequence == (*id_ptr)->sequence
&& strcmp (id->name, (*id_ptr)->name) > 0) */
)
{
id->next = *id_ptr;
*id_ptr = id;
break;
}
}
/* Now set the sequence numbers properly so write_c_file works. */
for (id = head_ptr->first; id; id = id->next)
id->sequence = ++sequence_number;
}
/* Write: `prefix', the names on list LIST, `suffix'. */
static void
......
......@@ -716,7 +716,7 @@ while (0)
/* Tell collect what flags to pass to nm. */
#ifndef NM_FLAGS
#define NM_FLAGS "-Bp"
#define NM_FLAGS "-Bn"
#endif
......
......@@ -130,6 +130,16 @@ AC_ARG_WITH(fast-fixincludes,
fast_fixinc="$with_fast_fixincludes",
fast_fixinc=no)
# Enable init_priority.
AC_ARG_ENABLE(init-priority,
[ --enable-init-priority Use attributes to assign initialization order
for static objects.
--disable-init-priority Conform to ISO C++ rules for ordering static objects
(i.e. initialized in order of declaration). ],
if [[[ x$enable_init_priority != xno ]]]; then
extra_c_flags=-DUSE_INIT_PRIORITY
fi)
# Enable threads
# Pass with no value to take the default
# Pass with a value to specify a thread package
......@@ -2231,6 +2241,8 @@ for machine in $build $host $target; do
mipstx39-*-elf*)
tm_file="mips/r3900.h mips/elf.h mips/abi64.h libgloss.h"
tmake_file=mips/t-r3900
# FIXME mips-elf should be fixed to use crtstuff.
use_collect2=yes
;;
mips-*-*) # Default MIPS RISC-OS 4.0.
if [[ x$stabs = xyes ]]; then
......@@ -3323,6 +3335,10 @@ else
done
fi
if [[ x$use_collect2 = xno ]]; then
use_collect2=
fi
# Add a definition of USE_COLLECT2 if system wants one.
# Also tell toplev.c what to do.
# This substitutes for lots of t-* files.
......@@ -3610,6 +3626,13 @@ if [[ x$enable_haifa != x ]]; then
done
fi
# Warn if using init_priority.
AC_MSG_CHECKING(whether to enable init_priority by default)
if [[ x$enable_init_priority != xyes ]]; then
enable_init_priority=no
fi
AC_MSG_RESULT($enable_init_priority)
# Nothing to do for FLOAT_H, float_format already handled.
objdir=`pwd`
AC_SUBST(objdir)
......
1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
* lang-options.h: Add -finit-priority.
* decl2.c: Likewise. Check flag_init_priority instead of
USE_INIT_PRIORITY.
* decl2.c (setup_initp): New fn.
(start_objects, finish_objects, do_ctors): Handle init_priority.
(do_dtors, finish_file): Likewise.
1998-08-13 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst_copy): Hush warning.
* rtti.c (get_tinfo_fn): Also set DECL_IGNORED_P.
......
......@@ -173,6 +173,14 @@ int flag_alt_external_templates;
int flag_implicit_templates = 1;
/* Nonzero means allow numerical priorities on constructors. */
#ifdef USE_INIT_PRIORITY
int flag_init_priority = 1;
#else
int flag_init_priority;
#endif
/* Nonzero means warn about implicit declarations. */
int warn_implicit = 1;
......@@ -492,6 +500,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"implement-inlines", &flag_implement_inlines, 1},
{"external-templates", &flag_external_templates, 1},
{"implicit-templates", &flag_implicit_templates, 1},
{"init-priority", &flag_init_priority, 1},
{"huge-objects", &flag_huge_objects, 1},
{"conserve-space", &flag_conserve_space, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
......@@ -2929,18 +2938,104 @@ get_sentry (base)
return sentry;
}
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
the TREE_VALUE slot and the initializer is stored
in the TREE_PURPOSE slot. */
extern tree static_aggregates_initp;
/* Set up the static_aggregates* lists for processing. Subroutine of
finish_file. Note that this function changes the format of
static_aggregates_initp, from (priority . decl) to
(priority . ((initializer . decl) ...)). */
static void
setup_initp ()
{
tree t, *p, next_t;
if (! flag_init_priority)
{
for (t = static_aggregates_initp; t; t = TREE_CHAIN (t))
cp_warning ("init_priority for `%#D' ignored without -finit-priority",
TREE_VALUE (t));
return;
}
/* First, remove any entries from static_aggregates that are also in
static_aggregates_initp, and update the entries in _initp to
include the initializer. */
p = &static_aggregates;
for (; *p; )
{
t = value_member (TREE_VALUE (*p), static_aggregates_initp);
if (t)
{
TREE_VALUE (t) = *p;
*p = TREE_CHAIN (*p);
TREE_CHAIN (TREE_VALUE (t)) = NULL_TREE;
}
else
p = &TREE_CHAIN (*p);
}
/* Then, group static_aggregates_initp. After this step, there will only
be one entry for each priority, with a chain coming off it. */
t = static_aggregates_initp;
static_aggregates_initp = NULL_TREE;
for (; t; t = next_t)
{
next_t = TREE_CHAIN (t);
for (p = &static_aggregates_initp; ; p = &TREE_CHAIN (*p))
{
if (*p == NULL_TREE
|| tree_int_cst_lt (TREE_PURPOSE (*p), TREE_PURPOSE (t)))
{
TREE_CHAIN (t) = *p;
*p = t;
break;
}
else if (tree_int_cst_equal (TREE_PURPOSE (*p), TREE_PURPOSE (t)))
{
TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (*p);
TREE_VALUE (*p) = TREE_VALUE (t);
break;
}
}
}
/* Reverse each list to preserve the order (currently reverse declaration
order, for destructors). */
for (t = static_aggregates_initp; t; t = TREE_CHAIN (t))
TREE_VALUE (t) = nreverse (TREE_VALUE (t));
}
/* Start the process of running a particular set of global constructors
or destructors. Subroutine of do_[cd]tors. */
static void
start_objects (method_type)
int method_type;
start_objects (method_type, initp)
int method_type, initp;
{
tree fnname;
char type[10];
/* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
fnname = get_file_function_name (method_type);
if (flag_init_priority)
{
if (initp == 0)
initp = DEFAULT_INIT_PRIORITY;
sprintf (type, "%c%c%.5u", method_type, JOINER, initp);
}
else
sprintf (type, "%c", method_type);
fnname = get_file_function_name_long (type);
start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE,
......@@ -2958,18 +3053,21 @@ start_objects (method_type)
or destructors. Subroutine of do_[cd]tors. */
static void
finish_objects (method_type)
int method_type;
finish_objects (method_type, initp)
int method_type, initp;
{
char *fnname;
tree list = (method_type == 'I' ? static_ctors : static_dtors);
if (! initp)
{
tree list = (method_type == 'I' ? static_ctors : static_dtors);
if (! current_function_decl && list)
start_objects (method_type);
if (! current_function_decl && list)
start_objects (method_type, initp);
for (; list; list = TREE_CHAIN (list))
expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
for (; list; list = TREE_CHAIN (list))
expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
}
if (! current_function_decl)
return;
......@@ -2982,19 +3080,56 @@ finish_objects (method_type)
pop_momentary ();
finish_function (lineno, 0, 0);
if (method_type == 'I')
assemble_constructor (fnname);
else
assemble_destructor (fnname);
if (! flag_init_priority)
{
if (method_type == 'I')
assemble_constructor (fnname);
else
assemble_destructor (fnname);
}
#ifdef ASM_OUTPUT_SECTION_NAME
/* If we're using init priority we can't use assemble_*tor, but on ELF
targets we can stick the references into named sections for GNU ld
to collect. */
if (flag_init_priority)
{
char buf[15];
if (initp == 0)
initp = DEFAULT_INIT_PRIORITY;
sprintf (buf, ".%ctors.%.5u", method_type == 'I' ? 'c' : 'd',
/* invert the numbering so the linker puts us in the proper
order; constructors are run from right to left, and the
linker sorts in increasing order. */
MAX_INIT_PRIORITY - initp);
named_section (NULL_TREE, buf, 0);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
POINTER_SIZE / BITS_PER_UNIT, 1);
}
#endif
}
/* Generate a function to run a set of global destructors. Subroutine of
finish_file. */
/* Generate a function to run a set of global destructors. START is either
NULL_TREE or a node indicating a set of destructors with the same
init priority. Subroutine of finish_file. */
static void
do_dtors ()
do_dtors (start)
tree start;
{
tree vars = static_aggregates;
tree vars;
int initp;
if (start)
{
initp = TREE_INT_CST_LOW (TREE_PURPOSE (start));
vars = TREE_VALUE (start);
}
else
{
initp = 0;
vars = static_aggregates;
}
for (; vars; vars = TREE_CHAIN (vars))
{
......@@ -3010,7 +3145,7 @@ do_dtors ()
|| DECL_WEAK (decl)));
if (! current_function_decl)
start_objects ('D');
start_objects ('D', initp);
/* Because of:
......@@ -3053,16 +3188,30 @@ do_dtors ()
}
}
finish_objects ('D');
finish_objects ('D', initp);
}
/* Generate a function to run a set of global constructors. Subroutine of
finish_file. */
/* Generate a function to run a set of global constructors. START is
either NULL_TREE or a node indicating a set of constructors with the
same init priority. Subroutine of finish_file. */
static void
do_ctors ()
do_ctors (start)
tree start;
{
tree vars = static_aggregates;
tree vars;
int initp;
if (start)
{
initp = TREE_INT_CST_LOW (TREE_PURPOSE (start));
vars = TREE_VALUE (start);
}
else
{
initp = 0;
vars = static_aggregates;
}
/* Reverse the list so it's in the right order for ctors. */
vars = nreverse (vars);
......@@ -3088,7 +3237,7 @@ do_ctors ()
|| DECL_WEAK (decl)));
if (! current_function_decl)
start_objects ('I');
start_objects ('I', initp);
/* Set these global variables so that GDB at least puts
us near the declaration which required the initialization. */
......@@ -3148,7 +3297,7 @@ do_ctors ()
my_friendly_abort (22);
}
finish_objects ('I');
finish_objects ('I', initp);
}
/* This routine is called from the last rule in yyparse ().
......@@ -3262,17 +3411,28 @@ finish_file ()
if (static_dtors || vars)
needs_cleaning = 1;
/* The aggregates are listed in reverse declaration order, for cleaning. */
setup_initp ();
/* After setup_initp, the aggregates are listed in reverse declaration
order, for cleaning. */
if (needs_cleaning)
{
do_dtors ();
do_dtors (NULL_TREE);
if (flag_init_priority)
for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars))
do_dtors (vars);
}
/* do_ctors will reverse the lists for messing up. */
if (needs_messing_up)
{
do_ctors ();
}
do_ctors (NULL_TREE);
if (flag_init_priority)
for (vars = static_aggregates_initp; vars; vars = TREE_CHAIN (vars))
do_ctors (vars);
}
permanent_allocation (1);
......
......@@ -66,6 +66,8 @@ DEFINE_LANG_NAME ("C++")
{ "-fno-implement-inlines", "Export functions even if they can be inlined" },
{ "-fimplicit-templates", "Emit implicit instatiations if needed" },
{ "-fno-implicit-templates", "" },
{ "-finit-priority", "Handle the init_priority attribute" },
{ "-fno-init-priority", "" },
{ "-flabels-ok", "Labels can be used as first class objects" },
{ "-fno-labels-ok", "" },
{ "-fmemoize-lookups", "Enable caching of member function resolutions" },
......
......@@ -1030,6 +1030,11 @@ your code with this flag (including the C++ library, if you use it).
This flag is not useful when compiling with -fvtable-thunks.
@item -finit-priority
Support @samp{__attribute__ ((init_priority (n)))} for controlling the
order of initialization of file-scope objects. On ELF targets, this
requires GNU ld 2.10 or later.
@item -fno-implement-inlines
To save space, do not emit out-of-line copies of inline functions
controlled by @samp{#pragma implementation}. This will cause linker
......
......@@ -4806,24 +4806,24 @@ dump_tree_statistics ()
#define FILE_FUNCTION_PREFIX_LEN 9
#ifndef NO_DOLLAR_IN_LABEL
#define FILE_FUNCTION_FORMAT "_GLOBAL_$D$%s"
#define FILE_FUNCTION_FORMAT "_GLOBAL_$%s$%s"
#else /* NO_DOLLAR_IN_LABEL */
#ifndef NO_DOT_IN_LABEL
#define FILE_FUNCTION_FORMAT "_GLOBAL_.D.%s"
#define FILE_FUNCTION_FORMAT "_GLOBAL_.%s.%s"
#else /* NO_DOT_IN_LABEL */
#define FILE_FUNCTION_FORMAT "_GLOBAL__D_%s"
#define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
#endif /* NO_DOT_IN_LABEL */
#endif /* NO_DOLLAR_IN_LABEL */
extern char * first_global_object_name;
extern char * weak_global_object_name;
/* If KIND=='I', return a suitable global initializer (constructor) name.
If KIND=='D', return a suitable global clean-up (destructor) name. */
/* TYPE is some string to identify this function to the linker or
collect2. */
tree
get_file_function_name (kind)
int kind;
get_file_function_name_long (type)
char *type;
{
char *buf;
register char *p;
......@@ -4837,13 +4837,14 @@ get_file_function_name (kind)
else
p = input_filename;
buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p));
buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
+ strlen (type));
/* Set up the name of the file-level functions we may need. */
/* Use a global object (which is already required to be unique over
the program) rather than the file name (which imposes extra
constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */
sprintf (buf, FILE_FUNCTION_FORMAT, p);
sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
/* Don't need to pull weird characters out of global names. */
if (p != first_global_object_name)
......@@ -4866,10 +4867,23 @@ get_file_function_name (kind)
*p = '_';
}
buf[FILE_FUNCTION_PREFIX_LEN] = kind;
return get_identifier (buf);
}
/* If KIND=='I', return a suitable global initializer (constructor) name.
If KIND=='D', return a suitable global clean-up (destructor) name. */
tree
get_file_function_name (kind)
int kind;
{
char p[2];
p[0] = kind;
p[1] = 0;
return get_file_function_name_long (p);
}
/* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
The result is placed in BUFFER (which has length BIT_SIZE),
......
......@@ -1124,6 +1124,11 @@ struct tree_type
do not allocate storage, and refer to a definition elsewhere. */
#define DECL_EXTERNAL(NODE) (DECL_CHECK (NODE)->decl.external_flag)
/* In a VAR_DECL for a RECORD_TYPE, sets number for non-init_priority
initializatons. */
#define DEFAULT_INIT_PRIORITY 65535
#define MAX_INIT_PRIORITY 65535
/* In a TYPE_DECL
nonzero means the detail info about this type is not dumped into stabs.
Instead it will generate cross reference ('x') of names.
......@@ -1843,6 +1848,7 @@ extern void (*incomplete_decl_finalize_hook) PROTO((tree));
/* In tree.c */
extern char *perm_calloc PROTO((int, long));
extern tree get_file_function_name PROTO((int));
extern tree get_file_function_name_long PROTO((char *));
extern tree get_set_constructor_bits PROTO((tree, char *, int));
extern tree get_set_constructor_bytes PROTO((tree,
unsigned char *, int));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment