Commit faae18ab by Mike Stump

62nd Cygnus<->FSF merge

From-SVN: r9298
parent 684cfb6b
Sun Apr 2 23:43:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* search.c (compute_access): Don't try to do access control on
nested types.
Fri Mar 31 10:14:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* repo.c: New file to handle things repo.
* pt.c (instantiate_template): Call repo_template_used if the
definition is accessible.
(mark_function_instantiated): Split out from
do_function_instantiation.
(mark_class_instantiated): Split out from do_type_instantiation.
* parse.y (template_instantiate_once): Call repo_template_used.
* lex.c (lang_init): Call init_repo.
* decl2.c: Handle flag_use_repository.
(finish_file): Call finish_repo.
* decl.c (start_method): Call repo_template_used if this is a
template method.
* Makefile.in (CXX_OBJS): Add repo.o.
(repo.o): Add dependencies.
* Make-lang.in (CXX_SRCS): Add repo.c.
* decl.c (start_function): If DECL_INTERFACE_KNOWN and
DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL.
* typeck.c (build_binary_op_nodefault): Identify the invalid operand
types used.
* decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN.
Thu Mar 30 17:54:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (build_binary_op_nodefault): Tidy up use of build_type
and result_type. When checking for comparison between signed
and unsigned, use result_type rather than the (possibly shortened)
type of op0. Also, don't warn about equality comparison of a
signed operand to an unsigned constant that fits in the signed
type.
* method.c (do_build_copy_constructor): Reverse
current_base_init_list after we've built it up.
Thu Mar 30 14:35:18 1995 Mike Stump <mrs@cygnus.com>
* except.c (build_throw): Never warn about the value of throw not
being used.
Thu Mar 30 13:16:54 1995 Mike Stump <mrs@cygnus.com>
* except.c (expand_start_catch_block): Check for bad catch parameter
declarations.
Thu Mar 30 13:06:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if
DECL_EXTERNAL is not already set.
Thu Mar 30 11:26:24 1995 Mike Stump <mrs@cygnus.com>
* method.c (emit_thunk): Let poplevel know that the last level is
for a function so it can create a BLOCK_NODE and set DECL_INITIAL.
Thu Mar 30 11:15:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN
here.
* decl.c (grokdeclarator): OK, don't abort if we see a decl with
METHOD_TYPE.
(finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on
all deferred inlines.
Wed Mar 29 19:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cp-tree.h (DECL_THIS_INLINE): New macro.
(DECL_NOT_REALLY_EXTERN): New macro.
(DECL_THIS_STATIC): New macro.
* decl.c: Lose all references to current_extern_inline. Break
inline semantics into DECL_INLINE for actual inlining and
DECL_THIS_INLINE for the linkage wierdness. Use DECL_THIS_STATIC.
* decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to
emit an inline here. Associated changes.
* lex.c: Ditto.
* pt.c: Ditto.
* typeck.c: Ditto.
* call.c (build_method_call): Don't bother trying to handle inlines
specially.
* cvt.c (convert_to_aggr): Ditto.
* pt.c (do_function_instantiation): Handle instantiation of
public inlines, too.
Wed Mar 29 16:04:25 1995 Mike Stump <mrs@cygnus.com>
* except.c (init_exception_processing): Change the interface for
__throw_type_match and add decl for new rtti matching routine
__throw_type_match_rtti.
(build_eh_type): New routine to build a run time descriptor for the
expression given.
(expand_start_catch_block): Update to use new calling convention for
the matcher.
(expand_throw): Update to use build_eh_type.
Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
* g++.c: Removed __NetBSD__ from conditional.
......
......@@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
$(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \
$(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c
$(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
......
......@@ -159,7 +159,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \
edsel.o except.o init.o method.o search.o tree.o xref.o
edsel.o except.o init.o method.o search.o tree.o xref.o repo.o
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
......@@ -247,6 +247,7 @@ pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H)
error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H)
sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
repo.o : repo.c $(CONFIG.H) $(CXX_TREE_H)
# These exist for maintenance purposes.
......
......@@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (function) == FUNCTION_DECL)
{
is_constructor = DECL_CONSTRUCTOR_P (function);
if (DECL_INLINE (function))
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
else
{
assemble_external (function);
TREE_USED (function) = 1;
function = default_conversion (function);
}
TREE_USED (function) = 1;
function = default_conversion (function);
}
else
{
......
......@@ -954,9 +954,11 @@ struct lang_decl_flags
unsigned saved_inline : 1;
unsigned use_template : 2;
unsigned declared_static : 1;
unsigned c_static : 1;
unsigned nonconverting : 1;
unsigned dummy : 6;
unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned dummy : 4;
tree access;
tree context;
......@@ -1234,10 +1236,14 @@ struct lang_decl
#define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
#define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was
specified in its declaration. */
#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
/* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
......@@ -1338,13 +1344,26 @@ struct lang_decl
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
/* This decl was declared to have internal linkage. */
#define DECL_DECLARED_STATIC(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static)
/* This decl was declared or deduced to have internal linkage. This is
only meaningful if TREE_PUBLIC is set. */
#define DECL_C_STATIC(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static)
/* This function was declared inline. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_THIS_INLINE(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline)
/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
so that assemble_external will work properly. So we have this flag to
tell us whether the decl is really not external. */
#define DECL_NOT_REALLY_EXTERN(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
#define DECL_PUBLIC(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \
: TREE_PUBLIC (NODE))
(TREE_CODE (NODE) == FUNCTION_DECL \
? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
......
......@@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE;
fntype = TREE_TYPE (function);
if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
else
function = default_conversion (function);
function = default_conversion (function);
result = build_nt (CALL_EXPR, function,
convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
......
......@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1;
int flag_vtable_thunks;
/* True if we want to deal with repository information. */
int flag_use_repository;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
......@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1},
{"check-new", &flag_check_new, 1}
{"check-new", &flag_check_new, 1},
{"repo", &flag_use_repository, 1}
};
/* Decode the string P as a language-specific option.
......@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl)
fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
}
if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn))
{
int save_extern = DECL_EXTERNAL (fn);
DECL_EXTERNAL (fn) = 1;
assemble_external (fn);
DECL_EXTERNAL (fn) = save_extern;
}
assemble_external (fn);
}
}
......@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final)
if (! found && ! final)
{
/* This check only works before the method definitions are seen,
since DECL_INLINE may get bashed. */
tree method;
for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
method = DECL_NEXT_METHOD (method))
if (DECL_VINDEX (method) != NULL_TREE && ! DECL_INLINE (method)
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_THIS_INLINE (method)
&& ! DECL_ABSTRACT_VIRTUAL_P (method))
{
found = 1;
......@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final)
if (final || ! found)
{
#ifdef ASSEMBLE_EXTERNAL
if (TREE_PUBLIC (decl))
cp_error ("all virtual functions redeclared inline");
#endif
TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 0;
}
}
}
......@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars)
method = DECL_NEXT_METHOD (method))
{
if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_DECLARED_STATIC (method)
&& !DECL_THIS_INLINE (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method))
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
......@@ -2747,23 +2747,21 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl))
return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl))
{
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
TREE_PUBLIC (decl) = 0;
else
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
}
else
TREE_PUBLIC (decl) = 0;
......@@ -3045,6 +3043,8 @@ finish_file ()
assemble_constructor (IDENTIFIER_POINTER (fnname));
}
permanent_allocation (1);
/* Done with C language context needs. */
pop_lang_context ();
......@@ -3115,8 +3115,9 @@ finish_file ()
{
TREE_CHAIN (last) = TREE_CHAIN (place);
if (! DECL_EXTERNAL (decl))
if (DECL_NOT_REALLY_EXTERN (decl))
{
DECL_EXTERNAL (decl) = 0;
reconsider = 1;
temporary_allocation ();
output_inline_function (decl);
......@@ -3142,7 +3143,7 @@ finish_file ()
emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars))
&& DECL_C_STATIC (vars))
TREE_PUBLIC (vars) = 0;
}
......@@ -3162,7 +3163,8 @@ finish_file ()
}
}
permanent_allocation (1);
finish_repo ();
this_time = get_run_time ();
parse_time -= this_time - start_time;
varconst_time += this_time - start_time;
......
......@@ -780,9 +780,14 @@ init_exception_processing ()
push_lang_context (lang_name_c);
catch_match_fndecl =
define_function ("__throw_type_match",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))),
define_function (flag_rtti
? "__throw_type_match_rtti"
: "__throw_type_match",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)))),
NOT_BUILT_IN,
pushdecl,
0);
......@@ -1131,6 +1136,31 @@ expand_leftover_cleanups ()
}
}
/* Build a type value for use at runtime for a exp that is thrown or
matched against by the exception handling system. */
static tree
build_eh_type (exp)
tree exp;
{
char *typestring;
tree type;
if (flag_rtti)
{
exp = build_typeid (exp);
return build1 (ADDR_EXPR, ptr_type_node, exp);
}
type = TREE_TYPE (exp);
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
typestring = build_overload_name (type, 1, 1);
exp = combine_strings (build_string (strlen (typestring)+1, typestring));
return build1 (ADDR_EXPR, ptr_type_node, exp);
}
/* call this to start a catch block. Typename is the typename, and identifier
is the variable to place the object in or NULL if the variable doesn't
matter. If typename is NULL, that means its a "catch (...)" or catch
......@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator)
{
rtx false_label_rtx;
rtx protect_label_rtx;
tree type;
tree decl;
tree decl = NULL_TREE;
tree init;
if (! doing_eh (1))
......@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator)
/* Create a binding level for the parm. */
expand_start_bindings (0);
if (declspecs)
{
tree init_type;
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
/* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_type);
init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
/* Do we need the below two lines? */
/* Let `finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
/* This needs to be preallocated under the try block,
in a union of all catch variables. */
pushdecl (decl);
type = TREE_TYPE (decl);
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
}
else
type = NULL_TREE;
/* These are saved for the exception table. */
push_rtl_perm ();
false_label_rtx = gen_label_rtx ();
......@@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator)
push_label_entry (&false_label_stack, false_label_rtx);
push_label_entry (&false_label_stack, protect_label_rtx);
if (type)
if (declspecs)
{
tree params;
char *typestring;
tree exp;
rtx call_rtx, return_value_rtx;
tree catch_match_fcall;
tree catchmatch_arg, argval;
typestring = build_overload_name (type, 1, 1);
params = tree_cons (NULL_TREE,
combine_strings (build_string (strlen (typestring)+1, typestring)),
tree_cons (NULL_TREE,
make_tree (ptr_type_node, saved_throw_type),
NULL_TREE));
catch_match_fcall = build_function_call (CatchMatch, params);
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
tree init_type;
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
if (decl == NULL_TREE)
{
error ("invalid catch parameter");
return;
}
/* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE)
init_type = build_reference_type (init_type);
exp = make_tree (ptr_type_node, saved_throw_value);
exp = tree_cons (NULL_TREE,
build_eh_type (decl),
tree_cons (NULL_TREE,
make_tree (ptr_type_node, saved_throw_type),
tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
call_rtx = expand_call (exp, NULL_RTX, 0);
assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx =
hard_function_value (integer_type_node, catch_match_fcall);
return_value_rtx = hard_function_value (ptr_type_node, exp);
/* did the throw type match function return TRUE? */
emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX,
emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
GET_MODE (return_value_rtx), 0, 0);
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_bne (false_label_rtx));
emit_jump_insn (gen_beq (false_label_rtx));
init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
/* Do we need the below two lines? */
/* Let `finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
else
......@@ -1535,7 +1553,6 @@ expand_throw (exp)
tree exp;
{
rtx label;
tree type;
if (! doing_eh (1))
return;
......@@ -1548,26 +1565,28 @@ expand_throw (exp)
if (exp)
{
tree throw_type;
rtx throw_type_rtx;
rtx throw_value_rtx;
/* throw expression */
/* First, decay it. */
exp = default_conversion (exp);
type = TREE_TYPE (exp);
{
char *typestring = build_overload_name (type, 1, 1);
tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
rtx throw_value_rtx;
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
if (exp == error_mark_node)
error (" in thrown expression");
throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx);
}
/* Make a copy of the thrown object. WP 15.1.5 */
exp = build_new (NULL_TREE, TREE_TYPE (exp),
build_tree_list (NULL_TREE, exp),
0);
if (exp == error_mark_node)
error (" in thrown expression");
throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
emit_move_insn (saved_throw_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx);
}
else
{
......@@ -1665,6 +1684,7 @@ build_throw (e)
{
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
}
return e;
}
......@@ -362,6 +362,7 @@ lang_init ()
if (flag_cadillac)
cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
}
void
......@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t)
punt them now, or output them now if we're doing implementations
and we know no overrides will exist. Otherwise, we delay until
end-of-file, to see if the definition is really required. */
if (DECL_INLINE (decl))
if (DECL_THIS_INLINE (decl))
/* delay_to_eof == 0 */;
else if (current_class_type && !interface_unknown)
{
......
......@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0);
poplevel (0, 0, 0);
poplevel (0, 0, 1);
/* From now on, allocate rtl in current_obstack, not in saveable_obstack.
Note that that may have been done above, in save_for_inline_copying.
......@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl)
= tree_cons (DECL_NAME (fields), init, current_member_init_list);
}
current_member_init_list = nreverse (current_member_init_list);
current_base_init_list = nreverse (current_base_init_list);
setup_vtbl_ptr ();
}
......
......@@ -897,6 +897,8 @@ template_instantiate_once:
pop_obstacks ();
end_template_instantiation ($1);
repo_template_used (t);
/* Now go after the methods & class data. */
instantiate_member_templates ($1);
......
......@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl)
TREE_STATIC (r) = 0;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_INLINE (r) = DECL_INLINE (t);
DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
{
#if 0 /* Maybe later. -jason */
struct tinst_level *til = tinst_for_decl();
......@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr)
else if (t->text)
{
SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
repo_template_used (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec;
p->bindings = targs;
......@@ -2384,7 +2386,7 @@ do_pending_expansions ()
DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (! DECL_EXTERNAL (t));
DECIDE (DECL_NOT_REALLY_EXTERN (t));
else if (! flag_implicit_templates)
DECIDE (0);
......@@ -2486,6 +2488,22 @@ add_pending_template (pt)
p->id = pt;
}
void
mark_function_instantiated (result, extern_p)
tree result;
int extern_p;
{
if (DECL_TEMPLATE_INSTANTIATION (result))
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
DECL_NOT_REALLY_EXTERN (result) = 1;
}
}
/* called from the parser. */
void
do_function_instantiation (declspecs, declarator, storage)
......@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree name = DECL_NAME (decl);
tree fn = IDENTIFIER_GLOBAL_VALUE (name);
tree result = NULL_TREE;
int extern_p = 0;
if (fn)
{
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (TREE_CODE (fn) == TEMPLATE_DECL)
if (decls_match (fn, decl)
&& DECL_DEFER_OUTPUT (fn))
{
result = fn;
break;
}
else if (TREE_CODE (fn) == TEMPLATE_DECL)
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
......@@ -2518,28 +2543,41 @@ do_function_instantiation (declspecs, declarator, storage)
}
}
if (! result)
cp_error ("no matching template for `%D' found", decl);
{
cp_error ("no matching template for `%D' found", decl);
return;
}
if (flag_external_templates)
return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE)
{
DECL_INTERFACE_KNOWN (result) = 1;
DECL_EXTERNAL (result) = 0;
TREE_STATIC (result) = 1;
}
else if (storage == ridpointers[(int) RID_EXTERN])
;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
mark_function_instantiated (result, extern_p);
}
void
mark_class_instantiated (t, extern_p)
tree t;
int extern_p;
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
rest_of_type_compilation (t, 1);
}
}
void
do_type_instantiation (name, storage)
tree name, storage;
{
......@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage)
}
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
if (! extern_p)
{
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
rest_of_type_compilation (t, 1);
}
}
mark_class_instantiated (t, extern_p);
{
tree tmp;
......@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage)
if (! extern_p)
{
DECL_INTERFACE_KNOWN (tmp) = 1;
DECL_EXTERNAL (tmp) = 0;
TREE_STATIC (tmp) = 1;
DECL_NOT_REALLY_EXTERN (tmp) = 1;
}
}
......
/* Code to maintain a C++ template repository.
Copyright (C) 1995 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* My strategy here is as follows:
Everything should be emitted in a translation unit where it is used.
The results of the automatic process should be easily reproducible with
explicit code.
I'm thinking of compiling with -frepo, running a Perl script to update
files, and then being able to rebuild everything with -fno-implicit.
Full automation can come later. */
#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "input.h"
extern char * rindex ();
static tree pending_repo;
static char repo_name[1024];
static FILE *repo_file;
extern int flag_use_repository;
extern int errorcount, sorrycount;
static int repo_changed;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
/* Record the flags used to compile this translation unit. */
void
repo_compile_flags (argc, argv)
int argc;
char **argv;
{
}
/* If this template has not been seen before, add a note to the repository
saying where the declaration was. This may be used to find the
definition at link time. */
void
repo_template_declared (t)
tree t;
{}
/* Note where the definition of a template lives so that instantiations can
be generated later. */
void
repo_template_defined (t)
tree t;
{}
/* Note where the definition of a class lives to that template
instantiations can use it. */
void
repo_class_defined (t)
tree t;
{}
/* Note that a template has been used. If we can see the definition, offer
to emit it. */
void
repo_template_used (t)
tree t;
{
tree id;
if (! flag_use_repository)
return;
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
id = DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t));
if (IDENTIFIER_REPO_CHOSEN (id))
mark_class_instantiated (t, 0);
}
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
{
id = DECL_ASSEMBLER_NAME (t);
if (IDENTIFIER_REPO_CHOSEN (id))
mark_function_instantiated (t, 0);
}
else
my_friendly_abort (1);
if (! IDENTIFIER_REPO_USED (id))
{
repo_changed = 1;
IDENTIFIER_REPO_USED (id) = 1;
}
pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
}
/* Note that the vtable for a class has been used, and offer to emit it. */
void
repo_vtable_used (t)
tree t;
{
if (! flag_use_repository)
return;
pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
}
/* Note that an inline with external linkage has been used, and offer to
emit it. */
void
repo_inline_used (fn)
tree fn;
{
if (! flag_use_repository)
return;
/* Member functions of polymorphic classes go with their vtables. */
if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
{
repo_vtable_used (DECL_CLASS_CONTEXT (fn));
return;
}
pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
}
/* Note that a particular typeinfo node has been used, and offer to
emit it. */
void
repo_tinfo_used (ti)
tree ti;
{
}
static void
open_repo_file (filename)
char *filename;
{
register char *p, *q;
char *file = filename;
char *s = rindex (file, '/');
if (s == NULL)
s = file;
else
++s;
for (p = repo_name, q = file; q < s; )
*p++ = *q++;
*p++ = '.';
strcpy (p, q);
strcat (p, ".repo");
repo_file = fopen (repo_name, "r");
}
void
init_repo (filename)
char *filename;
{
char buf[1024];
if (! flag_use_repository)
return;
open_repo_file (filename);
if (repo_file == 0)
return;
while (fgets (buf, 1024, repo_file))
{
int len = strlen (buf) - 1;
if (buf[len] != '\n')
error ("repository info line too long in %s", repo_name);
buf[len] = '\0';
switch (buf[0])
{
case 'A':
case 'M':
break;
case 'C':
case 'O':
{
tree id = get_identifier (&buf[2]);
IDENTIFIER_REPO_USED (id) = 1;
if (buf[0] == 'C')
IDENTIFIER_REPO_CHOSEN (id) = 1;
}
break;
default:
error ("mysterious repository information in %s", repo_name);
}
}
}
static void
reopen_repo_file_for_write ()
{
if (repo_file)
fclose (repo_file);
repo_file = fopen (repo_name, "w");
if (repo_file == 0)
{
error ("man't create repository information file `%s'", repo_name);
flag_use_repository = 0;
}
}
/* Emit any pending repos. */
void
finish_repo ()
{
tree t;
int changed = 0;
if (! flag_use_repository)
return;
/* Do we have to write out a new info file? */
if (! repo_changed || errorcount || sorrycount)
goto out;
reopen_repo_file_for_write ();
if (repo_file == 0)
goto out;
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
tree val = TREE_VALUE (t);
char type;
if (TREE_CODE_CLASS (TREE_CODE (val)) == 't')
val = TYPE_MAIN_DECL (val);
val = DECL_ASSEMBLER_NAME (val);
if (! IDENTIFIER_REPO_USED (val))
continue;
IDENTIFIER_REPO_USED (val) = 0;
type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
}
out:
if (repo_file)
fclose (repo_file);
}
......@@ -793,6 +793,10 @@ compute_access (basetype_path, field)
}
#endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
return access_public;
previous_scope = current_scope ();
context = DECL_CLASS_CONTEXT (field);
......
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