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> Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
* g++.c: Removed __NetBSD__ from conditional. * g++.c: Removed __NetBSD__ from conditional.
......
...@@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \ ...@@ -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/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.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/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 cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus 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 ...@@ -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 \ 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 \ 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. # Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o 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) ...@@ -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) error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
errfn.o : errfn.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 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. # These exist for maintenance purposes.
......
...@@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (function) == FUNCTION_DECL) if (TREE_CODE (function) == FUNCTION_DECL)
{ {
is_constructor = DECL_CONSTRUCTOR_P (function); is_constructor = DECL_CONSTRUCTOR_P (function);
if (DECL_INLINE (function)) TREE_USED (function) = 1;
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); function = default_conversion (function);
else
{
assemble_external (function);
TREE_USED (function) = 1;
function = default_conversion (function);
}
} }
else else
{ {
......
...@@ -954,9 +954,11 @@ struct lang_decl_flags ...@@ -954,9 +954,11 @@ struct lang_decl_flags
unsigned saved_inline : 1; unsigned saved_inline : 1;
unsigned use_template : 2; unsigned use_template : 2;
unsigned declared_static : 1; unsigned c_static : 1;
unsigned nonconverting : 1; unsigned nonconverting : 1;
unsigned dummy : 6; unsigned declared_inline : 1;
unsigned not_really_extern : 1;
unsigned dummy : 4;
tree access; tree access;
tree context; tree context;
...@@ -1234,10 +1236,14 @@ struct lang_decl ...@@ -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 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)) #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. */ specified in its declaration. */
#define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE)) #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. */ /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL. */
#define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE)) #define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
...@@ -1338,13 +1344,26 @@ struct lang_decl ...@@ -1338,13 +1344,26 @@ struct lang_decl
/* We know what we're doing with this decl now. */ /* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
/* This decl was declared to have internal linkage. */ /* This decl was declared or deduced to have internal linkage. This is
#define DECL_DECLARED_STATIC(NODE) \ only meaningful if TREE_PUBLIC is set. */
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static) #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) \ #define DECL_PUBLIC(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \ (TREE_CODE (NODE) == FUNCTION_DECL \
: TREE_PUBLIC (NODE)) ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
......
...@@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect) ...@@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect)
return NULL_TREE; return NULL_TREE;
fntype = TREE_TYPE (function); fntype = TREE_TYPE (function);
if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL) function = default_conversion (function);
function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
else
function = default_conversion (function);
result = build_nt (CALL_EXPR, function, result = build_nt (CALL_EXPR, function,
convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
......
...@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1; ...@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1;
int flag_vtable_thunks; 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 *' /* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */ to be useful, except in thoroughly ANSIfied programs. */
...@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"nonansi-builtins", &flag_no_nonansi_builtin, 0}, {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0}, {"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1}, {"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. /* Decode the string P as a language-specific option.
...@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl) ...@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl)
fnaddr = TREE_VALUE (entries); fnaddr = TREE_VALUE (entries);
TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl; TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
} }
if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn)) assemble_external (fn);
{
int save_extern = DECL_EXTERNAL (fn);
DECL_EXTERNAL (fn) = 1;
assemble_external (fn);
DECL_EXTERNAL (fn) = save_extern;
}
} }
} }
...@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final) ...@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final)
if (! found && ! final) if (! found && ! final)
{ {
/* This check only works before the method definitions are seen,
since DECL_INLINE may get bashed. */
tree method; tree method;
for (method = CLASSTYPE_METHODS (type); method != NULL_TREE; for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
method = DECL_NEXT_METHOD (method)) 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)) && ! DECL_ABSTRACT_VIRTUAL_P (method))
{ {
found = 1; found = 1;
...@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final) ...@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final)
if (final || ! found) if (final || ! found)
{ {
#ifdef ASSEMBLE_EXTERNAL
if (TREE_PUBLIC (decl))
cp_error ("all virtual functions redeclared inline");
#endif
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
DECL_EXTERNAL (decl) = 0; DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
} }
else else
{ {
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 0;
} }
} }
} }
...@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars) ...@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars)
method = DECL_NEXT_METHOD (method)) method = DECL_NEXT_METHOD (method))
{ {
if (DECL_VINDEX (method) != NULL_TREE if (DECL_VINDEX (method) != NULL_TREE
&& !DECL_DECLARED_STATIC (method) && !DECL_THIS_INLINE (method)
&& !DECL_ABSTRACT_VIRTUAL_P (method)) && !DECL_ABSTRACT_VIRTUAL_P (method))
{ {
SET_CLASSTYPE_INTERFACE_KNOWN (ctype); SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
...@@ -2747,23 +2747,21 @@ import_export_inline (decl) ...@@ -2747,23 +2747,21 @@ import_export_inline (decl)
if (DECL_INTERFACE_KNOWN (decl)) if (DECL_INTERFACE_KNOWN (decl))
return; return;
DECL_EXTERNAL (decl) = 0;
if (DECL_TEMPLATE_INSTANTIATION (decl)) if (DECL_TEMPLATE_INSTANTIATION (decl))
{ {
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates) if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
else else
DECL_EXTERNAL (decl) = 1; DECL_NOT_REALLY_EXTERN (decl) = 0;
} }
else if (DECL_FUNCTION_MEMBER_P (decl)) else if (DECL_FUNCTION_MEMBER_P (decl))
{ {
tree ctype = DECL_CLASS_CONTEXT (decl); tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype)) if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{ {
DECL_EXTERNAL (decl) DECL_NOT_REALLY_EXTERN (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype) = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines)); || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
} }
else else
TREE_PUBLIC (decl) = 0; TREE_PUBLIC (decl) = 0;
...@@ -3045,6 +3043,8 @@ finish_file () ...@@ -3045,6 +3043,8 @@ finish_file ()
assemble_constructor (IDENTIFIER_POINTER (fnname)); assemble_constructor (IDENTIFIER_POINTER (fnname));
} }
permanent_allocation (1);
/* Done with C language context needs. */ /* Done with C language context needs. */
pop_lang_context (); pop_lang_context ();
...@@ -3115,8 +3115,9 @@ finish_file () ...@@ -3115,8 +3115,9 @@ finish_file ()
{ {
TREE_CHAIN (last) = TREE_CHAIN (place); TREE_CHAIN (last) = TREE_CHAIN (place);
if (! DECL_EXTERNAL (decl)) if (DECL_NOT_REALLY_EXTERN (decl))
{ {
DECL_EXTERNAL (decl) = 0;
reconsider = 1; reconsider = 1;
temporary_allocation (); temporary_allocation ();
output_inline_function (decl); output_inline_function (decl);
...@@ -3142,7 +3143,7 @@ finish_file () ...@@ -3142,7 +3143,7 @@ finish_file ()
emit_thunk (vars); emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars) && ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars)) && DECL_C_STATIC (vars))
TREE_PUBLIC (vars) = 0; TREE_PUBLIC (vars) = 0;
} }
...@@ -3162,7 +3163,8 @@ finish_file () ...@@ -3162,7 +3163,8 @@ finish_file ()
} }
} }
permanent_allocation (1); finish_repo ();
this_time = get_run_time (); this_time = get_run_time ();
parse_time -= this_time - start_time; parse_time -= this_time - start_time;
varconst_time += this_time - start_time; varconst_time += this_time - start_time;
......
...@@ -780,9 +780,14 @@ init_exception_processing () ...@@ -780,9 +780,14 @@ init_exception_processing ()
push_lang_context (lang_name_c); push_lang_context (lang_name_c);
catch_match_fndecl = catch_match_fndecl =
define_function ("__throw_type_match", define_function (flag_rtti
build_function_type (integer_type_node, ? "__throw_type_match_rtti"
tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))), : "__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, NOT_BUILT_IN,
pushdecl, pushdecl,
0); 0);
...@@ -1131,6 +1136,31 @@ expand_leftover_cleanups () ...@@ -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 /* 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 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 matter. If typename is NULL, that means its a "catch (...)" or catch
...@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator)
{ {
rtx false_label_rtx; rtx false_label_rtx;
rtx protect_label_rtx; rtx protect_label_rtx;
tree type; tree decl = NULL_TREE;
tree decl;
tree init; tree init;
if (! doing_eh (1)) if (! doing_eh (1))
...@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator)
/* Create a binding level for the parm. */ /* Create a binding level for the parm. */
expand_start_bindings (0); 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. */ /* These are saved for the exception table. */
push_rtl_perm (); push_rtl_perm ();
false_label_rtx = gen_label_rtx (); false_label_rtx = gen_label_rtx ();
...@@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator) ...@@ -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, false_label_rtx);
push_label_entry (&false_label_stack, protect_label_rtx); push_label_entry (&false_label_stack, protect_label_rtx);
if (type) if (declspecs)
{ {
tree params; tree exp;
char *typestring;
rtx call_rtx, return_value_rtx; rtx call_rtx, return_value_rtx;
tree catch_match_fcall; tree init_type;
tree catchmatch_arg, argval;
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
typestring = build_overload_name (type, 1, 1);
if (decl == NULL_TREE)
params = tree_cons (NULL_TREE, {
combine_strings (build_string (strlen (typestring)+1, typestring)), error ("invalid catch parameter");
tree_cons (NULL_TREE, return;
make_tree (ptr_type_node, saved_throw_type), }
NULL_TREE));
catch_match_fcall = build_function_call (CatchMatch, params); /* Figure out the type that the initializer is. */
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0); 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)); assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx = return_value_rtx = hard_function_value (ptr_type_node, exp);
hard_function_value (integer_type_node, catch_match_fcall);
/* did the throw type match function return TRUE? */ /* 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); GET_MODE (return_value_rtx), 0, 0);
/* if it returned FALSE, jump over the catch block, else fall into it */ /* 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); finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
} }
else else
...@@ -1535,7 +1553,6 @@ expand_throw (exp) ...@@ -1535,7 +1553,6 @@ expand_throw (exp)
tree exp; tree exp;
{ {
rtx label; rtx label;
tree type;
if (! doing_eh (1)) if (! doing_eh (1))
return; return;
...@@ -1548,26 +1565,28 @@ expand_throw (exp) ...@@ -1548,26 +1565,28 @@ expand_throw (exp)
if (exp) if (exp)
{ {
tree throw_type;
rtx throw_type_rtx;
rtx throw_value_rtx;
/* throw expression */ /* throw expression */
/* First, decay it. */ /* First, decay it. */
exp = default_conversion (exp); exp = default_conversion (exp);
type = TREE_TYPE (exp);
{ /* Make a copy of the thrown object. WP 15.1.5 */
char *typestring = build_overload_name (type, 1, 1); exp = build_new (NULL_TREE, TREE_TYPE (exp),
tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring))); build_tree_list (NULL_TREE, exp),
rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0); 0);
rtx throw_value_rtx;
if (exp == error_mark_node)
/* Make a copy of the thrown object. WP 15.1.5 */ error (" in thrown expression");
exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
if (exp == error_mark_node) throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
error (" in thrown expression");
throw_value_rtx = expand_expr (exp, 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_value, throw_value_rtx);
emit_move_insn (saved_throw_type, throw_type_rtx); emit_move_insn (saved_throw_type, throw_type_rtx);
}
} }
else else
{ {
...@@ -1665,6 +1684,7 @@ build_throw (e) ...@@ -1665,6 +1684,7 @@ build_throw (e)
{ {
e = build1 (THROW_EXPR, void_type_node, e); e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1; TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
} }
return e; return e;
} }
...@@ -362,6 +362,7 @@ lang_init () ...@@ -362,6 +362,7 @@ lang_init ()
if (flag_cadillac) if (flag_cadillac)
cadillac_start (); cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename); if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename);
} }
void void
...@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t) ...@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t)
punt them now, or output them now if we're doing implementations punt them now, or output them now if we're doing implementations
and we know no overrides will exist. Otherwise, we delay until and we know no overrides will exist. Otherwise, we delay until
end-of-file, to see if the definition is really required. */ end-of-file, to see if the definition is really required. */
if (DECL_INLINE (decl)) if (DECL_THIS_INLINE (decl))
/* delay_to_eof == 0 */; /* delay_to_eof == 0 */;
else if (current_class_type && !interface_unknown) else if (current_class_type && !interface_unknown)
{ {
......
...@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl) ...@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl)
emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
expand_end_bindings (NULL, 1, 0); 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. /* 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. Note that that may have been done above, in save_for_inline_copying.
...@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl) ...@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl)
= tree_cons (DECL_NAME (fields), init, current_member_init_list); = tree_cons (DECL_NAME (fields), init, current_member_init_list);
} }
current_member_init_list = nreverse (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 (); setup_vtbl_ptr ();
} }
......
...@@ -897,6 +897,8 @@ template_instantiate_once: ...@@ -897,6 +897,8 @@ template_instantiate_once:
pop_obstacks (); pop_obstacks ();
end_template_instantiation ($1); end_template_instantiation ($1);
repo_template_used (t);
/* Now go after the methods & class data. */ /* Now go after the methods & class data. */
instantiate_member_templates ($1); instantiate_member_templates ($1);
......
...@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl)
TREE_STATIC (r) = 0; TREE_STATIC (r) = 0;
DECL_INTERFACE_KNOWN (r) = 0; DECL_INTERFACE_KNOWN (r) = 0;
DECL_INLINE (r) = DECL_INLINE (t); DECL_INLINE (r) = DECL_INLINE (t);
DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
{ {
#if 0 /* Maybe later. -jason */ #if 0 /* Maybe later. -jason */
struct tinst_level *til = tinst_for_decl(); struct tinst_level *til = tinst_for_decl();
...@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr)
else if (t->text) else if (t->text)
{ {
SET_DECL_IMPLICIT_INSTANTIATION (fndecl); SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
repo_template_used (fndecl);
p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
p->parm_vec = t->parm_vec; p->parm_vec = t->parm_vec;
p->bindings = targs; p->bindings = targs;
...@@ -2384,7 +2386,7 @@ do_pending_expansions () ...@@ -2384,7 +2386,7 @@ do_pending_expansions ()
DECIDE (0); DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t)) if (DECL_EXPLICIT_INSTANTIATION (t))
DECIDE (! DECL_EXTERNAL (t)); DECIDE (DECL_NOT_REALLY_EXTERN (t));
else if (! flag_implicit_templates) else if (! flag_implicit_templates)
DECIDE (0); DECIDE (0);
...@@ -2486,6 +2488,22 @@ add_pending_template (pt) ...@@ -2486,6 +2488,22 @@ add_pending_template (pt)
p->id = 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. */ /* called from the parser. */
void void
do_function_instantiation (declspecs, declarator, storage) do_function_instantiation (declspecs, declarator, storage)
...@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage)
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree fn = IDENTIFIER_GLOBAL_VALUE (name); tree fn = IDENTIFIER_GLOBAL_VALUE (name);
tree result = NULL_TREE; tree result = NULL_TREE;
int extern_p = 0;
if (fn) if (fn)
{ {
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (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)); int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms); tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
...@@ -2518,28 +2543,41 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2518,28 +2543,41 @@ do_function_instantiation (declspecs, declarator, storage)
} }
} }
if (! result) 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) if (flag_external_templates)
return; return;
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE) 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 else
cp_error ("storage class `%D' applied to template instantiation", cp_error ("storage class `%D' applied to template instantiation",
storage); storage);
mark_function_instantiated (result, extern_p);
} }
void 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) do_type_instantiation (name, storage)
tree name, storage; tree name, storage;
{ {
...@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage) ...@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage)
} }
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{ mark_class_instantiated (t, 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);
}
}
{ {
tree tmp; tree tmp;
...@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage) ...@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage)
if (! extern_p) if (! extern_p)
{ {
DECL_INTERFACE_KNOWN (tmp) = 1; DECL_INTERFACE_KNOWN (tmp) = 1;
DECL_EXTERNAL (tmp) = 0; DECL_NOT_REALLY_EXTERN (tmp) = 1;
TREE_STATIC (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) ...@@ -793,6 +793,10 @@ compute_access (basetype_path, field)
} }
#endif #endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
return access_public;
previous_scope = current_scope (); previous_scope = current_scope ();
context = DECL_CLASS_CONTEXT (field); 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