Commit db5ae43f by Mike Stump

49th Cygnus<->FSF merge

From-SVN: r8570
parent c7a7ac46
...@@ -61,7 +61,7 @@ g++: $(srcdir)/cp/g++.c $(CONFIG_H) $(LIBDEPS) ...@@ -61,7 +61,7 @@ g++: $(srcdir)/cp/g++.c $(CONFIG_H) $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o g++ $(srcdir)/cp/g++.c $(LIBS) $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o g++ $(srcdir)/cp/g++.c $(LIBS)
# Create a version of the g++ driver which calls the cross-compiler. # Create a version of the g++ driver which calls the cross-compiler.
g++-cross: $(srcdir)/cp/g++.c g++-cross: $(srcdir)/cp/g++.c version.o $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o g++-cross \ $(CC) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) -o g++-cross \
-DGCC_NAME=\"$(GCC_CROSS_NAME)\" $(srcdir)/cp/g++.c version.o $(LIBS) -DGCC_NAME=\"$(GCC_CROSS_NAME)\" $(srcdir)/cp/g++.c version.o $(LIBS)
......
...@@ -187,15 +187,26 @@ RTL_H = $(srcdir)/../rtl.h $(srcdir)/../rtl.def \ ...@@ -187,15 +187,26 @@ RTL_H = $(srcdir)/../rtl.h $(srcdir)/../rtl.def \
TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \ TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
$(srcdir)/../machmode.h $(srcdir)/../machmode.def $(srcdir)/../machmode.h $(srcdir)/../machmode.def
CXX_TREE_H = $(TREE_H) cp-tree.h tree.def CXX_TREE_H = $(TREE_H) cp-tree.h tree.def
PARSE_H = $(srcdir)/parse.h
PARSE_C = $(srcdir)/parse.c
parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(srcdir)/parse.c | sed 's,^\./,,'` `echo $(PARSE_C) | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y #$(PARSE_C) $(PARSE_H) : $(srcdir)/parse.y
# @echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts.
# cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
# cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
$(PARSE_C) $(PARSE_H) : stamp-parse ; @true
stamp-parse: $(srcdir)/parse.y
@echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts. @echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y $(BISON) $(BISONFLAGS) -d $(srcdir)/parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h grep '^#define[ ]*YYEMPTY' y.tab.c >>y.tab.h
$(srcdir)/../move-if-change y.tab.c $(PARSE_C)
$(srcdir)/../move-if-change y.tab.h $(PARSE_H)
cp $(PARSE_C) y.tab.c
touch stamp-parse
# hash.h really depends on $(srcdir)/gxx.gperf. # hash.h really depends on $(srcdir)/gxx.gperf.
# But this would screw things for people that don't have gperf, # But this would screw things for people that don't have gperf,
...@@ -206,9 +217,9 @@ $(srcdir)/hash.h: ...@@ -206,9 +217,9 @@ $(srcdir)/hash.h:
$(srcdir)/gxx.gperf >$(srcdir)/hash.h $(srcdir)/gxx.gperf >$(srcdir)/hash.h
spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \ spew.o : spew.c $(CONFIG_H) $(CXX_TREE_H) \
$(srcdir)/parse.h $(srcdir)/../flags.h lex.h $(PARSE_H) $(srcdir)/../flags.h lex.h
lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \ lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \
$(srcdir)/parse.h input.c $(srcdir)/../flags.h hash.h lex.h $(PARSE_H) input.c $(srcdir)/../flags.h hash.h lex.h
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(srcdir)/../stack.h lex.h decl.h $(srcdir)/../stack.h
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \ decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
...@@ -229,7 +240,7 @@ expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) $(srcdir)/../flags.h \ ...@@ -229,7 +240,7 @@ expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) $(srcdir)/../flags.h \
$(srcdir)/../expr.h ../insn-codes.h $(srcdir)/../expr.h ../insn-codes.h
edsel.o : edsel.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h edsel.o : edsel.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h
xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h
pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(srcdir)/parse.h 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
......
...@@ -525,13 +525,6 @@ convert_harshness (type, parmtype, parm) ...@@ -525,13 +525,6 @@ convert_harshness (type, parmtype, parm)
else else
penalty = 2; penalty = 2;
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
intype = unsigned_type (intype);
penalty += 2;
}
ttr = intype; ttr = intype;
/* If the initializer is not an lvalue, then it does not /* If the initializer is not an lvalue, then it does not
...@@ -551,6 +544,13 @@ convert_harshness (type, parmtype, parm) ...@@ -551,6 +544,13 @@ convert_harshness (type, parmtype, parm)
return h; return h;
} }
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
ttr = intype = unsigned_type (intype);
penalty += 2;
}
if (ttl == ttr) if (ttl == ttr)
{ {
if (penalty > 2) if (penalty > 2)
...@@ -2197,6 +2197,12 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2197,6 +2197,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
cp->function = function; cp->function = function;
cp->basetypes = basetype_path; cp->basetypes = basetype_path;
/* Don't allow non-converting constructors to convert. */
if (flags & LOOKUP_ONLYCONVERTING
&& DECL_LANG_SPECIFIC (function)
&& DECL_NONCONVERTING_P (function))
continue;
/* No "two-level" conversions. */ /* No "two-level" conversions. */
if (flags & LOOKUP_NO_CONVERSION if (flags & LOOKUP_NO_CONVERSION
&& (cp->h.code & USER_CODE)) && (cp->h.code & USER_CODE))
...@@ -2434,6 +2440,13 @@ build_method_call (instance, name, parms, basetype_path, flags) ...@@ -2434,6 +2440,13 @@ build_method_call (instance, name, parms, basetype_path, flags)
/* Declare external function if necessary. */ /* Declare external function if necessary. */
assemble_external (function); assemble_external (function);
#if 0
if (DECL_ARTIFICIAL (function) && ! flag_no_inline
&& DECL_SAVED_INSNS (function) == 0
&& ! TREE_ASM_WRITTEN (function))
synthesize_method (function);
#endif
fntype = TREE_TYPE (function); fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == POINTER_TYPE) if (TREE_CODE (fntype) == POINTER_TYPE)
fntype = TREE_TYPE (fntype); fntype = TREE_TYPE (fntype);
......
...@@ -408,7 +408,7 @@ struct lang_type ...@@ -408,7 +408,7 @@ struct lang_type
unsigned interface_only : 1; unsigned interface_only : 1;
unsigned interface_unknown : 1; unsigned interface_unknown : 1;
unsigned needs_virtual_reinit : 1; unsigned needs_virtual_reinit : 1;
unsigned declared_exception : 1; unsigned vec_delete_takes_size : 1;
unsigned declared_class : 1; unsigned declared_class : 1;
unsigned being_defined : 1; unsigned being_defined : 1;
unsigned redefined : 1; unsigned redefined : 1;
...@@ -442,13 +442,12 @@ struct lang_type ...@@ -442,13 +442,12 @@ struct lang_type
unsigned has_const_init_ref : 1; unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1; unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned vec_delete_takes_size : 1;
unsigned has_abstract_assign_ref : 1; unsigned has_abstract_assign_ref : 1;
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */ member `dummy' with new bits if you go over the edge. */
unsigned dummy : 19; unsigned dummy : 20;
unsigned n_vancestors : 16; unsigned n_vancestors : 16;
} type_flags; } type_flags;
...@@ -495,7 +494,7 @@ struct lang_type ...@@ -495,7 +494,7 @@ struct lang_type
char *mi_matrix; char *mi_matrix;
union tree_node *conversions[last_conversion_type]; union tree_node *conversions[last_conversion_type];
union tree_node *dossier; union tree_node *rtti;
union tree_node *methods; union tree_node *methods;
...@@ -629,8 +628,8 @@ struct lang_type ...@@ -629,8 +628,8 @@ struct lang_type
signature reference type. */ signature reference type. */
#define SIGNATURE_REFERENCE_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_reference_to) #define SIGNATURE_REFERENCE_TO(NODE) (TYPE_LANG_SPECIFIC(NODE)->signature_reference_to)
/* The is the VAR_DECL that contains NODE's dossier. */ /* The is the VAR_DECL that contains NODE's rtti. */
#define CLASSTYPE_DOSSIER(NODE) (TYPE_LANG_SPECIFIC(NODE)->dossier) #define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC(NODE)->rtti)
/* List of all explicit methods (chained using DECL_NEXT_METHOD), /* List of all explicit methods (chained using DECL_NEXT_METHOD),
in order they were parsed. */ in order they were parsed. */
...@@ -816,8 +815,6 @@ struct lang_type ...@@ -816,8 +815,6 @@ struct lang_type
/* Say whether this node was declared as a "class" or a "struct". */ /* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class) #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_EXCEPTION(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_exception)
/* whether this can be globalized. */ /* whether this can be globalized. */
#define CLASSTYPE_NO_GLOBALIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.no_globalize) #define CLASSTYPE_NO_GLOBALIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.no_globalize)
...@@ -947,7 +944,10 @@ struct lang_decl_flags ...@@ -947,7 +944,10 @@ struct lang_decl_flags
unsigned saved_inline : 1; unsigned saved_inline : 1;
unsigned use_template : 2; unsigned use_template : 2;
unsigned dummy : 8; unsigned interface_known : 1;
unsigned declared_static : 1;
unsigned nonconverting : 1;
unsigned dummy : 5;
tree access; tree access;
tree context; tree context;
...@@ -1032,6 +1032,10 @@ struct lang_decl ...@@ -1032,6 +1032,10 @@ struct lang_decl
is mutable. */ is mutable. */
#define DECL_MUTABLE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag) #define DECL_MUTABLE_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.mutable_flag)
/* Nonzero for _DECL means that this constructor is a non-converting
constructor. */
#define DECL_NONCONVERTING_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.nonconverting)
/* Nonzero for FUNCTION_DECL means that this member function /* Nonzero for FUNCTION_DECL means that this member function
exists as part of an abstract class's interface. */ exists as part of an abstract class's interface. */
#define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual) #define DECL_ABSTRACT_VIRTUAL_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.abstract_virtual)
...@@ -1322,6 +1326,18 @@ struct lang_decl ...@@ -1322,6 +1326,18 @@ struct lang_decl
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \ #define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE(NODE) = 3) (CLASSTYPE_USE_TEMPLATE(NODE) = 3)
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.interface_known)
/* This decl was declared to have internal linkage. */
#define DECL_DECLARED_STATIC(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static)
#define DECL_PUBLIC(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \
: TREE_PUBLIC (NODE))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i) #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
/* ...and for unexpanded-parameterized-type nodes. */ /* ...and for unexpanded-parameterized-type nodes. */
...@@ -1330,7 +1346,7 @@ struct lang_decl ...@@ -1330,7 +1346,7 @@ struct lang_decl
/* An enumeration of the kind of tags that C++ accepts. */ /* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type, enum tag_types { record_type, class_type, union_type, enum_type,
exception_type, signature_type }; signature_type };
/* Zero means prototype weakly, as in ANSI C (no args means nothing). /* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */ Each language context defines how this variable should be set. */
...@@ -1387,8 +1403,14 @@ extern tree void_zero_node; ...@@ -1387,8 +1403,14 @@ extern tree void_zero_node;
extern tree default_function_type; extern tree default_function_type;
extern tree vtable_entry_type; extern tree vtable_entry_type;
extern tree sigtable_entry_type; extern tree sigtable_entry_type;
extern tree __t_desc_type_node, __i_desc_type_node, __m_desc_type_node; extern tree __t_desc_type_node;
extern tree Type_info_type_node; extern tree __tp_desc_type_node;
extern tree __access_mode_type_node;
extern tree __bltn_desc_type_node, __user_desc_type_node;
extern tree __class_desc_type_node, __attr_desc_type_node;
extern tree __ptr_desc_type_node, __func_desc_type_node;
extern tree __ptmf_desc_type_node, __ptmd_desc_type_node;
extern tree type_info_type_node;
extern tree class_star_type_node; extern tree class_star_type_node;
extern tree this_identifier; extern tree this_identifier;
extern tree pfn_identifier; extern tree pfn_identifier;
...@@ -1402,7 +1424,7 @@ extern tree error_mark_list; ...@@ -1402,7 +1424,7 @@ extern tree error_mark_list;
extern tree ptr_type_node, const_ptr_type_node; extern tree ptr_type_node, const_ptr_type_node;
extern tree class_type_node, record_type_node, union_type_node, enum_type_node; extern tree class_type_node, record_type_node, union_type_node, enum_type_node;
extern tree exception_type_node, unknown_type_node; extern tree unknown_type_node;
extern tree opaque_type_node, signature_type_node; extern tree opaque_type_node, signature_type_node;
/* Node for "pointer to (virtual) function". /* Node for "pointer to (virtual) function".
...@@ -1419,11 +1441,6 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node; ...@@ -1419,11 +1441,6 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node;
extern tree integer_two_node, integer_three_node; extern tree integer_two_node, integer_three_node;
extern tree bool_type_node, true_node, false_node; extern tree bool_type_node, true_node, false_node;
/* in except.c */
extern tree current_exception_type;
extern tree current_exception_decl;
extern tree current_exception_object;
/* in pt.c */ /* in pt.c */
/* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or /* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those PARM_DECLs. BINDINGS, if non-null, is a vector of bindings for those
...@@ -1715,9 +1732,9 @@ extern int flag_int_enum_equivalence; ...@@ -1715,9 +1732,9 @@ extern int flag_int_enum_equivalence;
extern int flag_gc; extern int flag_gc;
/* Nonzero means generate 'dossiers' that give run-time type information. */ /* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_dossier; extern int flag_rtti;
/* Nonzero means do emit exported implementations of functions even if /* Nonzero means do emit exported implementations of functions even if
they can be inlined. */ they can be inlined. */
...@@ -1782,7 +1799,8 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ ...@@ -1782,7 +1799,8 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define LOOKUP_GLOBAL (16) #define LOOKUP_GLOBAL (16)
#define LOOKUP_HAS_IN_CHARGE (32) #define LOOKUP_HAS_IN_CHARGE (32)
#define LOOKUP_SPECULATIVELY (64) #define LOOKUP_SPECULATIVELY (64)
/* 128 & 256 are free */ #define LOOKUP_ONLYCONVERTING (128)
/* 256 is free */
#define LOOKUP_NO_CONVERSION (512) #define LOOKUP_NO_CONVERSION (512)
#define LOOKUP_DESTRUCTOR (512) #define LOOKUP_DESTRUCTOR (512)
...@@ -1953,7 +1971,7 @@ extern tree grok_enum_decls PROTO((tree, tree)); ...@@ -1953,7 +1971,7 @@ extern tree grok_enum_decls PROTO((tree, tree));
extern int start_function PROTO((tree, tree, tree, int)); extern int start_function PROTO((tree, tree, tree, int));
extern void store_parm_decls PROTO((void)); extern void store_parm_decls PROTO((void));
extern void store_return_init PROTO((tree, tree)); extern void store_return_init PROTO((tree, tree));
extern void finish_function PROTO((int, int)); extern void finish_function PROTO((int, int, int));
extern tree start_method PROTO((tree, tree, tree)); extern tree start_method PROTO((tree, tree, tree));
extern tree finish_method PROTO((tree)); extern tree finish_method PROTO((tree));
extern void hack_incomplete_structures PROTO((tree)); extern void hack_incomplete_structures PROTO((tree));
......
...@@ -663,10 +663,12 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ...@@ -663,10 +663,12 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (form == REFERENCE_TYPE) if (form == REFERENCE_TYPE)
{ {
rval = copy_node (expr); tree type = TREE_TYPE (expr);
TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr))); tree tmp = copy_node (expr);
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), rval, TREE_TYPE (tmp) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), tmp,
convtype, flags); convtype, flags);
TREE_TYPE (tmp) = type;
TREE_TYPE (rval) = reftype; TREE_TYPE (rval) = reftype;
return rval; return rval;
} }
...@@ -725,7 +727,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ...@@ -725,7 +727,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
&& (rval = build_method_call && (rval = build_method_call
(NULL_TREE, constructor_name_full (type), (NULL_TREE, constructor_name_full (type),
build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type),
LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY))) LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY
| LOOKUP_ONLYCONVERTING)))
{ {
tree init; tree init;
...@@ -736,7 +739,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ...@@ -736,7 +739,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
init = build_method_call (t, constructor_name_full (type), init = build_method_call (t, constructor_name_full (type),
build_tree_list (NULL_TREE, expr), build_tree_list (NULL_TREE, expr),
TYPE_BINFO (type), TYPE_BINFO (type),
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
| LOOKUP_ONLYCONVERTING);
if (init == error_mark_node) if (init == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -750,7 +754,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl) ...@@ -750,7 +754,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
init = build_method_call (NULL_TREE, constructor_name_full (type), init = build_method_call (NULL_TREE, constructor_name_full (type),
build_tree_list (NULL_TREE, expr), build_tree_list (NULL_TREE, expr),
TYPE_BINFO (type), TYPE_BINFO (type),
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
|LOOKUP_ONLYCONVERTING);
if (init == error_mark_node) if (init == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -1283,12 +1288,9 @@ cp_convert (type, expr, convtype, flags) ...@@ -1283,12 +1288,9 @@ cp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE_CODE (code)) if (IS_AGGR_TYPE_CODE (code))
{ {
tree dtype = TREE_TYPE (e); tree dtype = TREE_TYPE (e);
tree ctor = NULL_TREE;
tree conversion = NULL_TREE;
if (TREE_CODE (dtype) == REFERENCE_TYPE)
{
e = convert_from_reference (e);
dtype = TREE_TYPE (e);
}
dtype = TYPE_MAIN_VARIANT (dtype); dtype = TYPE_MAIN_VARIANT (dtype);
/* Conversion of object pointers or signature pointers/references /* Conversion of object pointers or signature pointers/references
...@@ -1321,87 +1323,78 @@ cp_convert (type, expr, convtype, flags) ...@@ -1321,87 +1323,78 @@ cp_convert (type, expr, convtype, flags)
There may be some ambiguity between using a constructor There may be some ambiguity between using a constructor
vs. using a type conversion operator when both apply. */ vs. using a type conversion operator when both apply. */
else if (IS_AGGR_TYPE (dtype)) if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
{ && TYPE_HAS_CONVERSION (dtype))
tree binfo;
tree conversion;
if (! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype))
conversion = build_type_conversion (CONVERT_EXPR, type, e, 1); conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
else
conversion = NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type)) if (conversion == error_mark_node)
{ {
tree rval = build_method_call (NULL_TREE, constructor_name_full (type), error ("ambiguous pointer conversion");
return conversion;
}
if (TYPE_HAS_CONSTRUCTOR (type))
ctor = build_method_call (NULL_TREE, constructor_name_full (type),
build_tree_list (NULL_TREE, e), build_tree_list (NULL_TREE, e),
TYPE_BINFO (type), TYPE_BINFO (type),
conversion ? LOOKUP_NO_CONVERSION : 0); LOOKUP_NORMAL | LOOKUP_SPECULATIVELY
| LOOKUP_ONLYCONVERTING
| (conversion ? LOOKUP_NO_CONVERSION : 0));
if (rval != error_mark_node) if (ctor == error_mark_node)
{
if (conversion)
{ {
error ("both constructor and type conversion operator apply"); cp_error ("in conversion to type `%T'", type);
return error_mark_node; return error_mark_node;
} }
/* call to constructor successful. */
rval = build_cplus_new (type, rval, 1);
return rval;
}
}
/* Type conversion successful/applies. */
if (conversion)
{
if (conversion == error_mark_node)
error ("ambiguous pointer conversion");
return conversion;
}
/* now try normal C++ assignment semantics. */ if (conversion && ctor)
binfo = TYPE_BINFO (dtype);
if (BINFO_TYPE (binfo) == type
|| (binfo = get_binfo (type, dtype, 1)))
{ {
if (binfo == error_mark_node) error ("both constructor and type conversion operator apply");
return error_mark_node; return error_mark_node;
} }
if (binfo != NULL_TREE) else if (conversion)
return conversion;
else if (ctor)
{ {
if (lvalue_p (e)) if (current_function_decl)
/* We can't pass 1 to the with_cleanup_p arg here, because that
screws up passing classes by value. */
ctor = build_cplus_new (type, ctor, 0);
else
{ {
e = build_unary_op (ADDR_EXPR, e, 0); register tree parm = TREE_OPERAND (ctor, 1);
if (! BINFO_OFFSET_ZEROP (binfo)) /* Initializers for static variables and parameters
e = build (PLUS_EXPR, TYPE_POINTER_TO (type), have to handle doing the initialization and
e, BINFO_OFFSET (binfo)); cleanup themselves. */
return build1 (INDIRECT_REF, type, e); my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322);
} #if 0
/* The following assertion fails in cases where we
sorry ("addressable aggregates"); are initializing a static member variable of a
return error_mark_node; particular instance of a template class with a
} call to a constructor of the given instance, as
error ("conversion between incompatible aggregate types requested"); in:
return error_mark_node;
} TMPL<int> object = TMPL<int>();
/* conversion from non-aggregate to aggregate type requires
constructor. */ Curiously, the assertion does not fail if we do
else if (TYPE_HAS_CONSTRUCTOR (type)) the same thing for a static member of a
{ non-template class, as in:
tree rval;
tree init = build_method_call (NULL_TREE, constructor_name_full (type), T object = T();
build_tree_list (NULL_TREE, e),
TYPE_BINFO (type), LOOKUP_NORMAL); I can't see why we should care here whether or not
if (init == error_mark_node) the initializer expression involves a call to
{ `new', so for the time being, it seems best to
cp_error ("in conversion to type `%T'", type); just avoid doing this assertion. */
return error_mark_node; my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)),
323);
#endif
TREE_VALUE (parm) = NULL_TREE;
ctor = build_indirect_ref (ctor, NULL_PTR);
TREE_HAS_CONSTRUCTOR (ctor) = 1;
} }
/* We can't pass 1 to the with_cleanup_p arg here, because that return ctor;
screws up passing classes by value. */
rval = build_cplus_new (type, init, 0);
return rval;
} }
} }
...@@ -1483,9 +1476,9 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure) ...@@ -1483,9 +1476,9 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
int flags; int flags;
if (for_sure == 0) if (for_sure == 0)
flags = LOOKUP_PROTECT; flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING;
else else
flags = LOOKUP_NORMAL; flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
rval = build_method_call (expr, typename, NULL_TREE, NULL_TREE, flags); rval = build_method_call (expr, typename, NULL_TREE, NULL_TREE, flags);
if (rval == error_mark_node) if (rval == error_mark_node)
...@@ -1615,9 +1608,9 @@ build_type_conversion (code, xtype, expr, for_sure) ...@@ -1615,9 +1608,9 @@ build_type_conversion (code, xtype, expr, for_sure)
int flags; int flags;
if (for_sure == 0) if (for_sure == 0)
flags = LOOKUP_PROTECT; flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING;
else else
flags = LOOKUP_NORMAL; flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
rval = build_method_call (expr, rval = build_method_call (expr,
constructor_name_full (typename), constructor_name_full (typename),
NULL_TREE, NULL_TREE, flags); NULL_TREE, NULL_TREE, flags);
......
...@@ -22,6 +22,7 @@ enum decl_context ...@@ -22,6 +22,7 @@ enum decl_context
{ NORMAL, /* Ordinary declaration */ { NORMAL, /* Ordinary declaration */
FUNCDEF, /* Function definition */ FUNCDEF, /* Function definition */
PARM, /* Declaration of parm before function body */ PARM, /* Declaration of parm before function body */
CATCHPARM, /* Declaration of catch parm */
FIELD, /* Declaration inside struct or union */ FIELD, /* Declaration inside struct or union */
BITFIELD, /* Likewise but with specified width */ BITFIELD, /* Likewise but with specified width */
TYPENAME, /* Typename (inside cast or sizeof) */ TYPENAME, /* Typename (inside cast or sizeof) */
......
...@@ -301,9 +301,9 @@ int flag_cadillac; ...@@ -301,9 +301,9 @@ int flag_cadillac;
that can be collected when they become garbage. */ that can be collected when they become garbage. */
int flag_gc; int flag_gc;
/* Controls whether compiler generates 'dossiers' that give /* Controls whether compiler generates 'type descriptor' that give
run-time type information. */ run-time type information. */
int flag_dossier; int flag_rtti = 0;
/* Nonzero if we wish to output cross-referencing information /* Nonzero if we wish to output cross-referencing information
for the GNU class browser. */ for the GNU class browser. */
...@@ -365,7 +365,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = ...@@ -365,7 +365,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"dollars-in-identifiers", &dollars_in_ident, 1}, {"dollars-in-identifiers", &dollars_in_ident, 1},
{"enum-int-equiv", &flag_int_enum_equivalence, 1}, {"enum-int-equiv", &flag_int_enum_equivalence, 1},
{"gc", &flag_gc, 1}, {"gc", &flag_gc, 1},
{"dossier", &flag_dossier, 1}, {"rtti", &flag_rtti, 1},
{"xref", &flag_gnu_xref, 1}, {"xref", &flag_gnu_xref, 1},
{"nonnull-objects", &flag_assume_nonnull_objects, 1}, {"nonnull-objects", &flag_assume_nonnull_objects, 1},
{"implement-inlines", &flag_implement_inlines, 1}, {"implement-inlines", &flag_implement_inlines, 1},
...@@ -442,14 +442,14 @@ lang_decode_option (p) ...@@ -442,14 +442,14 @@ lang_decode_option (p)
{ {
flag_gc = 1; flag_gc = 1;
/* This must come along for the ride. */ /* This must come along for the ride. */
flag_dossier = 1; flag_rtti = 1;
found = 1; found = 1;
} }
else if (! strcmp (p, "no-gc")) else if (! strcmp (p, "no-gc"))
{ {
flag_gc = 0; flag_gc = 0;
/* This must come along for the ride. */ /* This must come along for the ride. */
flag_dossier = 0; flag_rtti = 0;
found = 1; found = 1;
} }
else if (! strcmp (p, "alt-external-templates")) else if (! strcmp (p, "alt-external-templates"))
...@@ -707,15 +707,10 @@ grok_x_components (specs, components) ...@@ -707,15 +707,10 @@ grok_x_components (specs, components)
tcode = class_type_node; tcode = class_type_node;
else if (IS_SIGNATURE(t)) else if (IS_SIGNATURE(t))
tcode = signature_type_node; tcode = signature_type_node;
else if (CLASSTYPE_DECLARED_EXCEPTION(t))
tcode = exception_type_node;
t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE); t = xref_defn_tag(tcode, TYPE_IDENTIFIER(t), NULL_TREE);
if (TYPE_CONTEXT(t)) if (TYPE_CONTEXT(t))
CLASSTYPE_NO_GLOBALIZE(t) = 1; CLASSTYPE_NO_GLOBALIZE(t) = 1;
if (TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_DECLARED_EXCEPTION (t))
shadow_tag (specs);
return NULL_TREE; return NULL_TREE;
break; break;
...@@ -2170,7 +2165,9 @@ finish_table (name, type, init, publicp) ...@@ -2170,7 +2165,9 @@ finish_table (name, type, init, publicp)
if (TREE_VALUE (init) == integer_zero_node if (TREE_VALUE (init) == integer_zero_node
&& TREE_CHAIN (init) == NULL_TREE) && TREE_CHAIN (init) == NULL_TREE)
{ {
#if 0
if (empty_table == NULL_TREE) if (empty_table == NULL_TREE)
#endif
{ {
empty_table = get_temp_name (atype, 1); empty_table = get_temp_name (atype, 1);
init = build (CONSTRUCTOR, atype, NULL_TREE, init); init = build (CONSTRUCTOR, atype, NULL_TREE, init);
...@@ -2347,9 +2344,6 @@ mark_vtable_entries (decl) ...@@ -2347,9 +2344,6 @@ mark_vtable_entries (decl)
{ {
tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl))); tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)));
if (flag_dossier)
entries = TREE_CHAIN (entries);
for (; entries; entries = TREE_CHAIN (entries)) for (; entries; entries = TREE_CHAIN (entries))
{ {
tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries));
...@@ -2439,14 +2433,18 @@ finish_vtable_vardecl (prev, vars) ...@@ -2439,14 +2433,18 @@ finish_vtable_vardecl (prev, vars)
/* Stuff this virtual function table's size into /* Stuff this virtual function table's size into
`pfn' slot of `the_null_vtable_entry'. */ `pfn' slot of `the_null_vtable_entry'. */
#if 0
/* we do not put size as first entry any more */
tree nelts = array_type_nelts (TREE_TYPE (vars)); tree nelts = array_type_nelts (TREE_TYPE (vars));
if (flag_vtable_thunks) if (flag_vtable_thunks)
TREE_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))) = nelts; TREE_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))) = nelts;
else else
SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts); SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts);
/* Kick out the dossier before writing out the vtable. */ #endif
if (flag_dossier)
rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1); /* Kick out the type descriptor before writing out the vtable. */
if (flag_rtti)
rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (CONSTRUCTOR_ELTS (DECL_INITIAL (vars)))), 0), 0, 1, 1);
/* Write it out. */ /* Write it out. */
mark_vtable_entries (vars); mark_vtable_entries (vars);
...@@ -2565,15 +2563,14 @@ void ...@@ -2565,15 +2563,14 @@ void
import_export_inline (decl) import_export_inline (decl)
tree decl; tree decl;
{ {
if (TREE_PUBLIC (decl)) if (DECL_INTERFACE_KNOWN (decl))
return; return;
/* If an explicit instantiation doesn't have TREE_PUBLIC set, it was with if (DECL_TEMPLATE_INSTANTIATION (decl))
'extern'. */
if (DECL_EXPLICIT_INSTANTIATION (decl)
|| (DECL_IMPLICIT_INSTANTIATION (decl) && ! flag_implicit_templates))
{ {
TREE_PUBLIC (decl) = 1; if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
TREE_PUBLIC (decl) = 0;
else
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
} }
else if (DECL_FUNCTION_MEMBER_P (decl)) else if (DECL_FUNCTION_MEMBER_P (decl))
...@@ -2581,12 +2578,15 @@ import_export_inline (decl) ...@@ -2581,12 +2578,15 @@ import_export_inline (decl)
tree ctype = DECL_CLASS_CONTEXT (decl); tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype)) if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{ {
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) DECL_EXTERNAL (decl)
= (CLASSTYPE_INTERFACE_ONLY (ctype) = (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_INLINE (decl) && ! flag_implement_inlines)); || (DECL_INLINE (decl) && ! flag_implement_inlines));
} }
else
TREE_PUBLIC (decl) = 0;
} }
else
TREE_PUBLIC (decl) = 0;
} }
extern int parse_time, varconst_time; extern int parse_time, varconst_time;
...@@ -2693,7 +2693,7 @@ finish_file () ...@@ -2693,7 +2693,7 @@ finish_file ()
poplevel (1, 0, 0); poplevel (1, 0, 0);
pop_momentary (); pop_momentary ();
finish_function (lineno, 0); finish_function (lineno, 0, 0);
assemble_destructor (IDENTIFIER_POINTER (fnname)); assemble_destructor (IDENTIFIER_POINTER (fnname));
...@@ -2818,7 +2818,7 @@ finish_file () ...@@ -2818,7 +2818,7 @@ finish_file ()
poplevel (1, 0, 0); poplevel (1, 0, 0);
pop_momentary (); pop_momentary ();
finish_function (lineno, 0); finish_function (lineno, 0, 0);
assemble_constructor (IDENTIFIER_POINTER (fnname)); assemble_constructor (IDENTIFIER_POINTER (fnname));
} }
...@@ -2871,63 +2871,72 @@ finish_file () ...@@ -2871,63 +2871,72 @@ finish_file ()
pushdecl (vars); pushdecl (vars);
#endif #endif
interface_unknown = 1;
interface_only = 0;
for (vars = saved_inlines; vars; vars = TREE_CHAIN (vars))
{
tree decl = TREE_VALUE (vars);
if (DECL_ARTIFICIAL (decl)
&& ! DECL_INITIAL (decl)
&& (TREE_USED (decl) || ! DECL_EXTERNAL (decl)))
synthesize_method (decl);
}
walk_vtables ((void (*)())0, finish_vtable_vardecl); walk_vtables ((void (*)())0, finish_vtable_vardecl);
if (flag_handle_signatures) if (flag_handle_signatures)
walk_sigtables ((void (*)())0, finish_sigtable_vardecl); walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
for (vars = saved_inlines; vars; vars = TREE_CHAIN (vars))
{
tree decl = TREE_VALUE (vars);
if (DECL_ARTIFICIAL (decl)
&& ! DECL_INITIAL (decl)
&& TREE_USED (decl))
synthesize_method (decl);
}
for (vars = getdecls (); vars; vars = TREE_CHAIN (vars)) for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
{ {
if (TREE_CODE (vars) == THUNK_DECL) if (TREE_CODE (vars) == THUNK_DECL)
emit_thunk (vars); emit_thunk (vars);
else if (TREE_CODE (vars) == FUNCTION_DECL
&& ! DECL_INTERFACE_KNOWN (vars)
&& DECL_DECLARED_STATIC (vars))
TREE_PUBLIC (vars) = 0;
} }
{
int reconsider = 0; /* More may be referenced; check again */
tree delayed = NULL_TREE; /* These might be referenced later */
/* Now write out inline functions which had their addresses taken and /* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern which were not declared virtual and which were not declared `extern
inline'. */ inline'. */
while (saved_inlines)
{ {
tree decl = TREE_VALUE (saved_inlines); int reconsider = 1; /* More may be referenced; check again */
saved_inlines = TREE_CHAIN (saved_inlines); saved_inlines = tree_cons (NULL_TREE, NULL_TREE, saved_inlines);
/* Redefinition of a member function can cause DECL_SAVED_INSNS to be
0; don't crash. */ while (reconsider)
{
tree last = saved_inlines;
tree place = TREE_CHAIN (saved_inlines);
reconsider = 0;
for (; place; place = TREE_CHAIN (place))
{
tree decl = TREE_VALUE (place);
if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0) if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
{
TREE_CHAIN (last) = TREE_CHAIN (place);
continue; continue;
}
import_export_inline (decl); import_export_inline (decl);
if (TREE_PUBLIC (decl) if (TREE_PUBLIC (decl)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|| flag_keep_inline_functions) || flag_keep_inline_functions)
{ {
if (DECL_EXTERNAL (decl)) TREE_CHAIN (last) = TREE_CHAIN (place);
assemble_external (decl);
else
{
reconsider = 1;
temporary_allocation ();
output_inline_function (decl);
permanent_allocation (1);
}
}
else if (TREE_USED (decl)
|| TREE_USED (DECL_ASSEMBLER_NAME (decl)))
delayed = tree_cons (NULL_TREE, decl, delayed);
}
if (reconsider && delayed)
{
while (reconsider)
{
tree place;
reconsider = 0;
for (place = delayed; place; place = TREE_CHAIN (place))
{
tree decl = TREE_VALUE (place);
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& ! TREE_ASM_WRITTEN (decl))
{
if (DECL_EXTERNAL (decl)) if (DECL_EXTERNAL (decl))
assemble_external (decl); assemble_external (decl);
else else
...@@ -2937,8 +2946,11 @@ finish_file () ...@@ -2937,8 +2946,11 @@ finish_file ()
output_inline_function (decl); output_inline_function (decl);
permanent_allocation (1); permanent_allocation (1);
} }
continue;
} }
}
last = place;
} }
} }
} }
......
...@@ -43,6 +43,9 @@ tree builtin_return_address_fndecl; ...@@ -43,6 +43,9 @@ tree builtin_return_address_fndecl;
#define TRY_NEW_EH #define TRY_NEW_EH
#endif #endif
#endif #endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa)
#define TRY_NEW_EH
#endif
#endif #endif
#ifndef TRY_NEW_EH #ifndef TRY_NEW_EH
...@@ -188,60 +191,6 @@ easy_expand_asm (str) ...@@ -188,60 +191,6 @@ easy_expand_asm (str)
expand_asm (build_string (strlen (str)+1, str)); expand_asm (build_string (strlen (str)+1, str));
} }
/* unwind the stack. */
static void
do_unwind (throw_label)
rtx throw_label;
{
#ifdef sparc
extern FILE *asm_out_file;
tree fcall;
tree params;
rtx return_val_rtx;
/* call to __builtin_return_address () */
params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
/* In the return, the new pc is pc+8, as the value comming in is
really the address of the call insn, not the next insn. */
emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
Pmode,
throw_label), -8));
/* We use three values, PC, type, and value */
easy_expand_asm ("st %l0,[%fp]");
easy_expand_asm ("st %l1,[%fp+4]");
easy_expand_asm ("st %l2,[%fp+8]");
easy_expand_asm ("ret");
easy_expand_asm ("restore");
emit_barrier ();
#endif
#if m88k
rtx temp_frame = frame_pointer_rtx;
temp_frame = memory_address (Pmode, temp_frame);
temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
/* hopefully this will successfully pop the frame! */
emit_move_insn (frame_pointer_rtx, temp_frame);
emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
(HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
#if 0
emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
-(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
#endif
#endif
}
#if 0 #if 0
/* This is the startup, and finish stuff per exception table. */ /* This is the startup, and finish stuff per exception table. */
...@@ -834,10 +783,26 @@ init_exception_processing () ...@@ -834,10 +783,26 @@ init_exception_processing ()
pop_lang_context (); pop_lang_context ();
throw_label = gen_label_rtx (); throw_label = gen_label_rtx ();
#ifdef sparc
saved_pc = gen_rtx (REG, Pmode, 16); saved_pc = gen_rtx (REG, Pmode, 16);
saved_throw_type = gen_rtx (REG, Pmode, 17); saved_throw_type = gen_rtx (REG, Pmode, 17);
saved_throw_value = gen_rtx (REG, Pmode, 18); saved_throw_value = gen_rtx (REG, Pmode, 18);
#endif
#ifdef __i386
saved_pc = gen_rtx (REG, Pmode, 3);
saved_throw_type = gen_rtx (REG, Pmode, 4);
saved_throw_value = gen_rtx (REG, Pmode, 5);
#endif
#ifdef __rs6000
saved_pc = gen_rtx (REG, Pmode, 12);
saved_throw_type = gen_rtx (REG, Pmode, 13);
saved_throw_value = gen_rtx (REG, Pmode, 14);
#endif
#ifdef __hppa
saved_pc = gen_rtx (REG, Pmode, 5);
saved_throw_type = gen_rtx (REG, Pmode, 6);
saved_throw_value = gen_rtx (REG, Pmode, 7);
#endif
new_eh_queue (&ehqueue); new_eh_queue (&ehqueue);
new_eh_queue (&eh_table_output_queue); new_eh_queue (&eh_table_output_queue);
new_eh_stack (&ehstack); new_eh_stack (&ehstack);
...@@ -1112,7 +1077,7 @@ expand_start_catch_block (declspecs, declarator) ...@@ -1112,7 +1077,7 @@ expand_start_catch_block (declspecs, declarator)
if (declspecs) if (declspecs)
{ {
tree init_type; tree init_type;
decl = grokdeclarator (declarator, declspecs, NORMAL, 1, NULL_TREE); decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
/* Figure out the type that the initializer is. */ /* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl); init_type = TREE_TYPE (decl);
...@@ -1247,6 +1212,82 @@ do_function_call (func, params, return_type) ...@@ -1247,6 +1212,82 @@ do_function_call (func, params, return_type)
return NULL_RTX; return NULL_RTX;
} }
/* unwind the stack. */
static void
do_unwind (throw_label)
rtx throw_label;
{
#ifdef sparc
extern FILE *asm_out_file;
tree fcall;
tree params;
rtx return_val_rtx;
/* call to __builtin_return_address () */
params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
/* In the return, the new pc is pc+8, as the value comming in is
really the address of the call insn, not the next insn. */
emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
Pmode,
throw_label), -8));
/* We use three values, PC, type, and value */
easy_expand_asm ("st %l0,[%fp]");
easy_expand_asm ("st %l1,[%fp+4]");
easy_expand_asm ("st %l2,[%fp+8]");
easy_expand_asm ("ret");
easy_expand_asm ("restore");
emit_barrier ();
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa)
extern FILE *asm_out_file;
tree fcall;
tree params;
rtx return_val_rtx;
/* call to __builtin_return_address () */
params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
#if 0
/* I would like to do this here, but doesn't seem to work. */
emit_move_insn (return_val_rtx, gen_rtx (LABEL_REF,
Pmode,
throw_label));
/* So, for now, just pass throw label to stack unwinder. */
#endif
/* We use three values, PC, type, and value */
params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
do_function_call (Unwind, params, NULL_TREE);
emit_barrier ();
#endif
#if m88k
rtx temp_frame = frame_pointer_rtx;
temp_frame = memory_address (Pmode, temp_frame);
temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
/* hopefully this will successfully pop the frame! */
emit_move_insn (frame_pointer_rtx, temp_frame);
emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
(HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
#if 0
emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
-(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
#endif
#endif
}
/* is called from expand_excpetion_blocks () to generate the code in a function /* is called from expand_excpetion_blocks () to generate the code in a function
to "throw" if anything in the function needs to preform a throw. to "throw" if anything in the function needs to preform a throw.
...@@ -1306,6 +1347,12 @@ expand_builtin_throw () ...@@ -1306,6 +1347,12 @@ expand_builtin_throw ()
emit_jump_insn (gen_beq (gotta_call_terminate)); emit_jump_insn (gen_beq (gotta_call_terminate));
#ifndef sparc
/* On the SPARC, __builtin_return_address is already -8, no need to
subtract any more from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
#endif
/* yes it did */ /* yes it did */
emit_move_insn (saved_pc, return_val_rtx); emit_move_insn (saved_pc, return_val_rtx);
do_unwind (throw_label); do_unwind (throw_label);
...@@ -1344,7 +1391,8 @@ expand_exception_blocks () ...@@ -1344,7 +1391,8 @@ expand_exception_blocks ()
{ {
static int have_done = 0; static int have_done = 0;
if (! have_done && TREE_PUBLIC (current_function_decl) if (! have_done && TREE_PUBLIC (current_function_decl)
&& ! DECL_INLINE (current_function_decl)) && DECL_INTERFACE_KNOWN (current_function_decl)
&& ! DECL_EXTERNAL (current_function_decl))
{ {
have_done = 1; have_done = 1;
expand_builtin_throw (); expand_builtin_throw ();
...@@ -1394,7 +1442,7 @@ expand_throw (exp) ...@@ -1394,7 +1442,7 @@ expand_throw (exp)
rtx throw_value_rtx; rtx throw_value_rtx;
emit_move_insn (saved_throw_type, throw_type_rtx); emit_move_insn (saved_throw_type, throw_type_rtx);
exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, NULL_TREE); exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node);
if (exp == error_mark_node) if (exp == error_mark_node)
error (" in thrown expression"); error (" in thrown expression");
throw_value_rtx = expand_expr (build_unary_op (ADDR_EXPR, exp, 0), NULL_RTX, VOIDmode, 0); throw_value_rtx = expand_expr (build_unary_op (ADDR_EXPR, exp, 0), NULL_RTX, VOIDmode, 0);
...@@ -1437,7 +1485,8 @@ build_exception_table () ...@@ -1437,7 +1485,8 @@ build_exception_table ()
/* Beginning marker for table. */ /* Beginning marker for table. */
ASM_OUTPUT_ALIGN (asm_out_file, 2); ASM_OUTPUT_ALIGN (asm_out_file, 2);
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__"); ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
fprintf (asm_out_file, " .word 0, 0, 0\n"); output_exception_table_entry (asm_out_file,
const0_rtx, const0_rtx, const0_rtx);
} }
count++; count++;
output_exception_table_entry (asm_out_file, output_exception_table_entry (asm_out_file,
...@@ -1449,7 +1498,8 @@ build_exception_table () ...@@ -1449,7 +1498,8 @@ build_exception_table ()
{ {
/* Ending marker for table. */ /* Ending marker for table. */
ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__"); ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
fprintf (asm_out_file, " .word -1, -1, -1\n"); output_exception_table_entry (asm_out_file,
constm1_rtx, constm1_rtx, constm1_rtx);
} }
#endif /* TRY_NEW_EH */ #endif /* TRY_NEW_EH */
...@@ -1472,7 +1522,10 @@ tree ...@@ -1472,7 +1522,10 @@ tree
build_throw (e) build_throw (e)
tree e; tree e;
{ {
if (e != error_mark_node)
{
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;
}
return e; return e;
} }
...@@ -27,7 +27,11 @@ __volatile, TYPE_QUAL, RID_VOLATILE ...@@ -27,7 +27,11 @@ __volatile, TYPE_QUAL, RID_VOLATILE
__volatile__, TYPE_QUAL, RID_VOLATILE __volatile__, TYPE_QUAL, RID_VOLATILE
__wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */, __wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,
asm, ASM_KEYWORD, NORID, asm, ASM_KEYWORD, NORID,
and, ANDAND, NORID,
and_eq, ASSIGN, NORID,
auto, SCSPEC, RID_AUTO, auto, SCSPEC, RID_AUTO,
bitand, '&', NORID,
bitor, '|', NORID,
bool, TYPESPEC, RID_BOOL, bool, TYPESPEC, RID_BOOL,
break, BREAK, NORID, break, BREAK, NORID,
case, CASE, NORID, case, CASE, NORID,
...@@ -35,6 +39,7 @@ catch, CATCH, NORID, ...@@ -35,6 +39,7 @@ catch, CATCH, NORID,
char, TYPESPEC, RID_CHAR, char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS, class, AGGR, RID_CLASS,
classof, CLASSOF, NORID, classof, CLASSOF, NORID,
compl, '~', NORID,
const, TYPE_QUAL, RID_CONST, const, TYPE_QUAL, RID_CONST,
const_cast, CONST_CAST, NORID, const_cast, CONST_CAST, NORID,
continue, CONTINUE, NORID, continue, CONTINUE, NORID,
...@@ -45,6 +50,7 @@ double, TYPESPEC, RID_DOUBLE, ...@@ -45,6 +50,7 @@ double, TYPESPEC, RID_DOUBLE,
dynamic_cast, DYNAMIC_CAST, NORID, dynamic_cast, DYNAMIC_CAST, NORID,
else, ELSE, NORID, else, ELSE, NORID,
enum, ENUM, NORID, enum, ENUM, NORID,
explicit, SCSPEC, RID_EXPLICIT,
extern, SCSPEC, RID_EXTERN, extern, SCSPEC, RID_EXTERN,
false, CXX_FALSE, NORID, false, CXX_FALSE, NORID,
float, TYPESPEC, RID_FLOAT, float, TYPESPEC, RID_FLOAT,
...@@ -57,8 +63,13 @@ inline, SCSPEC, RID_INLINE, ...@@ -57,8 +63,13 @@ inline, SCSPEC, RID_INLINE,
int, TYPESPEC, RID_INT, int, TYPESPEC, RID_INT,
long, TYPESPEC, RID_LONG, long, TYPESPEC, RID_LONG,
mutable, SCSPEC, RID_MUTABLE, mutable, SCSPEC, RID_MUTABLE,
namespace, NAMESPACE, NORID,
new, NEW, NORID, new, NEW, NORID,
not, '!', NORID,
not_eq, EQCOMPARE, NORID,
operator, OPERATOR, NORID, operator, OPERATOR, NORID,
or, OROR, NORID,
or_eq, ASSIGN, NORID,
overload, OVERLOAD, NORID, overload, OVERLOAD, NORID,
private, VISSPEC, RID_PRIVATE, private, VISSPEC, RID_PRIVATE,
protected, VISSPEC, RID_PROTECTED, protected, VISSPEC, RID_PROTECTED,
...@@ -75,17 +86,21 @@ static, SCSPEC, RID_STATIC, ...@@ -75,17 +86,21 @@ static, SCSPEC, RID_STATIC,
static_cast, STATIC_CAST, NORID, static_cast, STATIC_CAST, NORID,
struct, AGGR, RID_RECORD, struct, AGGR, RID_RECORD,
switch, SWITCH, NORID, switch, SWITCH, NORID,
template, TEMPLATE, RID_TEMPLATE,
this, THIS, NORID, this, THIS, NORID,
throw, THROW, NORID, throw, THROW, NORID,
template, TEMPLATE, RID_TEMPLATE,
true, CXX_TRUE, NORID, true, CXX_TRUE, NORID,
try, TRY, NORID, try, TRY, NORID,
typedef, SCSPEC, RID_TYPEDEF, typedef, SCSPEC, RID_TYPEDEF,
typeof, TYPEOF, NORID, typename, TYPENAME_KEYWORD, NORID,
typeid, TYPEID, NORID, typeid, TYPEID, NORID,
typeof, TYPEOF, NORID,
union, AGGR, RID_UNION, union, AGGR, RID_UNION,
unsigned, TYPESPEC, RID_UNSIGNED, unsigned, TYPESPEC, RID_UNSIGNED,
using, USING, NORID,
virtual, SCSPEC, RID_VIRTUAL, virtual, SCSPEC, RID_VIRTUAL,
void, TYPESPEC, RID_VOID, void, TYPESPEC, RID_VOID,
volatile, TYPE_QUAL, RID_VOLATILE, volatile, TYPE_QUAL, RID_VOLATILE,
while, WHILE, NORID, while, WHILE, NORID,
xor, '^', NORID,
xor_eq, ASSIGN, NORID,
...@@ -1185,7 +1185,7 @@ On an rs6000, xlC stores exception objects on that stack, under the try ...@@ -1185,7 +1185,7 @@ On an rs6000, xlC stores exception objects on that stack, under the try
block. When is unwinds down into a handler, the frame pointer is block. When is unwinds down into a handler, the frame pointer is
adjusted back to the normal value for the frame in which the handler adjusted back to the normal value for the frame in which the handler
resides, and the stack pointer is left unchanged from the time at which resides, and the stack pointer is left unchanged from the time at which
the object was throwed. This is so that there is always someplace for the object was thrown. This is so that there is always someplace for
the exception object, and nothing can overwrite it, once we start the exception object, and nothing can overwrite it, once we start
throwing. The only bad part, is that the stack remains large. throwing. The only bad part, is that the stack remains large.
......
...@@ -125,6 +125,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -125,6 +125,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
tree real_binfos = BINFO_BASETYPES (real_binfo); tree real_binfos = BINFO_BASETYPES (real_binfo);
tree binfos = BINFO_BASETYPES (binfo); tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0; int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
int has_expanded = 0;
for (i = 0; i < n_baselinks; i++) for (i = 0; i < n_baselinks; i++)
{ {
...@@ -133,8 +134,12 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -133,8 +134,12 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
int is_not_base_vtable = int is_not_base_vtable =
i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo)); i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (real_base_binfo)) if (! TREE_VIA_VIRTUAL (real_base_binfo))
{
expand_direct_vtbls_init (real_base_binfo, base_binfo, expand_direct_vtbls_init (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr); (is_not_base_vtable || flag_rtti), can_elide, addr);
if (is_not_base_vtable && flag_rtti)
has_expanded = 1;
}
} }
#if 0 #if 0
/* Before turning this on, make sure it is correct. */ /* Before turning this on, make sure it is correct. */
...@@ -142,7 +147,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr) ...@@ -142,7 +147,7 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
return; return;
#endif #endif
/* Should we use something besides CLASSTYPE_VFIELDS? */ /* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo))) if (init_self && !has_expanded && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{ {
tree base_ptr = convert_pointer_to_real (binfo, addr); tree base_ptr = convert_pointer_to_real (binfo, addr);
expand_virtual_init (real_binfo, base_ptr); expand_virtual_init (real_binfo, base_ptr);
...@@ -421,13 +426,14 @@ emit_base_init (t, immediately) ...@@ -421,13 +426,14 @@ emit_base_init (t, immediately)
switch (n_baseclasses) switch (n_baseclasses)
{ {
case 0: case 0:
error ("type `%s' does not have a base class to initialize", cp_error ("`%T' does not have a base class to initialize",
IDENTIFIER_POINTER (current_class_name)); current_class_type);
return; return;
case 1: case 1:
break; break;
default: default:
error ("unnamed initializer ambiguous for type `%s' which uses multiple inheritance", IDENTIFIER_POINTER (current_class_name)); cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
current_class_type);
return; return;
} }
binfo = TREE_VEC_ELT (binfos, 0); binfo = TREE_VEC_ELT (binfos, 0);
...@@ -449,9 +455,9 @@ emit_base_init (t, immediately) ...@@ -449,9 +455,9 @@ emit_base_init (t, immediately)
break; break;
if (i < 0) if (i < 0)
{ {
error ("type `%s' is not an immediate base class of type `%s'", cp_error ("`%T' is not an immediate base class of `%T'",
IDENTIFIER_POINTER (basename), IDENTIFIER_TYPE_VALUE (basename),
IDENTIFIER_POINTER (current_class_name)); current_class_type);
continue; continue;
} }
} }
...@@ -641,9 +647,8 @@ emit_base_init (t, immediately) ...@@ -641,9 +647,8 @@ emit_base_init (t, immediately)
if (TREE_STATIC (member)) if (TREE_STATIC (member))
{ {
error_with_aggr_type (DECL_FIELD_CONTEXT (member), cp_error ("field `%#D' is static; only point of initialization is its declaration",
"field `%s::%s' is static; only point of initialization is its declaration", member);
IDENTIFIER_POINTER (TREE_PURPOSE (init_list)));
continue; continue;
} }
...@@ -745,8 +750,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list) ...@@ -745,8 +750,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
if (init) if (init)
init = TREE_PURPOSE (init); init = TREE_PURPOSE (init);
/* Call constructors, but don't set up vtables. */ /* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY);
expand_cleanups_to (NULL_TREE); expand_cleanups_to (NULL_TREE);
CLEAR_BINFO_VBASE_INIT_MARKED (binfo); CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
} }
...@@ -1196,12 +1200,12 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1196,12 +1200,12 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
out, then look hard. */ out, then look hard. */
tree rval; tree rval;
tree parms; tree parms;
int xxref_init_possible;
if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
{ {
parms = init; parms = init;
if (parms) init = TREE_VALUE (parms); if (parms)
init = TREE_VALUE (parms);
} }
else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)) else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))
{ {
...@@ -1213,16 +1217,6 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1213,16 +1217,6 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
else else
parms = build_tree_list (NULL_TREE, init); parms = build_tree_list (NULL_TREE, init);
if (TYPE_HAS_INIT_REF (type)
|| init == NULL_TREE
|| TREE_CHAIN (parms) != NULL_TREE)
xxref_init_possible = 0;
else
{
xxref_init_possible = LOOKUP_SPECULATIVELY;
flags &= ~LOOKUP_COMPLAIN;
}
if (TYPE_USES_VIRTUAL_BASECLASSES (type)) if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{ {
if (true_exp == exp) if (true_exp == exp)
...@@ -1232,41 +1226,31 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1232,41 +1226,31 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
flags |= LOOKUP_HAS_IN_CHARGE; flags |= LOOKUP_HAS_IN_CHARGE;
} }
rval = build_method_call (exp, constructor_name_full (type), if (init && TREE_CHAIN (parms) == NULL_TREE
parms, binfo, flags|xxref_init_possible); && TYPE_HAS_CONSTRUCTOR (type)
if (rval == NULL_TREE && xxref_init_possible) && ! TYPE_NEEDS_CONSTRUCTING (type)
{ && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
/* It is an error to implement a default copy constructor if
(see ARM 12.8 for details) ... one case being if another
copy constructor already exists. */
tree init_type = TREE_TYPE (init);
if (TREE_CODE (init_type) == REFERENCE_TYPE)
init_type = TREE_TYPE (init_type);
if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)
|| (IS_AGGR_TYPE (init_type)
&& UNIQUELY_DERIVED_FROM_P (type, init_type)))
{
if (type == BINFO_TYPE (binfo)
&& TYPE_USES_VIRTUAL_BASECLASSES (type))
{ {
tree addr = build_unary_op (ADDR_EXPR, exp, 0); rval = build (INIT_EXPR, type, exp, init);
expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE); TREE_SIDE_EFFECTS (rval) = 1;
expand_expr_stmt (rval);
expand_indirect_vtbls_init (binfo, exp, addr, 1);
}
expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
return;
} }
else else
rval = build_method_call (exp, constructor_name_full (type), parms, {
binfo, flags); rval = build_method_call (exp, constructor_name_full (type),
} parms, binfo, flags);
/* Private, protected, or otherwise unavailable. */ /* Private, protected, or otherwise unavailable. */
if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN)) if (rval == error_mark_node)
cp_error ("in base initialization for class `%T'", binfo); {
/* A valid initialization using constructor. */ if (flags & LOOKUP_COMPLAIN)
else if (rval != error_mark_node && rval != NULL_TREE) cp_error ("in base initialization for %sclass `%T'",
TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
binfo);
}
else if (rval == NULL_TREE)
my_friendly_abort (361);
else
{ {
/* p. 222: if the base class assigns to `this', then that /* p. 222: if the base class assigns to `this', then that
value is used in the derived class. */ value is used in the derived class. */
...@@ -1278,68 +1262,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags) ...@@ -1278,68 +1262,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
else else
expand_expr_stmt (rval); expand_expr_stmt (rval);
} }
else if (parms && TREE_CHAIN (parms) == NULL_TREE)
{
/* If we are initializing one aggregate value
from another, and though there are constructors,
and none accept the initializer, just do a bitwise
copy.
The above sounds wrong, ``If a class has any copy
constructor defined, the default copy constructor will
not be generated.'' 12.8 Copying Class Objects (mrs)
@@ This should reject initializer which a constructor
@@ rejected on access gounds, but there is
@@ no way right now to recognize that case with
@@ just `error_mark_node'. */
tree itype;
init = TREE_VALUE (parms);
itype = TREE_TYPE (init);
if (TREE_CODE (itype) == REFERENCE_TYPE)
{
init = convert_from_reference (init);
itype = TREE_TYPE (init);
}
itype = TYPE_MAIN_VARIANT (itype);
/* This is currently how the default X(X&) constructor
is implemented. */
if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0))
{
#if 0
warning ("bitwise copy in initialization of type `%s'",
TYPE_NAME_STRING (type));
#endif
rval = build (INIT_EXPR, type, exp, init);
expand_expr_stmt (rval);
}
else
{
cp_error ("in base initialization for class `%T',", binfo);
cp_error ("invalid initializer to constructor for type `%T'", type);
return;
}
}
else
{
if (init == NULL_TREE)
my_friendly_assert (parms == NULL_TREE, 210);
if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo))
cp_error ("virtual baseclass `%T' does not have default initializer", binfo);
else
{
cp_error ("in base initialization for class `%T',", binfo);
/* This will make an error message for us. */
build_method_call (exp, constructor_name_full (type), parms, binfo,
(TYPE_USES_VIRTUAL_BASECLASSES (type)
? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE
: LOOKUP_NORMAL));
}
return;
} }
/* Constructor has been called, but vtables may be for TYPE
rather than for FOR_TYPE. */
} }
/* This function is responsible for initializing EXP with INIT /* This function is responsible for initializing EXP with INIT
...@@ -2707,7 +2630,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals) ...@@ -2707,7 +2630,6 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals)
{ {
/* raw "main", and builtin functions never gets overloaded, /* raw "main", and builtin functions never gets overloaded,
but they can become friends. */ but they can become friends. */
TREE_PUBLIC (decl) = 1;
add_friend (current_class_type, decl); add_friend (current_class_type, decl);
DECL_FRIEND_P (decl) = 1; DECL_FRIEND_P (decl) = 1;
decl = void_type_node; decl = void_type_node;
......
...@@ -660,6 +660,9 @@ init_lex () ...@@ -660,6 +660,9 @@ init_lex ()
ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual"); ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL], SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL])); build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPLICIT],
build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPLICIT]));
ridpointers[(int) RID_FRIEND] = get_identifier ("friend"); ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND], SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND])); build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
...@@ -681,11 +684,6 @@ init_lex () ...@@ -681,11 +684,6 @@ init_lex ()
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE], SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE])); build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
/* Exception handling extensions. */
exception_type_node = build_int_2 (exception_type, 0);
TREE_TYPE (exception_type_node) = exception_type_node;
ridpointers[(int) RID_EXCEPTION] = exception_type_node;
/* Signature handling extensions. */ /* Signature handling extensions. */
signature_type_node = build_int_2 (signature_type, 0); signature_type_node = build_int_2 (signature_type, 0);
TREE_TYPE (signature_type_node) = signature_type_node; TREE_TYPE (signature_type_node) = signature_type_node;
...@@ -790,7 +788,7 @@ init_lex () ...@@ -790,7 +788,7 @@ init_lex ()
} }
#endif #endif
if (! (flag_gc || flag_dossier)) if (! (flag_gc || flag_rtti))
{ {
UNSET_RESERVED_WORD ("classof"); UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof"); UNSET_RESERVED_WORD ("headof");
...@@ -806,6 +804,17 @@ init_lex () ...@@ -806,6 +804,17 @@ init_lex ()
UNSET_RESERVED_WORD ("asm"); UNSET_RESERVED_WORD ("asm");
if (flag_no_asm || flag_traditional) if (flag_no_asm || flag_traditional)
UNSET_RESERVED_WORD ("typeof"); UNSET_RESERVED_WORD ("typeof");
if (!flag_ansi)
{
/* These are new ANSI keywords that may break code. */
UNSET_RESERVED_WORD ("and");
UNSET_RESERVED_WORD ("bitand");
UNSET_RESERVED_WORD ("bitor");
UNSET_RESERVED_WORD ("compl");
UNSET_RESERVED_WORD ("not");
UNSET_RESERVED_WORD ("or");
UNSET_RESERVED_WORD ("xor");
}
token_count = init_parse (); token_count = init_parse ();
interface_unknown = 1; interface_unknown = 1;
...@@ -1125,19 +1134,7 @@ do_pending_inlines () ...@@ -1125,19 +1134,7 @@ do_pending_inlines ()
DECL_PENDING_INLINE_INFO (f) = 0; DECL_PENDING_INLINE_INFO (f) = 0;
interface_unknown = t->interface == 1; interface_unknown = t->interface == 1;
interface_only = t->interface == 0; interface_only = t->interface == 0;
switch (- t->lineno) synthesize_method (f);
{
case 0: case 1:
build_dtor (f); break;
case 2:
build_default_constructor (f); break;
case 3: case 4:
build_copy_constructor (f); break;
case 5: case 6:
build_assign_ref (f); break;
default:
;
}
if (tail) if (tail)
tail->next = t->next; tail->next = t->next;
else else
...@@ -1712,6 +1709,7 @@ cons_up_default_function (type, name, kind) ...@@ -1712,6 +1709,7 @@ cons_up_default_function (type, name, kind)
tree fn, args; tree fn, args;
tree argtype; tree argtype;
int retref = 0; int retref = 0;
int complex = 0;
name = constructor_name (name); name = constructor_name (name);
switch (kind) switch (kind)
...@@ -1722,10 +1720,13 @@ cons_up_default_function (type, name, kind) ...@@ -1722,10 +1720,13 @@ cons_up_default_function (type, name, kind)
/* Fall through... */ /* Fall through... */
case 0: case 0:
name = build_parse_node (BIT_NOT_EXPR, name); name = build_parse_node (BIT_NOT_EXPR, name);
/* Fall through... */ args = void_list_node;
break;
case 2: case 2:
/* Default constructor. */ /* Default constructor. */
args = void_list_node; args = void_list_node;
complex = TYPE_NEEDS_CONSTRUCTING (type);
break; break;
case 3: case 3:
...@@ -1739,6 +1740,7 @@ cons_up_default_function (type, name, kind) ...@@ -1739,6 +1740,7 @@ cons_up_default_function (type, name, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
complex = TYPE_HAS_COMPLEX_INIT_REF (type);
break; break;
case 5: case 5:
...@@ -1755,6 +1757,7 @@ cons_up_default_function (type, name, kind) ...@@ -1755,6 +1757,7 @@ cons_up_default_function (type, name, kind)
build_tree_list (hash_tree_chain (argtype, NULL_TREE), build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")), get_identifier ("_ctor_arg")),
void_list_node); void_list_node);
complex = TYPE_HAS_COMPLEX_ASSIGN_REF (type);
break; break;
default: default:
...@@ -1777,11 +1780,23 @@ cons_up_default_function (type, name, kind) ...@@ -1777,11 +1780,23 @@ cons_up_default_function (type, name, kind)
if (fn == void_type_node) if (fn == void_type_node)
return fn; return fn;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) if (processing_template_defn)
SET_DECL_IMPLICIT_INSTANTIATION (fn); SET_DECL_IMPLICIT_INSTANTIATION (fn);
/* This kludge should go away when synthesized methods are handled if (CLASSTYPE_INTERFACE_KNOWN (type))
properly, i.e. only when needed. */ {
DECL_INTERFACE_KNOWN (fn) = 1;
DECL_EXTERNAL (fn) = (CLASSTYPE_INTERFACE_ONLY (type)
|| ! flag_implement_inlines);
TREE_STATIC (fn) = ! DECL_EXTERNAL (fn);
}
/* When on-the-fly synthesis works properly, remove the second and third
conditions here. */
if (flag_keep_inline_functions
|| ! flag_no_inline
|| complex
|| ! DECL_EXTERNAL (fn))
{ {
struct pending_inline *t; struct pending_inline *t;
t = (struct pending_inline *) t = (struct pending_inline *)
...@@ -1791,6 +1806,8 @@ cons_up_default_function (type, name, kind) ...@@ -1791,6 +1806,8 @@ cons_up_default_function (type, name, kind)
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (fn, t); store_pending_inline (fn, t);
} }
else
mark_inline_for_output (fn);
#ifdef DEBUG_DEFAULT_FUNCTIONS #ifdef DEBUG_DEFAULT_FUNCTIONS
{ char *fn_type = NULL; { char *fn_type = NULL;
...@@ -3474,6 +3491,52 @@ real_yylex () ...@@ -3474,6 +3491,52 @@ real_yylex ()
else else
yylval.ttype = old_ttype; yylval.ttype = old_ttype;
} }
else if (ptr->token == EQCOMPARE)
{
yylval.code = NE_EXPR;
token_buffer[0] = '!';
token_buffer[1] = '=';
token_buffer[2] = 0;
}
else if (ptr->token == ASSIGN)
{
if (strcmp ("and_eq", token_buffer) == 0)
{
yylval.code = BIT_AND_EXPR;
token_buffer[0] = '&';
}
else if (strcmp ("or_eq", token_buffer) == 0)
{
yylval.code = BIT_IOR_EXPR;
token_buffer[0] = '|';
}
else if (strcmp ("xor_eq", token_buffer) == 0)
{
yylval.code = BIT_XOR_EXPR;
token_buffer[0] = '^';
}
token_buffer[1] = '=';
token_buffer[2] = 0;
}
else if (ptr->token == '&')
{
yylval.code = BIT_AND_EXPR;
token_buffer[0] = '&';
token_buffer[1] = 0;
}
else if (ptr->token == '|')
{
yylval.code = BIT_IOR_EXPR;
token_buffer[0] = '|';
token_buffer[1] = 0;
}
else if (ptr->token == '^')
{
yylval.code = BIT_XOR_EXPR;
token_buffer[0] = '^';
token_buffer[1] = 0;
}
value = (int) ptr->token; value = (int) ptr->token;
} }
} }
......
...@@ -58,6 +58,7 @@ enum rid ...@@ -58,6 +58,7 @@ enum rid
RID_VOLATILE, RID_VOLATILE,
RID_FRIEND, RID_FRIEND,
RID_VIRTUAL, RID_VIRTUAL,
RID_EXPLICIT,
RID_SIGNED, RID_SIGNED,
RID_AUTO, RID_AUTO,
RID_MUTABLE, RID_MUTABLE,
......
...@@ -59,6 +59,7 @@ static char *scratch_firstobj; ...@@ -59,6 +59,7 @@ static char *scratch_firstobj;
IDENTIFIER_LENGTH (ID))) IDENTIFIER_LENGTH (ID)))
# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])
#ifdef NO_AUTO_OVERLOAD #ifdef NO_AUTO_OVERLOAD
int is_overloaded (); int is_overloaded ();
...@@ -317,19 +318,39 @@ static int numeric_outputed_need_bar; ...@@ -317,19 +318,39 @@ static int numeric_outputed_need_bar;
static void build_overload_identifier (); static void build_overload_identifier ();
static void static void
build_overload_nested_name (context) build_overload_nested_name (decl)
tree context; tree decl;
{ {
/* We use DECL_NAME here, because pushtag now sets the DECL_ASSEMBLER_NAME. */ if (DECL_CONTEXT (decl))
tree name = DECL_NAME (context);
if (DECL_CONTEXT (context))
{ {
context = DECL_CONTEXT (context); tree context = DECL_CONTEXT (decl);
if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
context = TYPE_NAME (context); context = TYPE_MAIN_DECL (context);
build_overload_nested_name (context); build_overload_nested_name (context);
} }
if (TREE_CODE (decl) == FUNCTION_DECL)
{
tree name = DECL_ASSEMBLER_NAME (decl);
char *label;
extern int var_labelno;
ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), var_labelno);
var_labelno++;
if (numeric_outputed_need_bar)
{
OB_PUTC ('_');
numeric_outputed_need_bar = 0;
}
icat (strlen (label));
OB_PUTCP (label);
}
else /* TYPE_DECL */
{
tree name = DECL_NAME (decl);
build_overload_identifier (name); build_overload_identifier (name);
}
} }
static void static void
...@@ -514,6 +535,7 @@ build_overload_name (parmtypes, begin, end) ...@@ -514,6 +535,7 @@ build_overload_name (parmtypes, begin, end)
tree parmtype; tree parmtype;
if (begin) OB_INIT (); if (begin) OB_INIT ();
numeric_outputed_need_bar = 0;
if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST))) if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST)))
{ {
...@@ -761,6 +783,13 @@ build_overload_name (parmtypes, begin, end) ...@@ -761,6 +783,13 @@ build_overload_name (parmtypes, begin, end)
if (TREE_CODE (name) == TYPE_DECL) if (TREE_CODE (name) == TYPE_DECL)
{ {
tree context = name; tree context = name;
/* If DECL_ASSEMBLER_NAME has been set properly, use it. */
if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context))
{
OB_PUTID (DECL_ASSEMBLER_NAME (context));
break;
}
while (DECL_CONTEXT (context)) while (DECL_CONTEXT (context))
{ {
i += 1; i += 1;
...@@ -780,7 +809,7 @@ build_overload_name (parmtypes, begin, end) ...@@ -780,7 +809,7 @@ build_overload_name (parmtypes, begin, end)
if (i > 9) if (i > 9)
OB_PUTC ('_'); OB_PUTC ('_');
numeric_outputed_need_bar = 0; numeric_outputed_need_bar = 0;
build_overload_nested_name (TYPE_NAME (parmtype)); build_overload_nested_name (TYPE_MAIN_DECL (parmtype));
} }
else else
build_overload_identifier (name); build_overload_identifier (name);
...@@ -920,7 +949,6 @@ build_decl_overload (dname, parms, for_method) ...@@ -920,7 +949,6 @@ build_decl_overload (dname, parms, for_method)
{ {
ALLOCATE_TYPEVEC (parms); ALLOCATE_TYPEVEC (parms);
nofold = 0; nofold = 0;
numeric_outputed_need_bar = 0;
if (for_method) if (for_method)
{ {
build_overload_name (TREE_VALUE (parms), 0, 0); build_overload_name (TREE_VALUE (parms), 0, 0);
...@@ -1906,6 +1934,10 @@ emit_thunk (thunk_fndecl) ...@@ -1906,6 +1934,10 @@ emit_thunk (thunk_fndecl)
unshare_all_rtl (insns); unshare_all_rtl (insns);
/* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ());
/* We are no longer anticipating cse in this function, at least. */ /* We are no longer anticipating cse in this function, at least. */
cse_not_expected = 1; cse_not_expected = 1;
...@@ -1971,16 +2003,6 @@ emit_thunk (thunk_fndecl) ...@@ -1971,16 +2003,6 @@ emit_thunk (thunk_fndecl)
/* Code for synthesizing methods which have default semantics defined. */ /* Code for synthesizing methods which have default semantics defined. */
void
build_default_constructor (fndecl)
tree fndecl;
{
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
setup_vtbl_ptr ();
finish_function (lineno, 0);
}
/* For the anonymous union in TYPE, return the member that is at least as /* For the anonymous union in TYPE, return the member that is at least as
large as the rest of the members, so we can copy it. */ large as the rest of the members, so we can copy it. */
static tree static tree
...@@ -2000,14 +2022,12 @@ largest_union_member (type) ...@@ -2000,14 +2022,12 @@ largest_union_member (type)
/* Generate code for default X(X&) constructor. */ /* Generate code for default X(X&) constructor. */
void void
build_copy_constructor (fndecl) do_build_copy_constructor (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree t; tree t;
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
clear_last_expr (); clear_last_expr ();
push_momentary (); push_momentary ();
...@@ -2085,17 +2105,15 @@ build_copy_constructor (fndecl) ...@@ -2085,17 +2105,15 @@ build_copy_constructor (fndecl)
} }
pop_momentary (); pop_momentary ();
finish_function (lineno, 0);
} }
void void
build_assign_ref (fndecl) do_build_assign_ref (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
start_function (NULL_TREE, fndecl, NULL_TREE, 1); clear_last_expr ();
store_parm_decls ();
push_momentary (); push_momentary ();
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
...@@ -2158,14 +2176,45 @@ build_assign_ref (fndecl) ...@@ -2158,14 +2176,45 @@ build_assign_ref (fndecl)
} }
c_expand_return (C_C_D); c_expand_return (C_C_D);
pop_momentary (); pop_momentary ();
finish_function (lineno, 0);
} }
void push_cp_function_context ();
void pop_cp_function_context ();
void void
build_dtor (fndecl) synthesize_method (fndecl)
tree fndecl; tree fndecl;
{ {
int nested = (current_function_decl != NULL_TREE);
int toplev = (decl_function_context (fndecl) == NULL_TREE);
char *f = input_filename;
if (nested)
push_cp_function_context (toplev);
input_filename = DECL_SOURCE_FILE (fndecl);
extract_interface_info ();
start_function (NULL_TREE, fndecl, NULL_TREE, 1); start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls (); store_parm_decls ();
finish_function (lineno, 0);
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
do_build_assign_ref (fndecl);
else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
;
else
{
tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);
if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl))
arg_chain = TREE_CHAIN (arg_chain);
if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
setup_vtbl_ptr ();
}
finish_function (lineno, 0, nested);
input_filename = f;
extract_interface_info ();
if (nested)
pop_cp_function_context (toplev);
} }
...@@ -150,6 +150,7 @@ empty_parms () ...@@ -150,6 +150,7 @@ empty_parms ()
%token <ttype> AGGR %token <ttype> AGGR
%token <itype> VISSPEC %token <itype> VISSPEC
%token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE %token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE
%token NAMESPACE TYPENAME_KEYWORD USING
%token LEFT_RIGHT TEMPLATE %token LEFT_RIGHT TEMPLATE
%token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST %token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST
%token <itype> SCOPE %token <itype> SCOPE
...@@ -170,6 +171,7 @@ empty_parms () ...@@ -170,6 +171,7 @@ empty_parms ()
%left '{' ',' ';' %left '{' ',' ';'
%nonassoc THROW
%right <code> ASSIGN '=' %right <code> ASSIGN '='
%right <code> '?' ':' %right <code> '?' ':'
%left <code> OROR %left <code> OROR
...@@ -190,7 +192,7 @@ empty_parms () ...@@ -190,7 +192,7 @@ empty_parms ()
%left <code> POINTSAT '.' '(' '[' %left <code> POINTSAT '.' '(' '['
%right SCOPE /* C++ extension */ %right SCOPE /* C++ extension */
%nonassoc NEW DELETE TRY CATCH THROW %nonassoc NEW DELETE TRY CATCH
%type <code> unop %type <code> unop
...@@ -430,9 +432,7 @@ template_def: ...@@ -430,9 +432,7 @@ template_def:
{ {
yychar = ':'; yychar = ':';
template1: template1:
if (current_aggr == exception_type_node) if (current_aggr == signature_type_node)
error ("template type must define an aggregate or union");
else if (current_aggr == signature_type_node)
sorry ("template type defining a signature"); sorry ("template type defining a signature");
/* Maybe pedantic warning for union? /* Maybe pedantic warning for union?
How about an enum? :-) */ How about an enum? :-) */
...@@ -564,7 +564,7 @@ datadef: ...@@ -564,7 +564,7 @@ datadef:
fndef: fndef:
fn.def1 base_init compstmt_or_error fn.def1 base_init compstmt_or_error
{ {
finish_function (lineno, 1); finish_function (lineno, 1, 0);
/* finish_function performs these three statements: /* finish_function performs these three statements:
expand_end_bindings (getdecls (), 1, 0); expand_end_bindings (getdecls (), 1, 0);
...@@ -577,7 +577,7 @@ fndef: ...@@ -577,7 +577,7 @@ fndef:
} }
| fn.def1 return_init base_init compstmt_or_error | fn.def1 return_init base_init compstmt_or_error
{ {
finish_function (lineno, 1); finish_function (lineno, 1, 0);
/* finish_function performs these three statements: /* finish_function performs these three statements:
expand_end_bindings (getdecls (), 1, 0); expand_end_bindings (getdecls (), 1, 0);
...@@ -589,13 +589,13 @@ fndef: ...@@ -589,13 +589,13 @@ fndef:
if ($<ttype>$) process_next_inline ($<ttype>$); if ($<ttype>$) process_next_inline ($<ttype>$);
} }
| fn.def1 nodecls compstmt_or_error | fn.def1 nodecls compstmt_or_error
{ finish_function (lineno, 0); { finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); } if ($<ttype>$) process_next_inline ($<ttype>$); }
| fn.def1 return_init ';' nodecls compstmt_or_error | fn.def1 return_init ';' nodecls compstmt_or_error
{ finish_function (lineno, 0); { finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); } if ($<ttype>$) process_next_inline ($<ttype>$); }
| fn.def1 return_init nodecls compstmt_or_error | fn.def1 return_init nodecls compstmt_or_error
{ finish_function (lineno, 0); { finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); } if ($<ttype>$) process_next_inline ($<ttype>$); }
| typed_declspecs declarator error | typed_declspecs declarator error
{} {}
...@@ -1148,7 +1148,7 @@ sub_cast_expr: ...@@ -1148,7 +1148,7 @@ sub_cast_expr:
{ {
tree type = IDENTIFIER_TYPE_VALUE ($3); tree type = IDENTIFIER_TYPE_VALUE ($3);
if (! IS_SIGNATURE(type)) if (! IS_SIGNATURE(type))
$$ = CLASSTYPE_DOSSIER (type); $$ = CLASSTYPE_RTTI (type);
else else
{ {
sorry ("signature name as argument of `classof'"); sorry ("signature name as argument of `classof'");
...@@ -2109,9 +2109,6 @@ structsp: ...@@ -2109,9 +2109,6 @@ structsp:
if (TREE_CODE ($$) == ENUMERAL_TYPE) if (TREE_CODE ($$) == ENUMERAL_TYPE)
/* $$ = $1 from default rule. */; /* $$ = $1 from default rule. */;
else if (CLASSTYPE_DECLARED_EXCEPTION ($$))
{
}
else else
{ {
$$ = finish_struct ($$, $3, semi); $$ = finish_struct ($$, $3, semi);
...@@ -2435,8 +2432,12 @@ left_curly: '{' ...@@ -2435,8 +2432,12 @@ left_curly: '{'
int needs_writing; int needs_writing;
tree name = TYPE_IDENTIFIER (t); tree name = TYPE_IDENTIFIER (t);
if (! ANON_AGGRNAME_P (name))
{
CLASSTYPE_INTERFACE_ONLY (t) = interface_only; CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, interface_unknown);
}
/* Record how to set the access of this class's /* Record how to set the access of this class's
virtual functions. If write_virtuals == 2 or 3, then virtual functions. If write_virtuals == 2 or 3, then
...@@ -3422,7 +3423,7 @@ handler_args: ...@@ -3422,7 +3423,7 @@ handler_args:
{ expand_start_catch_block ($2, $3); } { expand_start_catch_block ($2, $3); }
| '(' typed_typespecs after_type_declarator ')' | '(' typed_typespecs after_type_declarator ')'
{ expand_start_catch_block ($2, $3); } { expand_start_catch_block ($2, $3); }
*/ This allows reference parameters... */
| '(' parm ')' | '(' parm ')'
{ expand_start_catch_block (TREE_PURPOSE ($2), { expand_start_catch_block (TREE_PURPOSE ($2),
TREE_VALUE ($2)); } TREE_VALUE ($2)); }
......
...@@ -97,8 +97,7 @@ process_template_parm (list, next) ...@@ -97,8 +97,7 @@ process_template_parm (list, next)
PARM, 0, NULL_TREE); PARM, 0, NULL_TREE);
/* A template parameter is not modifiable. */ /* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
if (TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE if (IS_AGGR_TYPE (TREE_TYPE (parm)))
|| TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE)
{ {
sorry ("aggregate template parameter types"); sorry ("aggregate template parameter types");
TREE_TYPE (parm) = void_type_node; TREE_TYPE (parm) = void_type_node;
...@@ -466,7 +465,7 @@ coerce_template_parms (parms, arglist, in_decl) ...@@ -466,7 +465,7 @@ coerce_template_parms (parms, arglist, in_decl)
tree a = TREE_OPERAND (val, 0); tree a = TREE_OPERAND (val, 0);
if ((TREE_CODE (a) == VAR_DECL if ((TREE_CODE (a) == VAR_DECL
|| TREE_CODE (a) == FUNCTION_DECL) || TREE_CODE (a) == FUNCTION_DECL)
&& !TREE_PUBLIC (a)) && ! DECL_PUBLIC (a))
{ {
cp_error ("address of non-extern `%E' cannot be used as template argument", a); cp_error ("address of non-extern `%E' cannot be used as template argument", a);
val = error_mark_node; val = error_mark_node;
...@@ -683,7 +682,8 @@ push_template_decls (parmlist, arglist, class_level) ...@@ -683,7 +682,8 @@ push_template_decls (parmlist, arglist, class_level)
val = digest_init (TREE_TYPE (parm), arg, (tree *) 0); val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
if (val != error_mark_node) if (val != error_mark_node)
{ {
decl = build_decl (VAR_DECL, DECL_NAME (parm), TREE_TYPE (parm)); decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
DECL_INITIAL (decl) = val; DECL_INITIAL (decl) = val;
TREE_READONLY (decl) = 1; TREE_READONLY (decl) = 1;
} }
...@@ -834,6 +834,11 @@ uses_template_parms (t) ...@@ -834,6 +834,11 @@ uses_template_parms (t)
case UNINSTANTIATED_P_TYPE: case UNINSTANTIATED_P_TYPE:
return 1; return 1;
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
/* else fall through */
default: default:
switch (TREE_CODE_CLASS (TREE_CODE (t))) switch (TREE_CODE_CLASS (TREE_CODE (t)))
{ {
...@@ -898,19 +903,6 @@ instantiate_member_templates (classname) ...@@ -898,19 +903,6 @@ instantiate_member_templates (classname)
&TREE_VEC_ELT (parmvec, 0)); &TREE_VEC_ELT (parmvec, 0));
type = IDENTIFIER_TYPE_VALUE (id); type = IDENTIFIER_TYPE_VALUE (id);
my_friendly_assert (type != 0, 277); my_friendly_assert (type != 0, 277);
if (flag_external_templates)
{
if (CLASSTYPE_INTERFACE_UNKNOWN (type))
{
DECL_EXTERNAL (t2) = 0;
TREE_PUBLIC (t2) = 0;
}
else
{
DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type);
TREE_PUBLIC (t2) = 1;
}
}
break; break;
case 1: case 1:
/* Failure. */ /* Failure. */
...@@ -1116,14 +1108,10 @@ lookup_nested_type_by_name (ctype, name) ...@@ -1116,14 +1108,10 @@ lookup_nested_type_by_name (ctype, name)
{ {
tree t; tree t;
t = TREE_VALUE(CLASSTYPE_TAGS(ctype)); for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
while (t)
{ {
if (strcmp(IDENTIFIER_POINTER(name), IDENTIFIER_POINTER(TYPE_IDENTIFIER(t))) if (name == TREE_PURPOSE (t))
== 0) return TREE_VALUE (t);
return t;
else
t = TREE_CHAIN(t);
} }
return NULL_TREE; return NULL_TREE;
} }
...@@ -1198,9 +1186,12 @@ tsubst (t, args, nargs, in_decl) ...@@ -1198,9 +1186,12 @@ tsubst (t, args, nargs, in_decl)
tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl)); tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
return cp_build_type_variant (args[TEMPLATE_TYPE_IDX (t)], {
TYPE_READONLY (t), tree arg = args[TEMPLATE_TYPE_IDX (t)];
TYPE_VOLATILE (t)); return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
}
case TEMPLATE_CONST_PARM: case TEMPLATE_CONST_PARM:
return args[TEMPLATE_CONST_IDX (t)]; return args[TEMPLATE_CONST_IDX (t)];
...@@ -1404,9 +1395,10 @@ tsubst (t, args, nargs, in_decl) ...@@ -1404,9 +1395,10 @@ tsubst (t, args, nargs, in_decl)
} }
} }
} }
TREE_PUBLIC (r) = TREE_PUBLIC (t); TREE_PUBLIC (r) = 1;
DECL_EXTERNAL (r) = DECL_EXTERNAL (t); DECL_EXTERNAL (r) = 1;
TREE_STATIC (r) = TREE_STATIC (t); TREE_STATIC (r) = 0;
DECL_INTERFACE_KNOWN (r) = 0;
DECL_INLINE (r) = DECL_INLINE (t); DECL_INLINE (r) = DECL_INLINE (t);
{ {
#if 0 /* Maybe later. -jason */ #if 0 /* Maybe later. -jason */
...@@ -1720,9 +1712,20 @@ instantiate_template (tmpl, targ_ptr) ...@@ -1720,9 +1712,20 @@ instantiate_template (tmpl, targ_ptr)
extract_interface_info (); extract_interface_info ();
if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (tmpl)) if (interface_unknown && flag_external_templates)
{
if (DECL_CLASS_CONTEXT (fndecl)
&& CLASSTYPE_INTERFACE_KNOWN (DECL_CLASS_CONTEXT (fndecl)))
{
interface_unknown = 0;
interface_only
= CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
}
else if (! DECL_IN_SYSTEM_HEADER (tmpl))
warn_if_unknown_interface (); warn_if_unknown_interface ();
if (interface_unknown || !flag_external_templates) }
if (interface_unknown || ! flag_external_templates)
p->interface = 1; /* unknown */ p->interface = 1; /* unknown */
else else
p->interface = interface_only ? 0 : 2; p->interface = interface_only ? 0 : 2;
...@@ -2008,6 +2011,9 @@ type_unification (tparms, targs, parms, args, nsubsts, subr) ...@@ -2008,6 +2011,9 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
arg = TREE_TYPE (arg); arg = TREE_TYPE (arg);
} }
#endif #endif
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
if (TREE_CODE (parm) != REFERENCE_TYPE) if (TREE_CODE (parm) != REFERENCE_TYPE)
{ {
if (TREE_CODE (arg) == FUNCTION_TYPE if (TREE_CODE (arg) == FUNCTION_TYPE
...@@ -2068,9 +2074,6 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2068,9 +2074,6 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
if (arg == parm) if (arg == parm)
return 0; return 0;
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
switch (TREE_CODE (parm)) switch (TREE_CODE (parm))
{ {
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
...@@ -2082,6 +2085,7 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2082,6 +2085,7 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1; return 1;
} }
idx = TEMPLATE_TYPE_IDX (parm); idx = TEMPLATE_TYPE_IDX (parm);
#if 0
/* Template type parameters cannot contain cv-quals; i.e. /* Template type parameters cannot contain cv-quals; i.e.
template <class T> void f (T& a, T& b) will not generate template <class T> void f (T& a, T& b) will not generate
void f (const int& a, const int& b). */ void f (const int& a, const int& b). */
...@@ -2089,6 +2093,13 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2089,6 +2093,13 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
|| TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)) || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
return 1; return 1;
arg = TYPE_MAIN_VARIANT (arg); arg = TYPE_MAIN_VARIANT (arg);
#else
{
int constp = TYPE_READONLY (arg) > TYPE_READONLY (parm);
int volatilep = TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm);
arg = cp_build_type_variant (arg, constp, volatilep);
}
#endif
/* Simple cases: Value already set, does match or doesn't. */ /* Simple cases: Value already set, does match or doesn't. */
if (targs[idx] == arg) if (targs[idx] == arg)
return 0; return 0;
...@@ -2205,22 +2216,19 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts) ...@@ -2205,22 +2216,19 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
case UNINSTANTIATED_P_TYPE: case UNINSTANTIATED_P_TYPE:
{ {
tree a; tree a;
/* Unification of something that is not a template fails. (mrs) */ /* Unification of something that is not a class fails. */
if (TYPE_NAME (arg) == 0) if (! IS_AGGR_TYPE (arg))
return 1; return 1;
a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg)); a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));
/* Unification of something that is not a template fails. (mrs) */ if (a && UPT_TEMPLATE (parm) == TREE_PURPOSE (a))
if (a == 0) return unify (tparms, targs, ntparms, UPT_PARMS (parm),
TREE_VALUE (a), nsubsts);
/* FIXME: Should check base conversions here. */
return 1; return 1;
if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a))
/* different templates */
return 1;
return unify (tparms, targs, ntparms, UPT_PARMS (parm), TREE_VALUE (a),
nsubsts);
} }
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (parm)) if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm), return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
arg, nsubsts); arg, nsubsts);
...@@ -2295,6 +2303,9 @@ do_pending_expansions () ...@@ -2295,6 +2303,9 @@ do_pending_expansions ()
else if (! flag_implicit_templates) else if (! flag_implicit_templates)
DECIDE (0); DECIDE (0);
/* OK, it was an implicit instantiation. */
TREE_PUBLIC (t) = 0;
/* If it's a method, let the class type decide it. /* If it's a method, let the class type decide it.
@@ What if the method template is in a separate file? @@ What if the method template is in a separate file?
Maybe both file contexts should be taken into account? Maybe both file contexts should be taken into account?
...@@ -2425,17 +2436,14 @@ do_function_instantiation (declspecs, declarator, storage) ...@@ -2425,17 +2436,14 @@ do_function_instantiation (declspecs, declarator, storage)
if (flag_external_templates) if (flag_external_templates)
return; return;
if (DECL_EXPLICIT_INSTANTIATION (result) && TREE_PUBLIC (result))
return;
SET_DECL_EXPLICIT_INSTANTIATION (result); SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
if (storage == NULL_TREE) if (storage == NULL_TREE)
{ {
TREE_PUBLIC (result) = 1; DECL_INTERFACE_KNOWN (result) = 1;
DECL_EXTERNAL (result) = (DECL_INLINE (result) DECL_EXTERNAL (result) = 0;
&& ! flag_implement_inlines); TREE_STATIC (result) = 1;
TREE_STATIC (result) = ! DECL_EXTERNAL (result);
} }
else if (storage == ridpointers[(int) RID_EXTERN]) else if (storage == ridpointers[(int) RID_EXTERN])
; ;
...@@ -2475,7 +2483,7 @@ do_type_instantiation (name, storage) ...@@ -2475,7 +2483,7 @@ do_type_instantiation (name, storage)
} }
/* We've already instantiated this. */ /* We've already instantiated this. */
if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && CLASSTYPE_INTERFACE_KNOWN (t)) if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
{ {
if (! extern_p) if (! extern_p)
cp_pedwarn ("multiple explicit instantiation of `%#T'", t); cp_pedwarn ("multiple explicit instantiation of `%#T'", t);
...@@ -2485,22 +2493,29 @@ do_type_instantiation (name, storage) ...@@ -2485,22 +2493,29 @@ do_type_instantiation (name, storage)
if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
{ {
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (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) if (! extern_p)
{ {
SET_CLASSTYPE_INTERFACE_KNOWN (t);
CLASSTYPE_INTERFACE_ONLY (t) = 0;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
CLASSTYPE_DEBUG_REQUESTED (t) = 1; CLASSTYPE_DEBUG_REQUESTED (t) = 1;
TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
rest_of_type_compilation (t, 1); rest_of_type_compilation (t, 1);
} }
} }
instantiate_member_templates (TYPE_IDENTIFIER (t)); {
tree tmp;
/* Classes nested in template classes currently don't have an
IDENTIFIER_TEMPLATE--their out-of-line members are handled
by the enclosing template class. Note that there are name
conflict bugs with this approach. */
tmp = TYPE_IDENTIFIER (t);
if (IDENTIFIER_TEMPLATE (tmp))
instantiate_member_templates (tmp);
/* this should really be done by instantiate_member_templates */ /* this should really be done by instantiate_member_templates */
{ tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
for (; tmp; tmp = TREE_CHAIN (tmp)) for (; tmp; tmp = TREE_CHAIN (tmp))
{ {
if (DECL_TEMPLATE_SPECIALIZATION (tmp) if (DECL_TEMPLATE_SPECIALIZATION (tmp)
...@@ -2509,12 +2524,12 @@ do_type_instantiation (name, storage) ...@@ -2509,12 +2524,12 @@ do_type_instantiation (name, storage)
continue; continue;
SET_DECL_EXPLICIT_INSTANTIATION (tmp); SET_DECL_EXPLICIT_INSTANTIATION (tmp);
TREE_PUBLIC (tmp) = 1;
if (! extern_p) if (! extern_p)
{ {
TREE_PUBLIC (tmp) = 1; DECL_INTERFACE_KNOWN (tmp) = 1;
DECL_EXTERNAL (tmp) = (DECL_INLINE (tmp) DECL_EXTERNAL (tmp) = 0;
&& ! flag_implement_inlines); TREE_STATIC (tmp) = 1;
TREE_STATIC (tmp) = ! DECL_EXTERNAL (tmp);
} }
} }
......
...@@ -377,8 +377,8 @@ pop_memoized_context (use_old) ...@@ -377,8 +377,8 @@ pop_memoized_context (use_old)
type_stack = (struct type_level *)type_stack->base.prev; type_stack = (struct type_level *)type_stack->base.prev;
} }
#if 0 /* unused */
/* This is the newer recursive depth first search routine. */ /* This is the newer recursive depth first search routine. */
#if 0 /* unused */
/* Return non-zero if PARENT is directly derived from TYPE. By directly /* Return non-zero if PARENT is directly derived from TYPE. By directly
we mean it's only one step up the inheritance lattice. We check this we mean it's only one step up the inheritance lattice. We check this
by walking horizontally across the types that TYPE directly inherits by walking horizontally across the types that TYPE directly inherits
...@@ -1995,12 +1995,9 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals) ...@@ -1995,12 +1995,9 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
/* Should we use something besides CLASSTYPE_VFIELDS? */ /* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{ {
/* Get around first entry reserved for RTTI. */
tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo)); tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
/* Get around dossier entry if there is one. */
if (flag_dossier)
tmp = TREE_CHAIN (tmp);
while (tmp) while (tmp)
{ {
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp)); tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp));
...@@ -2417,10 +2414,10 @@ dfs_init_vbase_pointers (binfo) ...@@ -2417,10 +2414,10 @@ dfs_init_vbase_pointers (binfo)
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
/* If there is a dossier, it is the first field, though perhaps from /* If there is a rtti, it is the first field, though perhaps from
the base class. Otherwise, the first fields are virtual base class the base class. Otherwise, the first fields are virtual base class
pointer fields. */ pointer fields. */
if (CLASSTYPE_DOSSIER (type) && VFIELD_NAME_P (DECL_NAME (fields))) if (CLASSTYPE_RTTI (type) && VFIELD_NAME_P (DECL_NAME (fields)))
/* Get past vtable for the object. */ /* Get past vtable for the object. */
fields = TREE_CHAIN (fields); fields = TREE_CHAIN (fields);
......
...@@ -1250,8 +1250,7 @@ debug_binfo (elem) ...@@ -1250,8 +1250,7 @@ debug_binfo (elem)
virtuals = BINFO_VIRTUALS (elem); virtuals = BINFO_VIRTUALS (elem);
if (virtuals != 0) if (virtuals != 0)
{ {
virtuals = TREE_CHAIN (virtuals); /* skip the rtti type descriptor entry */
if (flag_dossier)
virtuals = TREE_CHAIN (virtuals); virtuals = TREE_CHAIN (virtuals);
} }
i = 1; i = 1;
......
...@@ -3404,6 +3404,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) ...@@ -3404,6 +3404,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0)); unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type) if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
/* We can shorten only if the shift count is less than the
number of bits in the smaller type size. */
&& TREE_INT_CST_HIGH (op1) == 0
&& TYPE_PRECISION (TREE_TYPE (arg0)) > TREE_INT_CST_LOW (op1)
/* If arg is sign-extended and then unsigned-shifted, /* If arg is sign-extended and then unsigned-shifted,
we can simulate this with a signed shift in arg's type we can simulate this with a signed shift in arg's type
only if the extended result is at least twice as wide only if the extended result is at least twice as wide
...@@ -3756,8 +3760,12 @@ build_x_unary_op (code, xarg) ...@@ -3756,8 +3760,12 @@ build_x_unary_op (code, xarg)
{ {
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
error message. */ error message. */
if (code != ADDR_EXPR || TREE_CODE (TREE_TYPE (xarg)) != RECORD_TYPE if (code == ADDR_EXPR
|| TYPE_SIZE (TREE_TYPE (xarg))) && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
&& TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE)
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* don't look for a function */;
else
{ {
tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
...@@ -3813,6 +3821,9 @@ build_unary_op (code, xarg, noconvert) ...@@ -3813,6 +3821,9 @@ build_unary_op (code, xarg, noconvert)
if (typecode == ENUMERAL_TYPE) if (typecode == ENUMERAL_TYPE)
typecode = INTEGER_TYPE; typecode = INTEGER_TYPE;
if (typecode == BOOLEAN_TYPE && ! noconvert)
typecode = INTEGER_TYPE;
isaggrtype = IS_AGGR_TYPE_CODE (typecode); isaggrtype = IS_AGGR_TYPE_CODE (typecode);
switch (code) switch (code)
...@@ -5435,7 +5446,14 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5435,7 +5446,14 @@ build_modify_expr (lhs, modifycode, rhs)
if (modifycode == INIT_EXPR) if (modifycode == INIT_EXPR)
{ {
if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_CONSTRUCTOR (lhstype)) if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
else if (! TYPE_HAS_CONSTRUCTOR (lhstype))
cp_error ("`%T' has no constructors", lhstype);
else if (! TYPE_NEEDS_CONSTRUCTING (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */;
else
{ {
result = build_method_call (lhs, constructor_name_full (lhstype), result = build_method_call (lhs, constructor_name_full (lhstype),
build_tree_list (NULL_TREE, rhs), build_tree_list (NULL_TREE, rhs),
...@@ -5449,7 +5467,17 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5449,7 +5467,17 @@ build_modify_expr (lhs, modifycode, rhs)
{ {
#if 1 #if 1
/* `operator=' is not an inheritable operator. */ /* `operator=' is not an inheritable operator. */
if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype)) if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
else if (! TYPE_HAS_ASSIGNMENT (lhstype))
cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype)
&& ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype)
/* FIXME find some way to deal with TARGET_EXPRs here. */
&& TREE_CODE (newrhs) != TARGET_EXPR
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */;
else
{ {
result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
lhs, rhs, make_node (NOP_EXPR)); lhs, rhs, make_node (NOP_EXPR));
...@@ -5655,6 +5683,8 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5655,6 +5683,8 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_SIDE_EFFECTS (newrhs)) if (TREE_SIDE_EFFECTS (newrhs))
newrhs = stabilize_reference (newrhs); newrhs = stabilize_reference (newrhs);
#if 0
/* This is now done by generating X(X&) and operator=(X&). */
/* C++: The semantics of C++ differ from those of C when an /* C++: The semantics of C++ differ from those of C when an
assignment of an aggregate is desired. Assignment in C++ is assignment of an aggregate is desired. Assignment in C++ is
now defined as memberwise assignment of non-static members now defined as memberwise assignment of non-static members
...@@ -5673,14 +5703,6 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5673,14 +5703,6 @@ build_modify_expr (lhs, modifycode, rhs)
|| (TREE_CODE (TREE_TYPE (newrhs)) == RECORD_TYPE || (TREE_CODE (TREE_TYPE (newrhs)) == RECORD_TYPE
&& UNIQUELY_DERIVED_FROM_P (lhstype, TREE_TYPE (newrhs))))) && UNIQUELY_DERIVED_FROM_P (lhstype, TREE_TYPE (newrhs)))))
{ {
/* This was decided in finish_struct. */
if (modifycode == INIT_EXPR)
cp_error ("can't generate default copy constructor for `%T'", lhstype);
else
cp_error ("can't generate default assignment operator for `%T'",
lhstype);
#if 0
/* This is now done by generating X(X&) and operator=(X&). */
tree vbases = CLASSTYPE_VBASECLASSES (lhstype); tree vbases = CLASSTYPE_VBASECLASSES (lhstype);
tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0); tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0);
tree rhs_addr; tree rhs_addr;
...@@ -5756,8 +5778,8 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5756,8 +5778,8 @@ build_modify_expr (lhs, modifycode, rhs)
TYPE_BINFO (lhstype)), TYPE_BINFO (lhstype)),
result); result);
return build_compound_expr (result); return build_compound_expr (result);
#endif
} }
#endif
/* Convert new value to destination type. */ /* Convert new value to destination type. */
...@@ -5811,6 +5833,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5811,6 +5833,7 @@ build_modify_expr (lhs, modifycode, rhs)
} }
else else
{ {
#if 0
if (IS_AGGR_TYPE (lhstype)) if (IS_AGGR_TYPE (lhstype))
{ {
if (result = build_opfncall (MODIFY_EXPR, if (result = build_opfncall (MODIFY_EXPR,
...@@ -5818,6 +5841,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5818,6 +5841,7 @@ build_modify_expr (lhs, modifycode, rhs)
make_node (NOP_EXPR))) make_node (NOP_EXPR)))
return result; return result;
} }
#endif
/* Avoid warnings on enum bit fields. */ /* Avoid warnings on enum bit fields. */
if (TREE_CODE (olhstype) == ENUMERAL_TYPE if (TREE_CODE (olhstype) == ENUMERAL_TYPE
&& TREE_CODE (lhstype) == INTEGER_TYPE) && TREE_CODE (lhstype) == INTEGER_TYPE)
...@@ -6603,8 +6627,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) ...@@ -6603,8 +6627,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
`convert_for_initialization'. They should otherwise be `convert_for_initialization'. They should otherwise be
bashed before coming here. */ bashed before coming here. */
else if (codel == REFERENCE_TYPE) else if (codel == REFERENCE_TYPE)
/* Force an abort. */ my_friendly_abort (317);
my_friendly_assert (codel != REFERENCE_TYPE, 317);
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs))) else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))
{ {
tree nrhs = build1 (NOP_EXPR, type, rhs); tree nrhs = build1 (NOP_EXPR, type, rhs);
...@@ -6742,6 +6765,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -6742,6 +6765,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
} }
/* Handle the case of default parameter initialization and /* Handle the case of default parameter initialization and
initialization of static variables. */ initialization of static variables. */
else if (TREE_CODE (rhs) == TARGET_EXPR)
return rhs;
else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs)) else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs))
{ {
my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318); my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318);
......
...@@ -329,7 +329,7 @@ ack (s, v, v2) ...@@ -329,7 +329,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */ same situation (call exit). */
/* First used: 0 (reserved), Last used: 360. Free: 261. */ /* First used: 0 (reserved), Last used: 361. Free: */
static int abortcount = 0; static int abortcount = 0;
...@@ -1342,6 +1342,7 @@ build_m_component_ref (datum, component) ...@@ -1342,6 +1342,7 @@ build_m_component_ref (datum, component)
if (TREE_CODE (objtype) == REFERENCE_TYPE) if (TREE_CODE (objtype) == REFERENCE_TYPE)
objtype = TREE_TYPE (objtype); objtype = TREE_TYPE (objtype);
objtype = TYPE_MAIN_VARIANT (objtype);
if (! IS_AGGR_TYPE (objtype)) if (! IS_AGGR_TYPE (objtype))
{ {
......
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