75th Cygnus<->FSF merge

From-SVN: r10438
This commit is contained in:
Mike Stump 1995-10-12 02:33:51 +00:00
parent c35836203c
commit f30432d726
28 changed files with 4008 additions and 2540 deletions

File diff suppressed because it is too large Load Diff

View File

@ -156,6 +156,55 @@ convert_harshness (type, parmtype, parm)
if (coder == ERROR_MARK) if (coder == ERROR_MARK)
return EVIL_RETURN (h); return EVIL_RETURN (h);
if (codel == REFERENCE_TYPE)
{
tree ttl, ttr;
int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
: TYPE_VOLATILE (parmtype));
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
ttl = TREE_TYPE (type);
/* Only allow const reference binding if we were given a parm to deal
with, since it isn't really a conversion. This is a hack to
prevent build_type_conversion from finding this conversion, but
still allow overloading to find it. */
if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
return EVIL_RETURN (h);
if (TYPE_READONLY (ttl) < constp
|| TYPE_VOLATILE (ttl) < volatilep)
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
little, so a non-const reference is preferred over this one. */
penalty = ((TYPE_READONLY (ttl) > constp)
+ (TYPE_VOLATILE (ttl) > volatilep));
ttl = TYPE_MAIN_VARIANT (ttl);
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
ttr = intype;
/* Maybe handle conversion to base here? */
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
h.code = QUAL_CODE;
h.int_penalty = penalty;
}
return h;
}
if (codel == POINTER_TYPE && fntype_p (parmtype)) if (codel == POINTER_TYPE && fntype_p (parmtype))
{ {
tree p1, p2; tree p1, p2;
@ -198,7 +247,7 @@ convert_harshness (type, parmtype, parm)
/* We allow the default conversion between function type /* We allow the default conversion between function type
and pointer-to-function type for free. */ and pointer-to-function type for free. */
if (type == parmtype) if (comptypes (type, parmtype, 1))
return h; return h;
if (pedantic) if (pedantic)
@ -421,10 +470,21 @@ convert_harshness (type, parmtype, parm)
} }
/* Convert arrays which have not previously been converted. */ /* Convert arrays which have not previously been converted. */
#if 0
if (codel == ARRAY_TYPE) if (codel == ARRAY_TYPE)
codel = POINTER_TYPE; codel = POINTER_TYPE;
#endif
if (coder == ARRAY_TYPE) if (coder == ARRAY_TYPE)
coder = POINTER_TYPE; {
coder = POINTER_TYPE;
if (parm)
{
parm = decay_conversion (parm);
parmtype = TREE_TYPE (parm);
}
else
parmtype = build_pointer_type (TREE_TYPE (parmtype));
}
/* Conversions among pointers */ /* Conversions among pointers */
if (codel == POINTER_TYPE && coder == POINTER_TYPE) if (codel == POINTER_TYPE && coder == POINTER_TYPE)
@ -462,7 +522,7 @@ convert_harshness (type, parmtype, parm)
ttr = unsigned_type (ttr); ttr = unsigned_type (ttr);
penalty = 10; penalty = 10;
} }
if (comp_target_types (ttl, ttr, 0) <= 0) if (comp_target_types (type, parmtype, 1) <= 0)
return EVIL_RETURN (h); return EVIL_RETURN (h);
} }
#else #else
@ -559,54 +619,6 @@ convert_harshness (type, parmtype, parm)
&& IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype))) && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
return ZERO_RETURN (h); return ZERO_RETURN (h);
if (codel == REFERENCE_TYPE)
{
tree ttl, ttr;
int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
: TYPE_VOLATILE (parmtype));
register tree intype = TYPE_MAIN_VARIANT (parmtype);
register enum tree_code form = TREE_CODE (intype);
int penalty = 0;
ttl = TREE_TYPE (type);
/* Only allow const reference binding if we were given a parm to deal
with, since it isn't really a conversion. This is a hack to
prevent build_type_conversion from finding this conversion, but
still allow overloading to find it. */
if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
return EVIL_RETURN (h);
if (TYPE_READONLY (ttl) < constp
|| TYPE_VOLATILE (ttl) < volatilep)
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
little, so a non-const reference is preferred over this one. */
penalty = ((TYPE_READONLY (ttl) > constp)
+ (TYPE_VOLATILE (ttl) > volatilep));
ttl = TYPE_MAIN_VARIANT (ttl);
if (form == OFFSET_TYPE)
{
intype = TREE_TYPE (intype);
form = TREE_CODE (intype);
}
ttr = intype;
/* Maybe handle conversion to base here? */
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
h.code = QUAL_CODE;
h.int_penalty = penalty;
}
return h;
}
if (codel == RECORD_TYPE && coder == RECORD_TYPE) if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{ {
int b_or_d = get_base_distance (type, parmtype, 0, 0); int b_or_d = get_base_distance (type, parmtype, 0, 0);
@ -625,6 +637,9 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h); return EVIL_RETURN (h);
} }
/* A clone of build_type_conversion for checking user-defined conversions in
overload resolution. */
int int
user_harshness (type, parmtype, parm) user_harshness (type, parmtype, parm)
register tree type, parmtype; register tree type, parmtype;
@ -1766,7 +1781,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{ {
basetype = SIGNATURE_TYPE (basetype); basetype = SIGNATURE_TYPE (basetype);
instance_ptr = build_optr_ref (instance); instance_ptr = build_optr_ref (instance);
instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr); instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
basetype_path = TYPE_BINFO (basetype); basetype_path = TYPE_BINFO (basetype);
} }
else else
@ -1788,7 +1803,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
within the scope of this function. */ within the scope of this function. */
if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)) if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
need_vtbl = maybe_needed; need_vtbl = maybe_needed;
instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance); instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);
} }
else else
{ {
@ -1883,7 +1898,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype = inst_ptr_basetype; basetype = inst_ptr_basetype;
else else
{ {
instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr); instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
if (instance_ptr == error_mark_node) if (instance_ptr == error_mark_node)
return error_mark_node; return error_mark_node;
} }
@ -1999,40 +2014,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes); parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
} }
if (flag_this_is_variable > 0) constp = 0;
{ volatilep = 0;
constp = 0; instance_ptr = build_int_2 (0, 0);
volatilep = 0; TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
instance_ptr = build_int_2 (0, 0); parms = tree_cons (NULL_TREE, instance_ptr, parms);
TREE_TYPE (instance_ptr) = TYPE_POINTER_TO (basetype);
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
else
{
constp = 0;
volatilep = 0;
instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0);
if (instance_ptr == error_mark_node)
return error_mark_node;
instance_ptr = save_expr (instance_ptr);
TREE_CALLS_NEW (instance_ptr) = 1;
instance = build_indirect_ref (instance_ptr, NULL_PTR);
#if 0
/* This breaks initialization of a reference from a new
expression of a different type. And it doesn't appear to
serve its original purpose any more, either. jason 10/12/94 */
/* If it's a default argument initialized from a ctor, what we get
from instance_ptr will match the arglist for the FUNCTION_DECL
of the constructor. */
if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR
&& TREE_OPERAND (TREE_VALUE (parms), 1)
&& TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
parms = build_tree_list (NULL_TREE, instance_ptr);
else
#endif
parms = tree_cons (NULL_TREE, instance_ptr, parms);
}
} }
parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes); parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
@ -2385,9 +2371,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
else if (ever_seen > 1) else if (ever_seen > 1)
{ {
TREE_CHAIN (last) = void_list_node; TREE_CHAIN (last) = void_list_node;
cp_error ("no matching function for call to `%T::%D (%A)'", cp_error ("no matching function for call to `%T::%D (%A)%V'",
TREE_TYPE (TREE_TYPE (instance_ptr)), TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))),
name, TREE_CHAIN (parmtypes)); name, TREE_CHAIN (parmtypes),
TREE_TYPE (TREE_TYPE (instance_ptr)));
TREE_CHAIN (last) = NULL_TREE; TREE_CHAIN (last) = NULL_TREE;
print_candidates (found_fns); print_candidates (found_fns);
} }
@ -2486,7 +2473,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function) if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
&& ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)) && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
cp_pedwarn ("inline function `%#D' called before definition", function); cp_warning ("inline function `%#D' called before definition", function);
fntype = TREE_TYPE (function); fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == POINTER_TYPE) if (TREE_CODE (fntype) == POINTER_TYPE)

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,15 @@ DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2) DEFTREECODE (DELETE_EXPR, "dl_expr", "e", 2)
DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2) DEFTREECODE (VEC_DELETE_EXPR, "vec_dl_expr", "e", 2)
/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs, that are protected
from being evaluated more than once should be reset so that a new
expand_expr call of this expr will cause those to be re-evaluated.
This is useful when we want to reuse a tree in different places,
but where we must re-expand. */
DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
/* Value is reference to particular overloaded class method. /* Value is reference to particular overloaded class method.
Operand 0 is the class name (an IDENTIFIER_NODE); Operand 0 is the class name (an IDENTIFIER_NODE);
operand 1 is the field (also an IDENTIFIER_NODE). operand 1 is the field (also an IDENTIFIER_NODE).

View File

@ -450,11 +450,12 @@ struct lang_type
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 has_abstract_assign_ref : 1; unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 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 : 20; unsigned dummy : 19;
unsigned n_vancestors : 16; unsigned n_vancestors : 16;
} type_flags; } type_flags;
@ -1054,6 +1055,9 @@ struct lang_decl
class where a virtual function instance is actually defined, and the class where a virtual function instance is actually defined, and the
lexical scope of a friend function defined in a class body. */ lexical scope of a friend function defined in a class body. */
#define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context) #define DECL_CLASS_CONTEXT(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.context)
#define DECL_REAL_CONTEXT(NODE) \
((TREE_CODE (NODE) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (NODE)) \
? DECL_CLASS_CONTEXT (NODE) : DECL_CONTEXT (NODE))
/* For a FUNCTION_DECL: the chain through which the next method /* For a FUNCTION_DECL: the chain through which the next method
in the method chain is found. We now use TREE_CHAIN to in the method chain is found. We now use TREE_CHAIN to
@ -1068,7 +1072,7 @@ struct lang_decl
#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method) #define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
/* In a VAR_DECL for a variable declared in a for statement, /* In a VAR_DECL for a variable declared in a for statement,
this is the shadowed (local) variable. */ this is the shadowed variable. */
#define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE) #define DECL_SHADOWED_FOR_VAR(NODE) DECL_RESULT(NODE)
/* Points back to the decl which caused this lang_decl to be allocated. */ /* Points back to the decl which caused this lang_decl to be allocated. */
@ -1218,6 +1222,13 @@ extern int flag_new_for_scope;
#define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE)) #define TYPE_NEEDS_CONSTRUCTING(NODE) (TYPE_LANG_FLAG_3(NODE))
#endif #endif
/* Nonzero means that an object of this type can not be initialized using
an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \
(TYPE_LANG_SPECIFIC (NODE)->type_flags.non_aggregate)
#define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if there is a user-defined X::op=(x&) for this class. */ /* Nonzero if there is a user-defined X::op=(x&) for this class. */
#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref) #define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref) #define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
@ -1953,6 +1964,7 @@ extern int root_lang_context_p PROTO((void));
extern tree instantiate_type PROTO((tree, tree, int)); extern tree instantiate_type PROTO((tree, tree, int));
extern void print_class_statistics PROTO((void)); extern void print_class_statistics PROTO((void));
extern void maybe_push_cache_obstack PROTO((void)); extern void maybe_push_cache_obstack PROTO((void));
extern unsigned HOST_WIDE_INT skip_rtti_stuff PROTO((tree *));
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree)); extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
@ -2030,7 +2042,7 @@ extern void cp_finish_decl PROTO((tree, tree, tree, int, int));
extern void expand_static_init PROTO((tree, tree)); extern void expand_static_init PROTO((tree, tree));
extern int complete_array_type PROTO((tree, tree, int)); extern int complete_array_type PROTO((tree, tree, int));
extern tree build_ptrmemfunc_type PROTO((tree)); extern tree build_ptrmemfunc_type PROTO((tree));
extern tree grokdeclarator (); /* PROTO((tree, tree, enum decl_context, int, tree)); */ /* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PROTO((tree)); extern int parmlist_is_exprlist PROTO((tree));
extern tree xref_tag PROTO((tree, tree, tree, int)); extern tree xref_tag PROTO((tree, tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree)); extern void xref_basetypes PROTO((tree, tree, tree, tree));
@ -2038,8 +2050,10 @@ extern tree start_enum PROTO((tree));
extern tree finish_enum PROTO((tree, tree)); extern tree finish_enum PROTO((tree, tree));
extern tree build_enumerator PROTO((tree, tree)); extern tree build_enumerator PROTO((tree, tree));
extern tree grok_enum_decls PROTO((tree, tree)); 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, tree, int));
extern void store_parm_decls PROTO((void)); extern void store_parm_decls PROTO((void));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_in_parms PROTO((struct rtx_def *));
extern void store_return_init PROTO((tree, tree)); extern void store_return_init PROTO((tree, tree));
extern void finish_function PROTO((int, 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));
@ -2059,8 +2073,8 @@ extern void grokclassfn PROTO((tree, tree, tree, enum overload_flags, tree));
extern tree grok_alignof PROTO((tree)); extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree)); extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int)); extern tree delete_sanity PROTO((tree, tree, int, int));
extern void check_classfn PROTO((tree, tree, tree)); extern tree check_classfn PROTO((tree, tree, tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree)); extern tree grokfield PROTO((tree, tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree)); extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree)); extern tree groktypefield PROTO((tree, tree));
extern tree grokoptypename PROTO((tree, tree)); extern tree grokoptypename PROTO((tree, tree));
@ -2093,6 +2107,7 @@ extern tree do_toplevel_using_decl PROTO((tree));
extern tree do_class_using_decl PROTO((tree)); extern tree do_class_using_decl PROTO((tree));
extern tree current_namespace_id PROTO((tree)); extern tree current_namespace_id PROTO((tree));
extern tree get_namespace_id PROTO((void)); extern tree get_namespace_id PROTO((void));
extern void check_default_args PROTO((tree));
/* in edsel.c */ /* in edsel.c */
@ -2113,12 +2128,16 @@ extern int might_have_exceptions_p PROTO((void));
extern void emit_exception_table PROTO((void)); extern void emit_exception_table PROTO((void));
extern tree build_throw PROTO((tree)); extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void)); extern void init_exception_processing PROTO((void));
extern void expand_builtin_throw PROTO((void));
extern void expand_start_eh_spec PROTO((void));
extern void expand_end_eh_spec PROTO((tree));
/* in expr.c */ /* in expr.c */
/* skip cplus_expand_expr */ /* skip cplus_expand_expr */
extern void init_cplus_expand PROTO((void)); extern void init_cplus_expand PROTO((void));
extern void fixup_result_decl PROTO((tree, struct rtx_def *)); extern void fixup_result_decl PROTO((tree, struct rtx_def *));
extern int decl_in_memory_p PROTO((tree)); extern int decl_in_memory_p PROTO((tree));
extern tree unsave_expr_now PROTO((tree));
/* in gc.c */ /* in gc.c */
extern int type_needs_gc_entry PROTO((tree)); extern int type_needs_gc_entry PROTO((tree));
@ -2232,6 +2251,7 @@ extern char *code_as_string PROTO((enum tree_code, int));
extern char *language_as_string PROTO((enum languages, int)); extern char *language_as_string PROTO((enum languages, int));
extern char *parm_as_string PROTO((int, int)); extern char *parm_as_string PROTO((int, int));
extern char *op_as_string PROTO((enum tree_code, int)); extern char *op_as_string PROTO((enum tree_code, int));
extern char *cv_as_string PROTO((tree, int));
/* in method.c */ /* in method.c */
extern void init_method PROTO((void)); extern void init_method PROTO((void));
@ -2367,13 +2387,15 @@ extern int promotes_to_aggr_type PROTO((tree, enum tree_code));
extern int is_aggr_type_2 PROTO((tree, tree)); extern int is_aggr_type_2 PROTO((tree, tree));
extern void message_2_types PROTO((void (*)(), char *, tree, tree)); extern void message_2_types PROTO((void (*)(), char *, tree, tree));
extern char *lang_printable_name PROTO((tree)); extern char *lang_printable_name PROTO((tree));
extern tree build_exception_variant PROTO((tree, tree, tree)); extern tree build_exception_variant PROTO((tree, tree));
extern tree copy_to_permanent PROTO((tree)); extern tree copy_to_permanent PROTO((tree));
extern void print_lang_statistics PROTO((void)); extern void print_lang_statistics PROTO((void));
/* skip __eprintf */ /* skip __eprintf */
extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_total PROTO((tree));
extern tree array_type_nelts_top PROTO((tree)); extern tree array_type_nelts_top PROTO((tree));
extern tree break_out_target_exprs PROTO((tree)); extern tree break_out_target_exprs PROTO((tree));
extern tree build_unsave_expr PROTO((tree));
extern int cp_expand_decl_cleanup PROTO((tree, tree));
/* in typeck.c */ /* in typeck.c */
extern tree condition_conversion PROTO((tree)); extern tree condition_conversion PROTO((tree));
@ -2397,6 +2419,7 @@ extern tree signed_or_unsigned_type PROTO((int, tree));
extern tree c_sizeof PROTO((tree)); extern tree c_sizeof PROTO((tree));
extern tree c_sizeof_nowarn PROTO((tree)); extern tree c_sizeof_nowarn PROTO((tree));
extern tree c_alignof PROTO((tree)); extern tree c_alignof PROTO((tree));
extern tree decay_conversion PROTO((tree));
extern tree default_conversion PROTO((tree)); extern tree default_conversion PROTO((tree));
extern tree build_object_ref PROTO((tree, tree, tree)); extern tree build_object_ref PROTO((tree, tree, tree));
extern tree build_component_ref_1 PROTO((tree, tree, int)); extern tree build_component_ref_1 PROTO((tree, tree, int));

View File

@ -180,6 +180,15 @@ cp_convert_to_pointer (type, expr)
return error_mark_node; return error_mark_node;
} }
if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE
|| (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
{
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
}
return build1 (NOP_EXPR, type, expr); return build1 (NOP_EXPR, type, expr);
} }
@ -904,7 +913,7 @@ convert_to_aggr (type, expr, msgp, protect)
/* The type of the first argument will be filled in inside the loop. */ /* The type of the first argument will be filled in inside the loop. */
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist); parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes); parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
#if 0 #if 0
method_name = build_decl_overload (name, parmtypes, 1); method_name = build_decl_overload (name, parmtypes, 1);
@ -1164,32 +1173,6 @@ convert_pointer_to (binfo, expr)
type = binfo; type = binfo;
return convert_pointer_to_real (type, expr); return convert_pointer_to_real (type, expr);
} }
/* Same as above, but don't abort if we get an "ambiguous" baseclass.
There's only one virtual baseclass we are looking for, and once
we find one such virtual baseclass, we have found them all. */
tree
convert_pointer_to_vbase (binfo, expr)
tree binfo;
tree expr;
{
tree intype = TREE_TYPE (TREE_TYPE (expr));
tree binfos = TYPE_BINFO_BASETYPES (intype);
int i;
for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
if (BINFO_TYPE (binfo) == basetype)
return convert_pointer_to (binfo, expr);
if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))
return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));
}
my_friendly_abort (6);
/* NOTREACHED */
return NULL_TREE;
}
/* Conversion... /* Conversion...
@ -1374,44 +1357,7 @@ cp_convert (type, expr, convtype, flags)
return conversion; return conversion;
else if (ctor) else if (ctor)
{ {
if (current_function_decl) ctor = build_cplus_new (type, ctor, 0);
/* 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
{
register tree parm = TREE_OPERAND (ctor, 1);
/* Initializers for static variables and parameters
have to handle doing the initialization and
cleanup themselves. */
my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322);
#if 0
/* The following assertion fails in cases where we
are initializing a static member variable of a
particular instance of a template class with a
call to a constructor of the given instance, as
in:
TMPL<int> object = TMPL<int>();
Curiously, the assertion does not fail if we do
the same thing for a static member of a
non-template class, as in:
T object = T();
I can't see why we should care here whether or not
the initializer expression involves a call to
`new', so for the time being, it seems best to
just avoid doing this assertion. */
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;
}
return ctor; return ctor;
} }
} }
@ -1524,7 +1470,14 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
If (FOR_SURE & 1) is non-zero, then we allow this type conversion If (FOR_SURE & 1) is non-zero, then we allow this type conversion
to take place immediately. Otherwise, we build a SAVE_EXPR to take place immediately. Otherwise, we build a SAVE_EXPR
which can be evaluated if the results are ever needed. */ which can be evaluated if the results are ever needed.
Changes to this functions should be mirrored in user_harshness.
FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */
tree tree
build_type_conversion (code, xtype, expr, for_sure) build_type_conversion (code, xtype, expr, for_sure)
@ -1604,10 +1557,9 @@ build_expr_type_conversion (desires, expr, complain)
tree winner = NULL_TREE; tree winner = NULL_TREE;
if (TREE_CODE (basetype) == OFFSET_TYPE) if (TREE_CODE (basetype) == OFFSET_TYPE)
{ expr = resolve_offset_ref (expr);
expr = resolve_offset_ref (expr); expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr); basetype = TREE_TYPE (expr);
}
if (! IS_AGGR_TYPE (basetype)) if (! IS_AGGR_TYPE (basetype))
switch (TREE_CODE (basetype)) switch (TREE_CODE (basetype))
@ -1641,11 +1593,16 @@ build_expr_type_conversion (desires, expr, complain)
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{ {
int win = 0; int win = 0;
tree candidate;
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
continue; continue;
switch (TREE_CODE (TREE_VALUE (conv))) candidate = TREE_VALUE (conv);
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
switch (TREE_CODE (candidate))
{ {
case BOOLEAN_TYPE: case BOOLEAN_TYPE:
case INTEGER_TYPE: case INTEGER_TYPE:
@ -1817,8 +1774,13 @@ tree
type_promotes_to (type) type_promotes_to (type)
tree type; tree type;
{ {
int constp = TYPE_READONLY (type); int constp, volatilep;
int volatilep = TYPE_VOLATILE (type);
if (type == error_mark_node)
return error_mark_node;
constp = TYPE_READONLY (type);
volatilep = TYPE_VOLATILE (type);
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same /* bool always promotes to int (not unsigned), even if it's the same

View File

@ -548,9 +548,9 @@ struct binding_level
/* The binding level which this one is contained in (inherits from). */ /* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain; struct binding_level *level_chain;
/* Number of decls in `names' that have incomplete /* List of decls in `names' that have incomplete
structure or union types. */ structure or union types. */
unsigned int n_incomplete; tree incomplete;
/* List of VAR_DECLS saved from a previous for statement. /* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might These would be dead in ANSI-conforming code, but might
@ -1488,7 +1488,7 @@ print_binding_level (lvl)
fprintf (stderr, " blocks="); fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks); fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d", fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
lvl->n_incomplete, lvl->parm_flag, lvl->keep); list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
if (lvl->tag_transparent) if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent"); fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok) if (lvl->more_cleanups_ok)
@ -2138,6 +2138,7 @@ pushtag (name, type, globalize)
d = make_type_decl (name, type); d = make_type_decl (name, type);
#else #else
d = build_decl (TYPE_DECL, name, type); d = build_decl (TYPE_DECL, name, type);
DECL_ASSEMBLER_NAME (d) = current_namespace_id (DECL_ASSEMBLER_NAME (d));
#endif #endif
SET_DECL_ARTIFICIAL (d); SET_DECL_ARTIFICIAL (d);
#ifdef DWARF_DEBUGGING_INFO #ifdef DWARF_DEBUGGING_INFO
@ -2806,9 +2807,9 @@ duplicate_decls (newdecl, olddecl)
{ {
tree ctype = NULL_TREE; tree ctype = NULL_TREE;
ctype = DECL_CLASS_CONTEXT (newdecl); ctype = DECL_CLASS_CONTEXT (newdecl);
TREE_TYPE (newdecl) = build_exception_variant (ctype, newtype, TREE_TYPE (newdecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))); TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
TREE_TYPE (olddecl) = build_exception_variant (ctype, newtype, TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype)); TYPE_RAISES_EXCEPTIONS (oldtype));
if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0)) if (! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
@ -3172,6 +3173,8 @@ pushdecl (x)
#endif #endif
if (TREE_CODE (t) == TYPE_DECL) if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t)); SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
return t; return t;
} }
@ -3395,6 +3398,7 @@ pushdecl (x)
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL) if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter"; warnstring = "declaration of `%s' shadows a parameter";
else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
&& current_class_decl
&& !TREE_STATIC (name)) && !TREE_STATIC (name))
warnstring = "declaration of `%s' shadows a member of `this'"; warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE) else if (oldlocal != NULL_TREE)
@ -3408,43 +3412,17 @@ pushdecl (x)
} }
if (TREE_CODE (x) == FUNCTION_DECL) if (TREE_CODE (x) == FUNCTION_DECL)
{ check_default_args (x);
/* This is probably the wrong place to check this, but it has to
come after the call to duplicate_decls. */
tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
int saw_def = 0, i = 1;
for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
{
if (TREE_PURPOSE (arg))
saw_def = 1;
else if (saw_def)
{
cp_error ("default argument missing for parameter %d of `%#D'",
i, x);
break;
}
}
}
/* Keep count of variables in this level with incomplete type. */ /* Keep count of variables in this level with incomplete type. */
if (TREE_CODE (x) != TEMPLATE_DECL
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
{
if (++b->n_incomplete == 0)
error ("too many incomplete variables at this point");
}
/* Keep count of variables in this level with incomplete type. */
/* RTTI TD entries are created while defining the type_info. */
if (TREE_CODE (x) == VAR_DECL if (TREE_CODE (x) == VAR_DECL
&& TREE_TYPE (x) != error_mark_node && TREE_TYPE (x) != error_mark_node
&& TYPE_LANG_SPECIFIC (TREE_TYPE (x)) && ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_BEING_DEFINED (TREE_TYPE (x))) && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
{ /* RTTI TD entries are created while defining the type_info. */
if (++b->n_incomplete == 0) || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
error ("too many incomplete variables at this point"); && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
} b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
} }
/* Put decls on list in reverse order. /* Put decls on list in reverse order.
@ -5428,11 +5406,11 @@ init_decl_processing ()
__i_desc_type_node = make_lang_type (RECORD_TYPE); __i_desc_type_node = make_lang_type (RECORD_TYPE);
__m_desc_type_node = make_lang_type (RECORD_TYPE); __m_desc_type_node = make_lang_type (RECORD_TYPE);
__t_desc_array_type = __t_desc_array_type =
build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE); build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE);
__i_desc_array_type = __i_desc_array_type =
build_array_type (TYPE_POINTER_TO (__i_desc_type_node), NULL_TREE); build_array_type (build_pointer_type (__i_desc_type_node), NULL_TREE);
__m_desc_array_type = __m_desc_array_type =
build_array_type (TYPE_POINTER_TO (__m_desc_type_node), NULL_TREE); build_array_type (build_pointer_type (__m_desc_type_node), NULL_TREE);
fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"), fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
string_type_node); string_type_node);
@ -5442,7 +5420,7 @@ init_decl_processing ()
unsigned_type_node); unsigned_type_node);
fields[3] = build_lang_field_decl (FIELD_DECL, fields[3] = build_lang_field_decl (FIELD_DECL,
get_identifier ("points_to"), get_identifier ("points_to"),
TYPE_POINTER_TO (__t_desc_type_node)); build_pointer_type (__t_desc_type_node));
fields[4] = build_lang_field_decl (FIELD_DECL, fields[4] = build_lang_field_decl (FIELD_DECL,
get_identifier ("ivars_count"), get_identifier ("ivars_count"),
integer_type_node); integer_type_node);
@ -5476,7 +5454,7 @@ init_decl_processing ()
fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"), fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("offset"),
integer_type_node); integer_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
TYPE_POINTER_TO (__t_desc_type_node)); build_pointer_type (__t_desc_type_node));
finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2, finish_builtin_type (__i_desc_type_node, "__i_desc", fields, 2,
integer_type_node); integer_type_node);
@ -5500,9 +5478,9 @@ init_decl_processing ()
fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"), fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("vindex"),
integer_type_node); integer_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"), fields[2] = build_lang_field_decl (FIELD_DECL, get_identifier ("vcontext"),
TYPE_POINTER_TO (__t_desc_type_node)); build_pointer_type (__t_desc_type_node));
fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"), fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("return_type"),
TYPE_POINTER_TO (__t_desc_type_node)); build_pointer_type (__t_desc_type_node));
fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"), fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("address"),
build_pointer_type (default_function_type)); build_pointer_type (default_function_type));
fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"), fields[5] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_count"),
@ -5510,7 +5488,7 @@ init_decl_processing ()
fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"), fields[6] = build_lang_field_decl (FIELD_DECL, get_identifier ("required_parms"),
short_integer_type_node); short_integer_type_node);
fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"), fields[7] = build_lang_field_decl (FIELD_DECL, get_identifier ("parm_types"),
build_pointer_type (build_array_type (TYPE_POINTER_TO (__t_desc_type_node), NULL_TREE))); build_pointer_type (build_array_type (build_pointer_type (__t_desc_type_node), NULL_TREE)));
finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7, finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
integer_type_node); integer_type_node);
} }
@ -5751,7 +5729,7 @@ shadow_tag (declspecs)
if (TYPE_FIELDS (t)) if (TYPE_FIELDS (t))
{ {
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0, tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL_TREE); NULL_TREE, NULL_TREE);
finish_anon_union (decl); finish_anon_union (decl);
} }
else else
@ -5792,7 +5770,7 @@ groktypename (typename)
return typename; return typename;
return grokdeclarator (TREE_VALUE (typename), return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename), TREE_PURPOSE (typename),
TYPENAME, 0, NULL_TREE); TYPENAME, 0, NULL_TREE, NULL_TREE);
} }
/* Decode a declarator in an ordinary declaration or data definition. /* Decode a declarator in an ordinary declaration or data definition.
@ -5836,7 +5814,8 @@ start_decl (declarator, declspecs, initialized, raises)
used_extern_spec = 1; used_extern_spec = 1;
} }
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises); decl = grokdeclarator (declarator, declspecs, NORMAL, initialized, raises,
NULL_TREE);
if (decl == NULL_TREE || decl == void_type_node) if (decl == NULL_TREE || decl == void_type_node)
return NULL_TREE; return NULL_TREE;
@ -6011,13 +5990,25 @@ start_decl (declarator, declspecs, initialized, raises)
else if (duplicate_decls (decl, field)) else if (duplicate_decls (decl, field))
decl = field; decl = field;
} }
else
/* If it was not explicitly declared `extern', {
revoke any previous claims of DECL_EXTERNAL. */ tree field = check_classfn (context, NULL_TREE, decl);
if (DECL_THIS_EXTERN (decl) == 0) if (field && duplicate_decls (decl, field))
DECL_EXTERNAL (decl) = 0; decl = field;
}
/* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set. */
if (DECL_LANG_SPECIFIC (decl)) if (DECL_LANG_SPECIFIC (decl))
DECL_IN_AGGR_P (decl) = 0; DECL_IN_AGGR_P (decl) = 0;
if (DECL_USE_TEMPLATE (decl) || CLASSTYPE_USE_TEMPLATE (context))
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
/* Stupid stupid stupid stupid (jason 7/21/95) */
if (pedantic && DECL_EXTERNAL (decl)
&& ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
pushclass (context, 2); pushclass (context, 2);
} }
@ -6164,7 +6155,7 @@ make_temporary_for_reference (decl, ctor_call, init, cleanupp)
} }
TREE_TYPE (tmp_addr) = build_pointer_type (target_type); TREE_TYPE (tmp_addr) = build_pointer_type (target_type);
DECL_INITIAL (decl) = convert (TYPE_POINTER_TO (target_type), tmp_addr); DECL_INITIAL (decl) = convert (build_pointer_type (target_type), tmp_addr);
TREE_TYPE (DECL_INITIAL (decl)) = type; TREE_TYPE (DECL_INITIAL (decl)) = type;
if (TYPE_NEEDS_CONSTRUCTING (target_type)) if (TYPE_NEEDS_CONSTRUCTING (target_type))
{ {
@ -6272,7 +6263,7 @@ grok_reference_init (decl, type, init, cleanupp)
if (TREE_CODE (tmp) == TARGET_EXPR) if (TREE_CODE (tmp) == TARGET_EXPR)
{ {
*cleanupp = build_delete *cleanupp = build_delete
(TYPE_POINTER_TO (subtype), (build_pointer_type (subtype),
build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0), build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
TREE_OPERAND (tmp, 2) = error_mark_node; TREE_OPERAND (tmp, 2) = error_mark_node;
@ -6515,7 +6506,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
init = digest_init (type, init, (tree *) 0); init = digest_init (type, init, (tree *) 0);
else if (TREE_CODE (init) == CONSTRUCTOR) else if (TREE_CODE (init) == CONSTRUCTOR)
{ {
if (TYPE_NEEDS_CONSTRUCTING (type)) if (TYPE_NON_AGGREGATE_CLASS (type))
{ {
cp_error ("`%D' must be initialized by constructor, not by `{...}'", cp_error ("`%D' must be initialized by constructor, not by `{...}'",
decl); decl);
@ -6524,47 +6515,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else else
goto dont_use_constructor; goto dont_use_constructor;
} }
#if 0
/* fix this in `build_functional_cast' instead.
Here's the trigger code:
struct ostream
{
ostream ();
ostream (int, char *);
ostream (char *);
operator char *();
ostream (void *);
operator void *();
operator << (int);
};
int buf_size = 1024;
static char buf[buf_size];
const char *debug(int i) {
char *b = &buf[0];
ostream o = ostream(buf_size, b);
o << i;
return buf;
}
*/
else if (TREE_CODE (init) == TARGET_EXPR
&& TREE_CODE (TREE_OPERAND (init, 1) == NEW_EXPR))
{
/* User wrote something like `foo x = foo (args)' */
my_friendly_assert (TREE_CODE (TREE_OPERAND (init, 0)) == VAR_DECL, 150);
my_friendly_assert (DECL_NAME (TREE_OPERAND (init, 0)) == NULL_TREE, 151);
/* User wrote exactly `foo x = foo (args)' */
if (TYPE_MAIN_VARIANT (type) == TREE_TYPE (init))
{
init = build (CALL_EXPR, TREE_TYPE (init),
TREE_OPERAND (TREE_OPERAND (init, 1), 0),
TREE_OPERAND (TREE_OPERAND (init, 1), 1), 0);
TREE_SIDE_EFFECTS (init) = 1;
}
}
#endif
} }
else else
{ {
@ -6859,11 +6809,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_STATIC (decl) && type != error_mark_node) else if (TREE_STATIC (decl) && type != error_mark_node)
{ {
/* Cleanups for static variables are handled by `finish_file'. */ /* Cleanups for static variables are handled by `finish_file'. */
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE) if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|| TYPE_NEEDS_DESTRUCTOR (type))
expand_static_init (decl, init); expand_static_init (decl, init);
else if (TYPE_NEEDS_DESTRUCTOR (type))
static_aggregates = perm_tree_cons (NULL_TREE, decl,
static_aggregates);
/* Make entry in appropriate vector. */ /* Make entry in appropriate vector. */
if (flag_gc && type_needs_gc_entry (type)) if (flag_gc && type_needs_gc_entry (type))
@ -6898,7 +6846,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{ {
/* XXX: Why don't we use decl here? */ /* XXX: Why don't we use decl here? */
/* Ans: Because it was already expanded? */ /* Ans: Because it was already expanded? */
if (! expand_decl_cleanup (NULL_TREE, cleanup)) if (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'", cp_error ("parser lost in parsing declaration of `%D'",
decl); decl);
/* Cleanup used up here. */ /* Cleanup used up here. */
@ -6928,7 +6876,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Store the cleanup, if there was one. */ /* Store the cleanup, if there was one. */
if (cleanup) if (cleanup)
{ {
if (! expand_decl_cleanup (decl, cleanup)) if (! cp_expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'", cp_error ("parser lost in parsing declaration of `%D'",
decl); decl);
} }
@ -6942,7 +6890,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
due to initialization of qualified member variable. due to initialization of qualified member variable.
I.e., Foo::x = 10; */ I.e., Foo::x = 10; */
{ {
tree context = DECL_CONTEXT (decl); tree context = DECL_REAL_CONTEXT (decl);
if (context if (context
&& TREE_CODE_CLASS (TREE_CODE (context)) == 't' && TREE_CODE_CLASS (TREE_CODE (context)) == 't'
&& (TREE_CODE (decl) == VAR_DECL && (TREE_CODE (decl) == VAR_DECL
@ -7036,13 +6984,14 @@ expand_static_init (decl, init)
old_cleanups = cleanups_this_call; old_cleanups = cleanups_this_call;
expand_assignment (temp, integer_one_node, 0, 0); expand_assignment (temp, integer_one_node, 0, 0);
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| TREE_CODE (init) == TREE_LIST) || (init && TREE_CODE (init) == TREE_LIST))
{ {
expand_aggr_init (decl, init, 0, 0); expand_aggr_init (decl, init, 0, 0);
do_pending_stack_adjust (); do_pending_stack_adjust ();
} }
else else if (init)
expand_assignment (decl, init, 0, 0); expand_assignment (decl, init, 0, 0);
/* Cleanup any temporaries needed for the initial value. */ /* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups); expand_cleanups_to (old_cleanups);
expand_end_cond (); expand_end_cond ();
@ -7200,12 +7149,12 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
not look, and -1 if we should not call `grokclassfn' at all. */ not look, and -1 if we should not call `grokclassfn' at all. */
static tree static tree
grokfndecl (ctype, type, declarator, virtualp, flags, quals, grokfndecl (ctype, type, declarator, virtualp, flags, quals,
raises, check, publicp, inlinep) raises, attrlist, check, publicp, inlinep)
tree ctype, type; tree ctype, type;
tree declarator; tree declarator;
int virtualp; int virtualp;
enum overload_flags flags; enum overload_flags flags;
tree quals, raises; tree quals, raises, attrlist;
int check, publicp, inlinep; int check, publicp, inlinep;
{ {
tree cname, decl; tree cname, decl;
@ -7219,7 +7168,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (raises) if (raises)
{ {
type = build_exception_variant (ctype, type, raises); type = build_exception_variant (type, raises);
raises = TYPE_RAISES_EXCEPTIONS (type); raises = TYPE_RAISES_EXCEPTIONS (type);
} }
decl = build_lang_decl (FUNCTION_DECL, declarator, type); decl = build_lang_decl (FUNCTION_DECL, declarator, type);
@ -7340,6 +7289,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
/* avoid creating circularities. */ /* avoid creating circularities. */
DECL_CHAIN (decl) = NULL_TREE; DECL_CHAIN (decl) = NULL_TREE;
} }
if (attrlist)
cplus_decl_attributes (decl, TREE_PURPOSE (attrlist),
TREE_VALUE (attrlist));
make_decl_rtl (decl, NULL_PTR, 1); make_decl_rtl (decl, NULL_PTR, 1);
} }
@ -7390,7 +7343,7 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes); type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes);
if (raises) if (raises)
{ {
type = build_exception_variant (ctype, type, raises); type = build_exception_variant (type, raises);
raises = TYPE_RAISES_EXCEPTIONS (type); raises = TYPE_RAISES_EXCEPTIONS (type);
} }
TREE_TYPE (decl) = type; TREE_TYPE (decl) = type;
@ -7500,6 +7453,7 @@ build_ptrmemfunc_type (type)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type)); push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
u = make_lang_type (UNION_TYPE); u = make_lang_type (UNION_TYPE);
IS_AGGR_TYPE (u) = 0;
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type); fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier, fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
delta_type_node); delta_type_node);
@ -7592,12 +7546,12 @@ build_ptrmemfunc_type (type)
enum return_types { return_normal, return_ctor, return_dtor, return_conversion }; enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
tree tree
grokdeclarator (declarator, declspecs, decl_context, initialized, raises) grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrlist)
tree declspecs; tree declspecs;
tree declarator; tree declarator;
enum decl_context decl_context; enum decl_context decl_context;
int initialized; int initialized;
tree raises; tree raises, attrlist;
{ {
RID_BIT_TYPE specbits; RID_BIT_TYPE specbits;
int nclasses = 0; int nclasses = 0;
@ -8034,7 +7988,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (return_type == return_dtor) if (return_type == return_dtor)
type = void_type_node; type = void_type_node;
else if (return_type == return_ctor) else if (return_type == return_ctor)
type = TYPE_POINTER_TO (ctor_return_type); type = build_pointer_type (ctor_return_type);
else if (return_type == return_conversion) else if (return_type == return_conversion)
type = ctor_return_type; type = ctor_return_type;
else if (current_class_type else if (current_class_type
@ -8077,7 +8031,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
else if (return_type == return_ctor) else if (return_type == return_ctor)
{ {
error ("return type specification for constructor invalid"); error ("return type specification for constructor invalid");
type = TYPE_POINTER_TO (ctor_return_type); type = build_pointer_type (ctor_return_type);
} }
else if (return_type == return_conversion) else if (return_type == return_conversion)
{ {
@ -8244,16 +8198,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
error ("non-object member `%s' cannot be declared `mutable'", name); error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits); RIDBIT_RESET (RID_MUTABLE, specbits);
} }
else if (constp)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
#if 0 #if 0
if (RIDBIT_SETP (RID_TYPEDEF, specbits)) if (RIDBIT_SETP (RID_TYPEDEF, specbits))
{ {
@ -8400,7 +8344,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1; SIGNATURE_GROKKING_TYPEDEF (current_class_type) = 1;
loc_typedecl = loc_typedecl =
grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE); grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
if (previous_declspec) if (previous_declspec)
TREE_CHAIN (previous_declspec) = scanner; TREE_CHAIN (previous_declspec) = scanner;
@ -8819,7 +8763,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (RIDBIT_ANY_SET (tmp_bits)) if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored"); error ("return value type specifier for constructor ignored");
} }
type = TYPE_POINTER_TO (ctype); type = build_pointer_type (ctype);
if (decl_context == FIELD && if (decl_context == FIELD &&
IS_SIGNATURE (current_class_type)) IS_SIGNATURE (current_class_type))
{ {
@ -9234,6 +9178,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* If this is declaring a typedef name, return a TYPE_DECL. */ /* If this is declaring a typedef name, return a TYPE_DECL. */
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (constp)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
if (RIDBIT_SETP (RID_TYPEDEF, specbits)) if (RIDBIT_SETP (RID_TYPEDEF, specbits))
{ {
tree decl; tree decl;
@ -9524,8 +9482,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
|| RIDBIT_SETP (RID_EXTERN, specbits) || RIDBIT_SETP (RID_EXTERN, specbits)
|| ! (funcdef_flag < 0 || inlinep)); || ! (funcdef_flag < 0 || inlinep));
decl = grokfndecl (ctype, type, declarator, decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, virtualp, flags, quals, raises, attrlist,
raises, friendp ? -1 : 0, publicp, inlinep); friendp ? -1 : 0, publicp, inlinep);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
decl = build_decl_attribute_variant (decl, decl_machine_attr); decl = build_decl_attribute_variant (decl, decl_machine_attr);
@ -9540,8 +9498,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
/* All method decls are public, so tell grokfndecl to set /* All method decls are public, so tell grokfndecl to set
TREE_PUBLIC, also. */ TREE_PUBLIC, also. */
decl = grokfndecl (ctype, type, declarator, decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals, virtualp, flags, quals, raises, attrlist,
raises, friendp ? -1 : 0, 1, 0); friendp ? -1 : 0, 1, 0);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
} }
@ -9634,6 +9592,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (staticp || (constp && initialized)) if (staticp || (constp && initialized))
{ {
/* ANSI C++ Apr '95 wp 9.2 */
if (staticp && declarator == current_class_name)
cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
declarator);
/* C++ allows static class members. /* C++ allows static class members.
All other work for this is done by grokfield. All other work for this is done by grokfield.
This VAR_DECL is built by build_lang_field_decl. This VAR_DECL is built by build_lang_field_decl.
@ -9715,8 +9678,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& !RIDBIT_SETP (RID_INLINE, specbits))); && !RIDBIT_SETP (RID_INLINE, specbits)));
decl = grokfndecl (ctype, type, original_name, decl = grokfndecl (ctype, type, original_name,
virtualp, flags, quals, virtualp, flags, quals, raises, attrlist,
raises,
processing_template_decl ? 0 : friendp ? 2 : 1, processing_template_decl ? 0 : friendp ? 2 : 1,
publicp, inlinep); publicp, inlinep);
if (decl == NULL_TREE) if (decl == NULL_TREE)
@ -9789,8 +9751,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
DECL_CONTEXT (decl) = ctype; DECL_CONTEXT (decl) = ctype;
if (staticp == 1) if (staticp == 1)
{ {
cp_error ("static member `%D' re-declared as static", cp_pedwarn ("static member `%D' re-declared as static", decl);
decl);
staticp = 0; staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits); RIDBIT_RESET (RID_STATIC, specbits);
} }
@ -9799,10 +9760,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
cp_error ("static member `%D' declared `register'", decl); cp_error ("static member `%D' declared `register'", decl);
RIDBIT_RESET (RID_REGISTER, specbits); RIDBIT_RESET (RID_REGISTER, specbits);
} }
if (RIDBIT_SETP (RID_EXTERN, specbits)) if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
{ {
cp_error ("cannot explicitly declare member `%#D' to have extern linkage", cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl); decl);
RIDBIT_RESET (RID_EXTERN, specbits); RIDBIT_RESET (RID_EXTERN, specbits);
} }
} }
@ -10005,7 +9966,8 @@ grokparms (first_parm, funcdef_flag)
/* @@ May need to fetch out a `raises' here. */ /* @@ May need to fetch out a `raises' here. */
decl = grokdeclarator (TREE_VALUE (decl), decl = grokdeclarator (TREE_VALUE (decl),
TREE_PURPOSE (decl), TREE_PURPOSE (decl),
PARM, init != NULL_TREE, NULL_TREE); PARM, init != NULL_TREE,
NULL_TREE, NULL_TREE);
if (! decl) if (! decl)
continue; continue;
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
@ -11130,8 +11092,8 @@ grok_enum_decls (type, decl)
@@ something we had previously. */ @@ something we had previously. */
int int
start_function (declspecs, declarator, raises, pre_parsed_p) start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
tree declarator, declspecs, raises; tree declspecs, declarator, raises, attrs;
int pre_parsed_p; int pre_parsed_p;
{ {
tree decl1, olddecl; tree decl1, olddecl;
@ -11162,6 +11124,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
protect_list = NULL_TREE; protect_list = NULL_TREE;
current_base_init_list = NULL_TREE; current_base_init_list = NULL_TREE;
current_member_init_list = NULL_TREE; current_member_init_list = NULL_TREE;
ctor_label = dtor_label = NULL_TREE;
clear_temp_name (); clear_temp_name ();
@ -11236,7 +11199,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
} }
else else
{ {
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises); decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, raises,
NULL_TREE);
/* If the declarator is not suitable for a function definition, /* If the declarator is not suitable for a function definition,
cause a syntax error. */ cause a syntax error. */
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0; if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
@ -11311,7 +11275,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
TREE_TYPE (decl1) TREE_TYPE (decl1)
= build_function_type (void_type_node, = build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl1))); TYPE_ARG_TYPES (TREE_TYPE (decl1)));
DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype)); DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (TREE_TYPE (fntype));
TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (TREE_TYPE (fntype));
} }
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
@ -11445,6 +11412,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
GNU_xref_function (decl1, current_function_parms); GNU_xref_function (decl1, current_function_parms);
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
make_function_rtl (decl1); make_function_rtl (decl1);
/* Allocate further tree nodes temporarily during compilation /* Allocate further tree nodes temporarily during compilation
@ -11465,9 +11434,15 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
restype = integer_type_node; restype = integer_type_node;
} }
if (DECL_RESULT (decl1) == NULL_TREE) if (DECL_RESULT (decl1) == NULL_TREE)
DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, restype); {
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
TREE_READONLY (DECL_RESULT (decl1)) = TYPE_READONLY (restype);
TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = TYPE_VOLATILE (restype);
}
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))) if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
&& DECL_LANGUAGE (decl1) == lang_cplusplus)
{ {
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
ctor_label = NULL_TREE; ctor_label = NULL_TREE;
@ -11487,6 +11462,30 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
return 1; return 1;
} }
void
expand_start_early_try_stmts ()
{
rtx insns;
start_sequence ();
expand_start_try_stmts ();
insns = get_insns ();
end_sequence ();
store_in_parms (insns);
}
void
store_in_parms (insns)
rtx insns;
{
rtx last_parm_insn;
last_parm_insn = get_first_nonparm_insn ();
if (last_parm_insn == NULL_RTX)
emit_insns (insns);
else
emit_insns_before (insns, previous_insn (last_parm_insn));
}
/* Store the parameter declarations into the current function declaration. /* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before This is called after parsing the parameter declarations, before
digesting the body of the function. digesting the body of the function.
@ -11576,7 +11575,7 @@ store_parm_decls ()
if (cleanup) if (cleanup)
{ {
expand_decl (parm); expand_decl (parm);
if (! expand_decl_cleanup (parm, cleanup)) if (! cp_expand_decl_cleanup (parm, cleanup))
cp_error ("parser lost in parsing declaration of `%D'", cp_error ("parser lost in parsing declaration of `%D'",
parm); parm);
parms_have_cleanups = 1; parms_have_cleanups = 1;
@ -11626,7 +11625,7 @@ store_parm_decls ()
if (flag_gc) if (flag_gc)
{ {
maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node); maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
if (! expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup)) if (! cp_expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
cp_error ("parser lost in parsing declaration of `%D'", fndecl); cp_error ("parser lost in parsing declaration of `%D'", fndecl);
} }
@ -11648,6 +11647,26 @@ store_parm_decls ()
output_builtin_tdesc_entries (); output_builtin_tdesc_entries ();
#endif #endif
} }
/* Take care of exception handling things. */
if (flag_handle_exceptions)
{
rtx insns;
start_sequence ();
/* Mark the start of a stack unwinder if we need one. */
start_eh_unwinder ();
/* Do the starting of the exception specifications, if we have any. */
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
expand_start_eh_spec ();
insns = get_insns ();
end_sequence ();
if (insns)
store_in_parms (insns);
}
} }
/* Bind a name and initialization to the return value of /* Bind a name and initialization to the return value of
@ -11722,7 +11741,7 @@ finish_function (lineno, call_poplevel, nested)
{ {
register tree fndecl = current_function_decl; register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE; tree fntype, ctype = NULL_TREE;
rtx head, last_parm_insn, mark; rtx last_parm_insn, insns;
/* Label to use if this function is supposed to return a value. */ /* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE; tree no_return_label = NULL_TREE;
tree decls = NULL_TREE; tree decls = NULL_TREE;
@ -11784,12 +11803,9 @@ finish_function (lineno, call_poplevel, nested)
/* If this destructor is empty, then we don't need to check /* If this destructor is empty, then we don't need to check
whether `this' is NULL in some cases. */ whether `this' is NULL in some cases. */
mark = get_last_insn ();
last_parm_insn = get_first_nonparm_insn ();
if ((flag_this_is_variable & 1) == 0) if ((flag_this_is_variable & 1) == 0)
ok_to_optimize_dtor = 1; ok_to_optimize_dtor = 1;
else if (mark == last_parm_insn) else if (get_last_insn () == get_first_nonparm_insn ())
ok_to_optimize_dtor ok_to_optimize_dtor
= (n_baseclasses == 0 = (n_baseclasses == 0
|| (n_baseclasses == 1 || (n_baseclasses == 1
@ -11854,8 +11870,8 @@ finish_function (lineno, call_poplevel, nested)
{ {
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases))) if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
{ {
tree ptr = convert_pointer_to_vbase (vbases, current_class_decl); tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl);
expand_expr_stmt (build_delete (TYPE_POINTER_TO (BINFO_TYPE (vbases)), expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
ptr, integer_zero_node, ptr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0)); LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
} }
@ -11879,7 +11895,7 @@ finish_function (lineno, call_poplevel, nested)
exprstmt = exprstmt =
build_method_call build_method_call
(build_indirect_ref (build_indirect_ref
(build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), (build1 (NOP_EXPR, build_pointer_type (current_class_type),
error_mark_node), error_mark_node),
NULL_PTR), NULL_PTR),
ansi_opname[(int) DELETE_EXPR], ansi_opname[(int) DELETE_EXPR],
@ -11907,12 +11923,8 @@ finish_function (lineno, call_poplevel, nested)
/* Back to the top of destructor. */ /* Back to the top of destructor. */
/* Dont execute destructor code if `this' is NULL. */ /* Dont execute destructor code if `this' is NULL. */
mark = get_last_insn ();
last_parm_insn = get_first_nonparm_insn (); start_sequence ();
if (last_parm_insn == NULL_RTX)
last_parm_insn = mark;
else
last_parm_insn = previous_insn (last_parm_insn);
/* Make all virtual function table pointers in non-virtual base /* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function classes point to CURRENT_CLASS_TYPE's virtual function
@ -11926,8 +11938,18 @@ finish_function (lineno, call_poplevel, nested)
current_class_decl, integer_zero_node, 1); current_class_decl, integer_zero_node, 1);
expand_start_cond (cond, 0); expand_start_cond (cond, 0);
} }
if (mark != get_last_insn ())
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); insns = get_insns ();
end_sequence ();
last_parm_insn = get_first_nonparm_insn ();
if (last_parm_insn == NULL_RTX)
last_parm_insn = get_last_insn ();
else
last_parm_insn = previous_insn (last_parm_insn);
emit_insns_after (insns, last_parm_insn);
if (! ok_to_optimize_dtor) if (! ok_to_optimize_dtor)
expand_end_cond (); expand_end_cond ();
} }
@ -11981,11 +12003,7 @@ finish_function (lineno, call_poplevel, nested)
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals; CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
/* must keep the first insn safe. */ start_sequence ();
head = get_insns ();
/* this note will come up to the top with us. */
mark = get_last_insn ();
if (flag_this_is_variable > 0) if (flag_this_is_variable > 0)
{ {
@ -12008,6 +12026,9 @@ finish_function (lineno, call_poplevel, nested)
base_init_expr = NULL_TREE; base_init_expr = NULL_TREE;
} }
insns = get_insns ();
end_sequence ();
/* This is where the body of the constructor begins. /* This is where the body of the constructor begins.
If there were no insns in this function body, then the If there were no insns in this function body, then the
last_parm_insn is also the last insn. last_parm_insn is also the last insn.
@ -12016,12 +12037,11 @@ finish_function (lineno, call_poplevel, nested)
we don't hold on to it (across emit_base_init). */ we don't hold on to it (across emit_base_init). */
last_parm_insn = get_first_nonparm_insn (); last_parm_insn = get_first_nonparm_insn ();
if (last_parm_insn == NULL_RTX) if (last_parm_insn == NULL_RTX)
last_parm_insn = mark; last_parm_insn = get_last_insn ();
else else
last_parm_insn = previous_insn (last_parm_insn); last_parm_insn = previous_insn (last_parm_insn);
if (mark != get_last_insn ()) emit_insns_after (insns, last_parm_insn);
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
end_protect_partials (); end_protect_partials ();
@ -12118,7 +12138,7 @@ finish_function (lineno, call_poplevel, nested)
expand_function_end (input_filename, lineno, 1); expand_function_end (input_filename, lineno, 1);
if (flag_handle_exceptions) if (flag_handle_exceptions)
expand_exception_blocks(); expand_exception_blocks ();
/* This must come after expand_function_end because cleanups might /* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into have declarations (from inline functions) that need to go into
@ -12259,7 +12279,8 @@ tree
start_method (declspecs, declarator, raises) start_method (declspecs, declarator, raises)
tree declarator, declspecs, raises; tree declarator, declspecs, raises;
{ {
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises); tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0, raises,
NULL_TREE);
/* Something too ugly to handle. */ /* Something too ugly to handle. */
if (fndecl == NULL_TREE) if (fndecl == NULL_TREE)
@ -12430,46 +12451,43 @@ void
hack_incomplete_structures (type) hack_incomplete_structures (type)
tree type; tree type;
{ {
tree decl; tree *list;
if (current_binding_level->n_incomplete == 0) if (current_binding_level->incomplete == NULL_TREE)
return; return;
if (!type) /* Don't do this for class templates. */ if (!type) /* Don't do this for class templates. */
return; return;
for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) for (list = &current_binding_level->incomplete; *list; )
if (TREE_TYPE (decl) == type {
|| (TREE_TYPE (decl) tree decl = TREE_VALUE (*list);
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE if (decl && TREE_TYPE (decl) == type
&& TREE_TYPE (TREE_TYPE (decl)) == type)) || (TREE_TYPE (decl)
{ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
if (TREE_CODE (decl) == TYPE_DECL) && TREE_TYPE (TREE_TYPE (decl)) == type))
layout_type (TREE_TYPE (decl)); {
else int toplevel = toplevel_bindings_p ();
{ if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
int toplevel = toplevel_bindings_p (); && TREE_TYPE (TREE_TYPE (decl)) == type)
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE layout_type (TREE_TYPE (decl));
&& TREE_TYPE (TREE_TYPE (decl)) == type) layout_decl (decl, 0);
layout_type (TREE_TYPE (decl)); rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
layout_decl (decl, 0); if (! toplevel)
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); {
if (! toplevel) tree cleanup;
{ expand_decl (decl);
tree cleanup; cleanup = maybe_build_cleanup (decl);
expand_decl (decl); expand_decl_init (decl);
cleanup = maybe_build_cleanup (decl); if (! cp_expand_decl_cleanup (decl, cleanup))
expand_decl_init (decl); cp_error ("parser lost in parsing declaration of `%D'",
if (! expand_decl_cleanup (decl, cleanup)) decl);
cp_error ("parser lost in parsing declaration of `%D'", }
decl); *list = TREE_CHAIN (*list);
} }
} else
/* list = &TREE_CHAIN (*list);
my_friendly_assert (current_binding_level->n_incomplete > 0, 164); }
*/
--current_binding_level->n_incomplete;
}
} }
/* Nonzero if presently building a cleanup. Needed because /* Nonzero if presently building a cleanup. Needed because
@ -12620,13 +12638,20 @@ revert_static_member_fn (decl, fn, argtypes)
tree function = fn ? *fn : TREE_TYPE (*decl); tree function = fn ? *fn : TREE_TYPE (*decl);
tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function); tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (args))))
cp_error ("static member function `%#D' declared const", *decl);
if (TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (args))))
cp_error ("static member function `%#D' declared volatile", *decl);
args = TREE_CHAIN (args); args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args); tmp = build_function_type (TREE_TYPE (function), args);
tmp = build_type_variant (tmp, TYPE_READONLY (function), tmp = build_type_variant (tmp, TYPE_READONLY (function),
TYPE_VOLATILE (function)); TYPE_VOLATILE (function));
tmp = build_exception_variant (TYPE_METHOD_BASETYPE (function), tmp, tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function)); TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp; TREE_TYPE (*decl) = tmp;
if (DECL_ARGUMENTS (*decl))
DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl));
DECL_STATIC_FUNCTION_P (*decl) = 1; DECL_STATIC_FUNCTION_P (*decl) = 1;
if (fn) if (fn)
*fn = tmp; *fn = tmp;

View File

@ -30,6 +30,9 @@ enum decl_context
MEMFUNCDEF /* Member function definition */ MEMFUNCDEF /* Member function definition */
}; };
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator PROTO((tree, tree, enum decl_context, int, tree, tree));
/* C++: Keep these around to reduce calls to `get_identifier'. /* C++: Keep these around to reduce calls to `get_identifier'.
Identifiers for `this' in member functions and the auto-delete Identifiers for `this' in member functions and the auto-delete
parameter for destructors. */ parameter for destructors. */

View File

@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h" #include "output.h"
#include "defaults.h" #include "defaults.h"
extern tree grokdeclarator ();
extern tree get_file_function_name (); extern tree get_file_function_name ();
extern tree cleanups_this_call; extern tree cleanups_this_call;
static void grok_function_init (); static void grok_function_init ();
@ -677,7 +676,7 @@ grok_method_quals (ctype, function, quals)
? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) ? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
: TYPE_ARG_TYPES (fntype))); : TYPE_ARG_TYPES (fntype)));
if (raises) if (raises)
fntype = build_exception_variant (ctype, fntype, raises); fntype = build_exception_variant (fntype, raises);
TREE_TYPE (function) = fntype; TREE_TYPE (function) = fntype;
return ctype; return ctype;
@ -719,8 +718,11 @@ warn_if_unknown_interface (decl)
int sl = lineno; int sl = lineno;
char *sf = input_filename; char *sf = input_filename;
lineno = til->line; if (til)
input_filename = til->file; {
lineno = til->line;
input_filename = til->file;
}
cp_warning ("template `%#D' instantiated in file without #pragma interface", cp_warning ("template `%#D' instantiated in file without #pragma interface",
decl); decl);
lineno = sl; lineno = sl;
@ -864,6 +866,8 @@ grokclassfn (ctype, cname, function, flags, quals)
tree arg_types; tree arg_types;
tree parm; tree parm;
tree qualtype; tree qualtype;
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
if (fn_name == NULL_TREE) if (fn_name == NULL_TREE)
{ {
@ -959,8 +963,13 @@ grokclassfn (ctype, cname, function, flags, quals)
/* This is the same chain as DECL_ARGUMENTS (...). */ /* This is the same chain as DECL_ARGUMENTS (...). */
TREE_CHAIN (last_function_parms) = parm; TREE_CHAIN (last_function_parms) = parm;
TREE_TYPE (function) = build_cplus_method_type (qualtype, void_type_node, fntype = build_cplus_method_type (qualtype, void_type_node,
arg_types); arg_types);
if (raises)
{
fntype = build_exception_variant (fntype, raises);
}
TREE_TYPE (function) = fntype;
TYPE_HAS_DESTRUCTOR (ctype) = 1; TYPE_HAS_DESTRUCTOR (ctype) = 1;
} }
else else
@ -971,10 +980,14 @@ grokclassfn (ctype, cname, function, flags, quals)
{ {
arg_types = hash_tree_chain (integer_type_node, arg_types = hash_tree_chain (integer_type_node,
TREE_CHAIN (arg_types)); TREE_CHAIN (arg_types));
TREE_TYPE (function) fntype = build_cplus_method_type (qualtype,
= build_cplus_method_type (qualtype, TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (function)), arg_types);
arg_types); if (raises)
{
fntype = build_exception_variant (fntype, raises);
}
TREE_TYPE (function) = fntype;
arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
} }
@ -982,7 +995,7 @@ grokclassfn (ctype, cname, function, flags, quals)
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */ /* Only true for static member functions. */
these_arg_types = hash_tree_chain (TYPE_POINTER_TO (qualtype), these_arg_types = hash_tree_chain (build_pointer_type (qualtype),
arg_types); arg_types);
DECL_ASSEMBLER_NAME (function) DECL_ASSEMBLER_NAME (function)
@ -1213,7 +1226,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
really a member of the class (CTYPE) it is supposed to belong to. really a member of the class (CTYPE) it is supposed to belong to.
CNAME is the same here as it is for grokclassfn above. */ CNAME is the same here as it is for grokclassfn above. */
void tree
check_classfn (ctype, cname, function) check_classfn (ctype, cname, function)
tree ctype, cname, function; tree ctype, cname, function;
{ {
@ -1229,8 +1242,7 @@ check_classfn (ctype, cname, function)
end = TREE_VEC_END (method_vec); end = TREE_VEC_END (method_vec);
/* First suss out ctors and dtors. */ /* First suss out ctors and dtors. */
if (*methods if (*methods && fn_name == DECL_NAME (*methods))
&& (fn_name == cname || fn_name == DECL_NAME (*methods)))
goto got_it; goto got_it;
while (++methods != end) while (++methods != end)
@ -1242,14 +1254,14 @@ check_classfn (ctype, cname, function)
while (fndecl) while (fndecl)
{ {
if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl)) if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
return; return fndecl;
#if 0 #if 0
/* This should work, but causes libg++ to fail /* This should work, but causes libg++ to fail
make check-tFix. */ make check-tFix. */
/* We have to do more extensive argument checking here, as /* We have to do more extensive argument checking here, as
the name may have been changed by asm("new_name"). */ the name may have been changed by asm("new_name"). */
if (decls_match (function, fndecl)) if (decls_match (function, fndecl))
return; return fndecl;
#else #else
if (DECL_NAME (function) == DECL_NAME (fndecl)) if (DECL_NAME (function) == DECL_NAME (fndecl))
{ {
@ -1265,7 +1277,12 @@ check_classfn (ctype, cname, function)
if (comptypes (TREE_TYPE (TREE_TYPE (function)), if (comptypes (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)), 1) TREE_TYPE (TREE_TYPE (fndecl)), 1)
&& compparms (p1, p2, 3)) && compparms (p1, p2, 3))
return; {
if (DECL_STATIC_FUNCTION_P (fndecl)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
revert_static_member_fn (&function, NULL, NULL);
return fndecl;
}
} }
#endif #endif
fndecl = DECL_CHAIN (fndecl); fndecl = DECL_CHAIN (fndecl);
@ -1276,8 +1293,15 @@ check_classfn (ctype, cname, function)
} }
if (methods != end) if (methods != end)
cp_error ("argument list for `%#D' does not match any in class `%T'", {
function, ctype); tree fndecl = *methods;
cp_error ("prototype for `%#D' does not match any in class `%T'",
function, ctype);
cp_error_at ("candidate%s: %+#D", DECL_CHAIN (fndecl) ? "s are" : " is",
fndecl);
while (fndecl = DECL_CHAIN (fndecl), fndecl)
cp_error_at (" %#D", fndecl);
}
else else
{ {
methods = 0; methods = 0;
@ -1288,6 +1312,7 @@ check_classfn (ctype, cname, function)
/* If we did not find the method in the class, add it to /* If we did not find the method in the class, add it to
avoid spurious errors. */ avoid spurious errors. */
add_method (ctype, methods, function); add_method (ctype, methods, function);
return NULL_TREE;
} }
/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
@ -1311,8 +1336,8 @@ check_classfn (ctype, cname, function)
CHANGES TO CODE IN `start_method'. */ CHANGES TO CODE IN `start_method'. */
tree tree
grokfield (declarator, declspecs, raises, init, asmspec_tree) grokfield (declarator, declspecs, raises, init, asmspec_tree, attrlist)
tree declarator, declspecs, raises, init, asmspec_tree; tree declarator, declspecs, raises, init, asmspec_tree, attrlist;
{ {
register tree value; register tree value;
char *asmspec = 0; char *asmspec = 0;
@ -1337,7 +1362,8 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
&& TREE_CHAIN (init) == NULL_TREE) && TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE; init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises); value = grokdeclarator (declarator, declspecs, FIELD, init != 0,
raises, attrlist);
if (! value) if (! value)
return value; /* friend or constructor went bad. */ return value; /* friend or constructor went bad. */
@ -1509,6 +1535,7 @@ grokfield (declarator, declspecs, raises, init, asmspec_tree)
} }
if (TREE_CODE (value) == FUNCTION_DECL) if (TREE_CODE (value) == FUNCTION_DECL)
{ {
check_default_args (value);
if (DECL_CHAIN (value) != NULL_TREE) if (DECL_CHAIN (value) != NULL_TREE)
{ {
/* Need a fresh node here so that we don't get circularity /* Need a fresh node here so that we don't get circularity
@ -1551,7 +1578,8 @@ tree
grokbitfield (declarator, declspecs, width) grokbitfield (declarator, declspecs, width)
tree declarator, declspecs, width; tree declarator, declspecs, width;
{ {
register tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL_TREE); register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
0, NULL_TREE, NULL_TREE);
if (! value) return NULL_TREE; /* friends went bad. */ if (! value) return NULL_TREE; /* friends went bad. */
@ -1754,7 +1782,7 @@ groktypefield (declspecs, parmlist)
found: found:
decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE), decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE),
declspecs, FIELD, 0, NULL_TREE); declspecs, FIELD, 0, NULL_TREE, NULL_TREE);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
@ -1797,7 +1825,8 @@ tree
grokoptypename (declspecs, declarator) grokoptypename (declspecs, declarator)
tree declspecs, declarator; tree declspecs, declarator;
{ {
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE); tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0,
NULL_TREE, NULL_TREE);
return build_typename_overload (t); return build_typename_overload (t);
} }
@ -2037,7 +2066,7 @@ constructor_name (thing)
void void
setup_vtbl_ptr () setup_vtbl_ptr ()
{ {
extern rtx base_init_expr; extern tree base_init_expr;
if (base_init_expr == 0 if (base_init_expr == 0
&& DECL_CONSTRUCTOR_P (current_function_decl)) && DECL_CONSTRUCTOR_P (current_function_decl))
@ -2199,6 +2228,11 @@ finish_anon_union (anon_union_decl)
if (TREE_CODE (field) != FIELD_DECL) if (TREE_CODE (field) != FIELD_DECL)
continue; continue;
if (TREE_PRIVATE (field))
cp_pedwarn_at ("private member `%#D' in anonymous union", field);
else if (TREE_PROTECTED (field))
cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
/* tell `pushdecl' that this is not tentative. */ /* tell `pushdecl' that this is not tentative. */
DECL_INITIAL (decl) = error_mark_node; DECL_INITIAL (decl) = error_mark_node;
@ -2449,7 +2483,9 @@ static void
mark_vtable_entries (decl) mark_vtable_entries (decl)
tree decl; tree decl;
{ {
tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl))); tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
skip_rtti_stuff (&entries);
for (; entries; entries = TREE_CHAIN (entries)) for (; entries; entries = TREE_CHAIN (entries))
{ {
@ -2757,7 +2793,7 @@ import_export_inline (decl)
else if (DECL_FUNCTION_MEMBER_P (decl)) else if (DECL_FUNCTION_MEMBER_P (decl))
{ {
tree ctype = DECL_CLASS_CONTEXT (decl); tree ctype = DECL_CLASS_CONTEXT (decl);
if (CLASSTYPE_INTERFACE_KNOWN (ctype)) if (CLASSTYPE_INTERFACE_KNOWN (ctype) && ! DECL_ARTIFICIAL (decl))
{ {
DECL_NOT_REALLY_EXTERN (decl) DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype) = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
@ -2874,7 +2910,10 @@ finish_file ()
goto mess_up; goto mess_up;
fnname = get_file_function_name ('D'); fnname = get_file_function_name ('D');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname, void_list_node,
NULL_TREE),
NULL_TREE, NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl); fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls (); store_parm_decls ();
@ -2900,7 +2939,7 @@ finish_file ()
else else
{ {
mark_addressable (decl); mark_addressable (decl);
temp = build1 (ADDR_EXPR, TYPE_POINTER_TO (type), decl); temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
} }
temp = build_delete (TREE_TYPE (temp), temp, temp = build_delete (TREE_TYPE (temp), temp,
integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
@ -2931,7 +2970,10 @@ finish_file ()
if (needs_messing_up) if (needs_messing_up)
{ {
fnname = get_file_function_name ('I'); fnname = get_file_function_name ('I');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname,
void_list_node, NULL_TREE),
NULL_TREE, NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl); fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls (); store_parm_decls ();
@ -2973,40 +3015,6 @@ finish_file ()
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl); DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1; DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
#if 0
if (init)
{
if (TREE_CODE (init) == VAR_DECL)
{
/* This behavior results when there are
multiple declarations of an aggregate,
the last of which defines it. */
if (DECL_RTL (init) == DECL_RTL (decl))
{
my_friendly_assert (DECL_INITIAL (decl) == error_mark_node
|| (TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
&& CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) == NULL_TREE),
199);
init = DECL_INITIAL (init);
if (TREE_CODE (init) == CONSTRUCTOR
&& CONSTRUCTOR_ELTS (init) == NULL_TREE)
init = NULL_TREE;
}
else if (TREE_TYPE (decl) == TREE_TYPE (init))
{
#if 1
my_friendly_abort (200);
#else
/* point to real decl's rtl anyway. */
DECL_RTL (init) = DECL_RTL (decl);
my_friendly_assert (DECL_INITIAL (decl) == error_mark_node,
201);
init = DECL_INITIAL (init);
#endif /* 1 */
}
}
}
#endif /* 0 */
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0); expand_aggr_init (decl, init, 0, 0);
@ -3030,7 +3038,16 @@ finish_file ()
/* a `new' expression at top level. */ /* a `new' expression at top level. */
expand_expr (decl, const0_rtx, VOIDmode, 0); expand_expr (decl, const0_rtx, VOIDmode, 0);
free_temp_slots (); free_temp_slots ();
expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0); if (TREE_CODE (init) == TREE_VEC)
{
expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0),
const0_rtx, VOIDmode, 0);
free_temp_slots ();
}
else
expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
} }
} }
else if (decl == error_mark_node) else if (decl == error_mark_node)
@ -3053,6 +3070,8 @@ finish_file ()
assemble_constructor (IDENTIFIER_POINTER (fnname)); assemble_constructor (IDENTIFIER_POINTER (fnname));
} }
expand_builtin_throw ();
permanent_allocation (1); permanent_allocation (1);
/* Done with C language context needs. */ /* Done with C language context needs. */
@ -3460,7 +3479,10 @@ tree
do_class_using_decl (decl) do_class_using_decl (decl)
tree decl; tree decl;
{ {
return error_mark_node; tree type;
/* Ignore for now, unimplemented. */
return NULL_TREE;
} }
void void
@ -3468,3 +3490,22 @@ do_using_directive (namespace)
tree namespace; tree namespace;
{ {
} }
void
check_default_args (x)
tree x;
{
tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
int saw_def = 0, i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
{
if (TREE_PURPOSE (arg))
saw_def = 1;
else if (saw_def)
{
cp_error ("default argument missing for parameter %P of `%#D'",
i, x);
break;
}
}
}

View File

@ -43,11 +43,11 @@ extern int cp_line_of PROTO((tree));
#define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap) #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
#define NARGS 3 #define NARGS 4
#define arglist a1, a2, a3 #define arglist a1, a2, a3, a4
#define arglist_dcl HOST_WIDE_INT a1, a2, a3; #define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4;
#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; #define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;
#define ARGSLIST args[0], args[1], args[2] #define ARGSLIST args[0], args[1], args[2], args[3]
static void static void
cp_thing (errfn, atarg1, format, arglist) cp_thing (errfn, atarg1, format, arglist)

View File

@ -35,6 +35,7 @@ typedef char* cp_printer ();
#define O op_as_string #define O op_as_string
#define P parm_as_string #define P parm_as_string
#define T type_as_string #define T type_as_string
#define V cv_as_string
#define _ (cp_printer *) 0 #define _ (cp_printer *) 0
cp_printer * cp_printers[256] = cp_printer * cp_printers[256] =
@ -45,7 +46,7 @@ cp_printer * cp_printers[256] =
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */ _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
P, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */ P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
}; };
@ -56,6 +57,7 @@ cp_printer * cp_printers[256] =
#undef O #undef O
#undef P #undef P
#undef T #undef T
#undef V
#undef _ #undef _
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
@ -269,7 +271,7 @@ dump_aggr_type (t, v)
name = TYPE_NAME (t); name = TYPE_NAME (t);
if (DECL_CONTEXT (name)) if (name && DECL_CONTEXT (name))
{ {
/* FUNCTION_DECL or RECORD_TYPE */ /* FUNCTION_DECL or RECORD_TYPE */
dump_decl (DECL_CONTEXT (name), 0); dump_decl (DECL_CONTEXT (name), 0);
@ -277,10 +279,10 @@ dump_aggr_type (t, v)
} }
/* kludge around weird behavior on g++.brendan/line1.C */ /* kludge around weird behavior on g++.brendan/line1.C */
if (TREE_CODE (name) != IDENTIFIER_NODE) if (name && TREE_CODE (name) != IDENTIFIER_NODE)
name = DECL_NAME (name); name = DECL_NAME (name);
if (ANON_AGGRNAME_P (name)) if (name == 0 || ANON_AGGRNAME_P (name))
{ {
OB_PUTS ("{anonymous"); OB_PUTS ("{anonymous");
if (!v) if (!v)
@ -512,6 +514,9 @@ ident_fndecl (t)
{ {
tree n = lookup_name (t, 0); tree n = lookup_name (t, 0);
if (n == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (n) == FUNCTION_DECL) if (TREE_CODE (n) == FUNCTION_DECL)
return n; return n;
else if (TREE_CODE (n) == TREE_LIST else if (TREE_CODE (n) == TREE_LIST
@ -643,26 +648,30 @@ dump_decl (t, v)
/* These special cases are duplicated here so that other functions /* These special cases are duplicated here so that other functions
can feed identifiers to cp_error and get them demangled properly. */ can feed identifiers to cp_error and get them demangled properly. */
case IDENTIFIER_NODE: case IDENTIFIER_NODE:
if (DESTRUCTOR_NAME_P (t)) { tree f;
{ if (DESTRUCTOR_NAME_P (t)
OB_PUTC ('~'); && (f = ident_fndecl (t))
dump_decl (DECL_NAME (ident_fndecl (t)), 0); && DECL_LANGUAGE (f) == lang_cplusplus)
} {
else if (IDENTIFIER_TYPENAME_P (t)) OB_PUTC ('~');
{ dump_decl (DECL_NAME (f), 0);
OB_PUTS ("operator "); }
/* Not exactly IDENTIFIER_TYPE_VALUE. */ else if (IDENTIFIER_TYPENAME_P (t))
dump_type (TREE_TYPE (t), 0); {
break; OB_PUTS ("operator ");
} /* Not exactly IDENTIFIER_TYPE_VALUE. */
else if (IDENTIFIER_OPNAME_P (t)) dump_type (TREE_TYPE (t), 0);
{ break;
char *name_string = operator_name_string (t); }
OB_PUTS ("operator "); else if (IDENTIFIER_OPNAME_P (t))
OB_PUTCP (name_string); {
} char *name_string = operator_name_string (t);
else OB_PUTS ("operator ");
OB_PUTID (t); OB_PUTCP (name_string);
}
else
OB_PUTID (t);
}
break; break;
case FUNCTION_DECL: case FUNCTION_DECL:
@ -785,7 +794,7 @@ dump_function_decl (t, v)
parmtypes = TREE_CHAIN (parmtypes); parmtypes = TREE_CHAIN (parmtypes);
} }
if (DESTRUCTOR_NAME_P (name)) if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
parmtypes = TREE_CHAIN (parmtypes); parmtypes = TREE_CHAIN (parmtypes);
dump_function_name (t); dump_function_name (t);
@ -824,7 +833,8 @@ dump_function_name (t)
/* There ought to be a better way to find out whether or not something is /* There ought to be a better way to find out whether or not something is
a destructor. */ a destructor. */
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))) if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
&& DECL_LANGUAGE (t) == lang_cplusplus)
{ {
OB_PUTC ('~'); OB_PUTC ('~');
dump_decl (name, 0); dump_decl (name, 0);
@ -1456,3 +1466,17 @@ args_as_string (p, v)
return type_as_string (p, v); return type_as_string (p, v);
} }
char *
cv_as_string (p, v)
tree p;
int v;
{
OB_INIT ();
dump_readonly_or_volatile (p, before);
OB_FINISH ();
return (char *)obstack_base (&scratch_obstack);
}

File diff suppressed because it is too large Load Diff

View File

@ -105,7 +105,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
&& TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0))) && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
{ {
type = TYPE_POINTER_TO (type); type = build_pointer_type (type);
/* Don't clobber a value that might be part of a default /* Don't clobber a value that might be part of a default
parameter value. */ parameter value. */
mark_addressable (slot); mark_addressable (slot);
@ -226,6 +226,14 @@ cplus_expand_expr (exp, target, tmode, modifier)
expand_throw (TREE_OPERAND (exp, 0)); expand_throw (TREE_OPERAND (exp, 0));
return NULL; return NULL;
case UNSAVE_EXPR:
{
rtx temp;
temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
return temp;
}
default: default:
break; break;
} }

View File

@ -8,7 +8,7 @@
\(** \(**
.. ..
.SH NAME .SH NAME
g++ \- GNU project C++ Compiler (v2.4) g++ \- GNU project C++ Compiler
.SH SYNOPSIS .SH SYNOPSIS
.RB g++ " [" \c .RB g++ " [" \c
.IR option " | " filename " ].\|.\|. .IR option " | " filename " ].\|.\|.
@ -31,8 +31,12 @@ C++ source files use one of the suffixes `\|\c
.B .C\c .B .C\c
\&\|', `\|\c \&\|', `\|\c
.B .cc\c .B .cc\c
\&\|', or `\|\c \&\|', `\|\c
.B .cxx\c .B .cxx\c
\&\|', `\|\c
.B .cpp\c
\&\|', or `\|\c
.B .c++\c
\&\|'; preprocessed C++ files use the suffix `\|\c \&\|'; preprocessed C++ files use the suffix `\|\c
.B .ii\c .B .ii\c
\&\|'. \&\|'.

View File

@ -9,13 +9,9 @@ __asm, GCC_ASM_KEYWORD, NORID
__asm__, GCC_ASM_KEYWORD, NORID __asm__, GCC_ASM_KEYWORD, NORID
__attribute, ATTRIBUTE, NORID __attribute, ATTRIBUTE, NORID
__attribute__, ATTRIBUTE, NORID __attribute__, ATTRIBUTE, NORID
__classof, CLASSOF, NORID
__classof__, CLASSOF, NORID
__const, TYPE_QUAL, RID_CONST __const, TYPE_QUAL, RID_CONST
__const__, TYPE_QUAL, RID_CONST __const__, TYPE_QUAL, RID_CONST
__extension__, EXTENSION, NORID __extension__, EXTENSION, NORID
__headof, HEADOF, NORID
__headof__, HEADOF, NORID
__inline, SCSPEC, RID_INLINE __inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID __label__, LABEL, NORID
@ -40,7 +36,6 @@ case, CASE, NORID,
catch, CATCH, NORID, catch, CATCH, NORID,
char, TYPESPEC, RID_CHAR, char, TYPESPEC, RID_CHAR,
class, AGGR, RID_CLASS, class, AGGR, RID_CLASS,
classof, CLASSOF, NORID,
compl, '~', NORID, compl, '~', NORID,
const, TYPE_QUAL, RID_CONST, const, TYPE_QUAL, RID_CONST,
const_cast, CONST_CAST, NORID, const_cast, CONST_CAST, NORID,
@ -59,7 +54,6 @@ float, TYPESPEC, RID_FLOAT,
for, FOR, NORID, for, FOR, NORID,
friend, SCSPEC, RID_FRIEND, friend, SCSPEC, RID_FRIEND,
goto, GOTO, NORID, goto, GOTO, NORID,
headof, HEADOF, NORID,
if, IF, NORID, if, IF, NORID,
inline, SCSPEC, RID_INLINE, inline, SCSPEC, RID_INLINE,
int, TYPESPEC, RID_INT, int, TYPESPEC, RID_INT,

View File

@ -924,29 +924,47 @@ will never be a problem.
@node Templates, Access Control, Coding Conventions, Top @node Templates, Access Control, Coding Conventions, Top
@section Templates @section Templates
g++ uses the simple approach to instantiating templates: it blindly A template is represented by a @code{TEMPLATE_DECL}. The specific
generates the code for each instantiation as needed. For class fields used are:
templates, g++ pushes the template parameters into the namespace for the
duration of the instantiation; for function templates, it's a simple
search and replace.
This approach does not support any of the template definition-time error
checking that is being bandied about by X3J16. It makes no attempt to deal
with name binding in a consistent way.
Instantiation of a class template is triggered by the use of a template
class anywhere but in a straight declaration like @code{class A<int>}.
This is wrong; in fact, it should not be triggered by typedefs or
declarations of pointers. Now that explicit instantiation is supported,
this misfeature is not necessary.
Important functions:
@table @code @table @code
@item instantiate_class_template @item DECL_TEMPLATE_RESULT
This function The generic decl on which instantiations are based. This looks just
like any other decl.
@item DECL_TEMPLATE_PARMS
The parameters to this template.
@end table @end table
The generic decl is parsed as much like any other decl as possible,
given the parameterization. The template decl is not built up until the
generic decl has been completed. For template classes, a template decl
is generated for each member function and static data member, as well.
Template members of template classes are represented by a TEMPLATE_DECL
for the class' parameters around another TEMPLATE_DECL for the member's
parameters.
All declarations that are instantiations or specializations of templates
refer to their template and parameters through DECL_TEMPLATE_INFO.
How should I handle parsing member functions with the proper param
decls? Set them up again or try to use the same ones? Currently we do
the former. We can probably do this without any extra machinery in
store_pending_inline, by deducing the parameters from the decl in
do_pending_inlines. PRE_PARSED_TEMPLATE_DECL?
If a base is a parm, we can't check anything about it. If a base is not
a parm, we need to check it for name binding. Do finish_base_struct if
no bases are parameterized (only if none, including indirect, are
parms). Nah, don't bother trying to do any of this until instantiation
-- we only need to do name binding in advance.
Always set up method vec and fields, inc. synthesized methods. Really?
We can't know the types of the copy folks, or whether we need a
destructor, or can have a default ctor, until we know our bases and
fields. Otherwise, we can assume and fix ourselves later. Hopefully.
@node Access Control, Error Reporting, Templates, Top @node Access Control, Error Reporting, Templates, Top
@section Access Control @section Access Control
The function compute_access returns one of three values: The function compute_access returns one of three values:
@ -1194,63 +1212,218 @@ 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.
The below points out some things that work in g++'s exception handling.
All completely constructed temps and local variables are cleaned up in
all unwinded scopes. Completely constructed parts of partially
constructed objects are cleaned up. This includes partially built
arrays. Exception specifications are now handled.
The below points out some flaws in g++'s exception handling, as it now The below points out some flaws in g++'s exception handling, as it now
stands. stands.
Only exact type matching or reference matching of throw types works when Only exact type matching or reference matching of throw types works when
-fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and -fno-rtti is used. Only works on a SPARC (like Suns), i386, arm and
rs6000 machines. Partial support is also in for alpha, hppa, m68k and rs6000 machines. Partial support is in for all other machines, but a
mips machines, but a stack unwinder called __unwind_function has to be stack unwinder called __unwind_function has to be written, and added to
written, and added to libgcc2 for them. See below for details on libgcc2 for them. See below for details on __unwind_function. Don't
__unwind_function. All completely constructed temps and local variables expect exception handling to work right if you optimize, in fact the
are cleaned up in all unwinded scopes. Completed parts of partially compiler will probably core dump. RTL_EXPRs for EH cond variables for
constructed objects are cleaned up with the exception that partially && and || exprs should probably be wrapped in UNSAVE_EXPRs, and
built arrays are not cleaned up as required. Don't expect exception RTL_EXPRs tweaked so that they can be unsaved, and the UNSAVE_EXPR code
handling to work right if you optimize, in fact the compiler will should be in the backend, or alternatively, UNSAVE_EXPR should be ripped
probably core dump. If two EH regions are the exact same size, the out and exactly one finalization allowed to be expanded by the backend.
backend cannot tell which one is first. It punts by picking the last I talked with kenner about this, and we have to allow multiple
one, if they tie. This is usually right. We really should stick in a expansions.
nop, if they are the same size.
When we invoke the copy constructor for an exception object because it We only do pointer conversions on exception matching a la 15.3 p2 case
is passed by value, and if we take a hit (exception) inside the copy 3: `A handler with type T, const T, T&, or const T& is a match for a
constructor someplace, where do we go? I have tentatively chosen to throw-expression with an object of type E if [3]T is a pointer type and
not catch throws by the outer block at the same unwind level, if one E is a pointer type that can be converted to T by a standard pointer
exists, but rather to allow the frame to unwind into the next series of conversion (_conv.ptr_) not involving conversions to pointers to private
handlers, if any. If this is the wrong way to do it, we will need to or protected base classes.' when -frtti is given.
protect the rest of the handler in some fashion. Maybe just changing
the handler's handler to protect the whole series of handlers is the
right way to go. This part is wrong. We should call terminate if an
exception is thrown while doing things like trying to copy the exception
object.
Exception specifications are handled syntax wise, but not semantic wise. We don't call delete on new expressions that die because the ctor threw
build_exception_variant should sort the incoming list, so that is an exception. See except/18 for a test case.
15.2 para 13: The exception being handled should be rethrown if control
reaches the end of a handler of the function-try-block of a constructor
or destructor, right now, it is not.
15.2 para 12: If a return statement appears in a handler of
function-try-block of a constructor, the program is ill-formed, but this
isn't diagnosed.
15.2 para 11: If the handlers of a function-try-block contain a jump
into the body of a constructor or destructor, the program is ill-formed,
but this isn't diagnosed.
15.2 para 9: Check that the fully constructed base classes and members
of an object are destroyed before entering the handler of a
function-try-block of a constructor or destructor for that object.
build_exception_variant should sort the incoming list, so that it
implements set compares, not exact list equality. Type smashing should implements set compares, not exact list equality. Type smashing should
smash exception specifications using set union. smash exception specifications using set union.
Thrown objects are allocated on the heap, in the usual way, but they are Thrown objects are usually allocated on the heap, in the usual way, but
never deleted. They should be deleted by the catch clauses. If one they are never deleted. They should be deleted by the catch clauses.
runs out of heap space, throwing an object will probably never work. If one runs out of heap space, throwing an object will probably never
This could be relaxed some by passing an __in_chrg parameter to track work. This could be relaxed some by passing an __in_chrg parameter to
who has control over the exception object. track who has control over the exception object. Thrown objects are not
allocated on the heap when they are pointer to object types.
When the backend returns a value, it can create new exception regions When the backend returns a value, it can create new exception regions
that need protecting. The new region should rethrow the object in that need protecting. The new region should rethrow the object in
context of the last associated cleanup that ran to completion. context of the last associated cleanup that ran to completion.
The structure of the code that is generated for C++ exception handling
code is shown below:
@example
Ln: throw value;
copy value onto heap
jump throw (Ln, id, address of copy of value on heap)
try {
+Lstart: the start of the main EH region
|... ...
+Lend: the end of the main EH region
} catch (T o) {
...1
}
Lresume:
nop used to make sure there is something before
the next region ends, if there is one
... ...
jump Ldone
[
Lmainhandler: handler for the region Lstart-Lend
cleanup
] zero or more, depending upon automatic vars with dtors
+Lpartial:
| jump Lover
+Lhere:
rethrow (Lhere, same id, same obj);
Lterm: handler for the region Lpartial-Lhere
call terminate
Lover:
[
[
call throw_type_match
if (eq) {
] these lines disappear when there is no catch condition
+Lsregion2:
| ...1
| jump Lresume
|Lhandler: handler for the region Lsregion2-Leregion2
| rethrow (Lresume, same id, same obj);
+Leregion2
}
] there are zero or more of these sections, depending upon how many
catch clauses there are
----------------------------- expand_end_all_catch --------------------------
here we have fallen off the end of all catch
clauses, so we rethrow to outer
rethrow (Lresume, same id, same obj);
----------------------------- expand_end_all_catch --------------------------
[
L1: maybe throw routine
] depending upon if we have expanded it or not
Ldone:
ret
start_all_catch emits labels: Lresume,
#end example
The __unwind_function takes a pointer to the throw handler, and is The __unwind_function takes a pointer to the throw handler, and is
expected to pop the stack frame that was built to call it, as well as expected to pop the stack frame that was built to call it, as well as
the frame underneath and then jump to the throw handler. It must not the frame underneath and then jump to the throw handler. It must
change the three registers allocated for the pointer to the exception restore all registers to their proper values as well as all other
object, the pointer to the type descriptor that identifies the type of machine state as determined by the context in which we are unwinding
the exception object, and the pointer to the code that threw. On hppa, into. The way I normally start is to compile:
these are %r5, %r6, %r7. On m68k these are a2, a3, a4. On mips they
are s0, s1, s2. On Alpha these are $9, $10, $11. It takes about a day
to write this routine, if someone wants to volunteer to write this
routine for any architecture, exception support for that architecture
will be added to g++. Please send in those code donations.
void *g;
foo(void* a) { g = a; }
with -S, and change the thing that alters the PC (return, or ret
usually) to not alter the PC, making sure to leave all other semantics
(like adjusting the stack pointer, or frame pointers) in. After that,
replicate the prologue once more at the end, again, changing the PC
altering instructions, and finally, at the very end, jump to `g'.
It takes about a week to write this routine, if someone wants to
volunteer to write this routine for any architecture, exception support
for that architecture will be added to g++. Please send in those code
donations. One other thing that needs to be done, is to double check
that __builtin_return_address (0) works.
@subsection Specific Targets
For the alpha, the __unwind_function will be something resembling:
@example
void
__unwind_function(void *ptr)
@{
/* First frame */
asm ("ldq $15, 8($30)"); /* get the saved frame ptr; 15 is fp, 30 is sp */
asm ("bis $15, $15, $30"); /* reload sp with the fp we found */
/* Second frame */
asm ("ldq $15, 8($30)"); /* fp */
asm ("bis $15, $15, $30"); /* reload sp with the fp we found */
/* Return */
asm ("ret $31, ($16), 1"); /* return to PTR, stored in a0 */
@}
@end example
@noindent
However, there are a few problems preventing it from working. First of
all, the gcc-internal function @code{__builtin_return_address} needs to
work given an argument of 0 for the alpha. As it stands as of August
30th, 1995, the code for @code{BUILT_IN_RETURN_ADDRESS} in @file{expr.c}
will definitely not work on the alpha. Instead, we need to define
the macros @code{DYNAMIC_CHAIN_ADDRESS} (maybe),
@code{RETURN_ADDR_IN_PREVIOUS_FRAME}, and definitely need a new
definition for @code{RETURN_ADDR_RTX}.
In addition (and more importantly), we need a way to reliably find the
frame pointer on the alpha. The use of the value 8 above to restore the
frame pointer (register 15) is incorrect. On many systems, the frame
pointer is consistently offset to a specific point on the stack. On the
alpha, however, the frame pointer is pushed last. First the return
address is stored, then any other registers are saved (e.g., @code{s0}),
and finally the frame pointer is put in place. So @code{fp} could have
an offset of 8, but if the calling function saved any registers at all,
they add to the offset.
The only places the frame size is noted are with the @samp{.frame}
directive, for use by the debugger and the OSF exception handling model
(useless to us), and in the initial computation of the new value for
@code{sp}, the stack pointer. For example, the function may start with:
@example
lda $30,-32($30)
.frame $15,32,$26,0
@end example
@noindent
The 32 above is exactly the value we need. With this, we can be sure
that the frame pointer is stored 8 bytes less---in this case, at 24(sp)).
The drawback is that there is no way that I (Brendan) have found to let
us discover the size of a previous frame @emph{inside} the definition
of @code{__unwind_function}.
So to accomplish exception handling support on the alpha, we need two
things: first, a way to figure out where the frame pointer was stored,
and second, a functional @code{__builtin_return_address} implementation
for except.c to be able to use it.
@subsection Backend Exception Support
The backend must be extended to fully support exceptions. Right now The backend must be extended to fully support exceptions. Right now
there are a few hooks into the alpha exception handling backend that there are a few hooks into the alpha exception handling backend that
@ -1285,6 +1458,78 @@ semantics.
The above is not meant to be exhaustive, but does include all things I The above is not meant to be exhaustive, but does include all things I
have thought of so far. I am sure other limitations exist. have thought of so far. I am sure other limitations exist.
Below are some notes on the migration of the exception handling code
backend from the C++ frontend to the backend.
NOTEs are to be used to denote the start of an exception region, and the
end of the region. I presume that the interface used to generate these
notes in the backend would be two functions, start_exception_region and
end_exception_region (or something like that). The frontends are
required to call them in pairs. When marking the end of a region, an
argument can be passed to indicate the handler for the marked region.
This can be passed in many ways, currently a tree is used. Another
possibility would be insns for the handler, or a label that denotes a
handler. I have a feeling insns might be the the best way to pass it.
Semantics are, if an exception is thrown inside the region, control is
transfered unconditionally to the handler. If control passes through
the handler, then the backend is to rethrow the exception, in the
context of the end of the original region. The handler is protected by
the conventional mechanisms; it is the frontend's responsibility to
protect the handler, if special semantics are required.
This is a very low level view, and it would be nice is the backend
supported a somewhat higher level view in addition to this view. This
higher level could include source line number, name of the source file,
name of the language that threw the exception and possibly the name of
the exception. Kenner may want to rope you into doing more than just
the basics required by C++. You will have to resolve this. He may want
you to do support for non-local gotos, first scan for exception handler,
if none is found, allow the debugger to be entered, without any cleanups
being done. To do this, the backend would have to know the difference
between a cleanup-rethrower, and a real handler, if would also have to
have a way to know if a handler `matches' a thrown exception, and this
is frontend specific.
The UNSAVE_EXPR tree code has to be migrated to the backend. Exprs such
as TARGET_EXPRs, WITH_CLEANUP_EXPRs, CALL_EXPRs and RTL_EXPRs have to be
changed to support unsaving. This is meant to be a complete list.
SAVE_EXPRs can be unsaved already. expand_decl_cleanup should be
changed to unsave it's argument, if needed. See
cp/tree.c:cp_expand_decl_cleanup, unsave_expr_now, unsave_expr, and
cp/expr.c:cplus_expand_expr(case UNSAVE_EXPR:) for the UNSAVE_EXPR code.
Now, as to why... because kenner already tripped over the exact same
problem in Ada, we talked about it, he didn't like any of the solution,
but yet, didn't like no solution either. He was willing to live with
the drawbacks of this solution. The drawback is unsave_expr_now. It
should have a callback into the frontend, to allow the unsaveing of
frontend special codes. The callback goes in, inplace of the call to
my_friendly_abort.
The stack unwinder is one of the hardest parts to do. It is highly
machine dependent. The form that kenner seems to like was a couple of
macros, that would do the machine dependent grunt work. One preexisting
function that might be of some use is __builtin_return_address (). One
macro he seemed to want was __builtin_return_address, and the other
would do the hard work of fixing up the registers, adjusting the stack
pointer, frame pointer, arg pointer and so on.
The eh archive (~mrs/eh) might be good reading for understanding the Ada
perspective, and some of kenners mindset, and a detailed explanation
(Message-Id: <9308301130.AA10543@vlsi1.ultra.nyu.edu>) of the concepts
involved.
Here is a guide to existing backend type code. It is all in
cp/except.c. Check out do_unwind, and expand_builtin_throw for current
code on how to figure out what handler matches an exception,
emit_exception_table for code on emitting the PC range table that is
built during compilation, expand_exception_blocks for code that emits
all the handlers at the end of a functions, end_protect to mark the end
of an exception region, start_protect to mark the start of an exception
region, lang_interim_eh is the master hook used by the backend into the
EH backend that now exists in the frontend, and expand_internal_throw to
raise an exception.
@node Free Store, Concept Index, Exception Handling, Top @node Free Store, Concept Index, Exception Handling, Top
@section Free Store @section Free Store

View File

@ -3,12 +3,12 @@
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
struct resword { char *name; short token; enum rid rid;}; struct resword { char *name; short token; enum rid rid;};
#define TOTAL_KEYWORDS 101 #define TOTAL_KEYWORDS 97
#define MIN_WORD_LENGTH 2 #define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 16 #define MAX_WORD_LENGTH 16
#define MIN_HASH_VALUE 4 #define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 210 #define MAX_HASH_VALUE 219
/* maximum key range = 207, duplicates = 0 */ /* maximum key range = 216, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
inline inline
@ -20,19 +20,19 @@ hash (str, len)
{ {
static unsigned char asso_values[] = static unsigned char asso_values[] =
{ {
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
211, 211, 211, 211, 211, 0, 211, 35, 1, 69, 220, 220, 220, 220, 220, 0, 220, 88, 16, 19,
61, 0, 19, 65, 20, 100, 211, 5, 11, 52, 52, 0, 9, 72, 1, 77, 220, 0, 0, 38,
3, 25, 6, 2, 31, 26, 4, 41, 24, 64, 13, 44, 38, 30, 27, 57, 1, 14, 0, 2,
10, 24, 211, 211, 211, 211, 211, 211, 2, 7, 220, 220, 220, 220, 220, 220,
}; };
register int hval = len; register int hval = len;
@ -65,144 +65,144 @@ is_reserved_word (str, len)
{ {
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"else", ELSE, NORID,}, {"else", ELSE, NORID,},
{"",}, {"",}, {"",},
{"true", CXX_TRUE, NORID,}, {"true", CXX_TRUE, NORID,},
{"extern", SCSPEC, RID_EXTERN,}, {"",},
{"not", '!', NORID,}, {"while", WHILE, NORID,},
{"not_eq", EQCOMPARE, NORID,}, {"virtual", SCSPEC, RID_VIRTUAL,},
{"",}, {"",}, {"",}, {"",},
{"try", TRY, NORID,},
{"",}, {"",}, {"",}, {"",},
{"typeof", TYPEOF, NORID,},
{"not", '!', NORID,},
{"new", NEW, NORID,},
{"extern", SCSPEC, RID_EXTERN,},
{"bool", TYPESPEC, RID_BOOL,},
{"",}, {"",},
{"case", CASE, NORID,},
{"__alignof__", ALIGNOF, NORID},
{"",},
{"typedef", SCSPEC, RID_TYPEDEF,},
{"",},
{"__extension__", EXTENSION, NORID},
{"",}, {"",},
{"__alignof", ALIGNOF, NORID},
{"xor", '^', NORID,},
{"",},
{"__inline", SCSPEC, RID_INLINE}, {"__inline", SCSPEC, RID_INLINE},
{"",}, {"",},
{"__inline__", SCSPEC, RID_INLINE}, {"__inline__", SCSPEC, RID_INLINE},
{"",}, {"",},
{"xor_eq", ASSIGN, NORID,}, {"xor_eq", ASSIGN, NORID,},
{"",}, {"",}, {"",}, {"for", FOR, NORID,},
{"template", TEMPLATE, RID_TEMPLATE,},
{"",}, {"",}, {"",}, {"",},
{"__alignof__", ALIGNOF, NORID}, {"continue", CONTINUE, NORID,},
{"__extension__", EXTENSION, NORID},
{"bool", TYPESPEC, RID_BOOL,},
{"",},
{"typeof", TYPEOF, NORID,},
{"",},
{"try", TRY, NORID,},
{"or_eq", ASSIGN, NORID,},
{"__asm__", GCC_ASM_KEYWORD, NORID},
{"",},
{"__headof__", HEADOF, NORID},
{"",}, {"",},
{"catch", CATCH, NORID,},
{"private", VISSPEC, RID_PRIVATE,}, {"private", VISSPEC, RID_PRIVATE,},
{"",},
{"typename", TYPENAME_KEYWORD, NORID,},
{"template", TEMPLATE, RID_TEMPLATE,},
{"not_eq", EQCOMPARE, NORID,},
{"",}, {"",},
{"throw", THROW, NORID,},
{"__const", TYPE_QUAL, RID_CONST},
{"__const__", TYPE_QUAL, RID_CONST}, {"__const__", TYPE_QUAL, RID_CONST},
{"__volatile", TYPE_QUAL, RID_VOLATILE}, {"__volatile", TYPE_QUAL, RID_VOLATILE},
{"__const", TYPE_QUAL, RID_CONST}, {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
{"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"__volatile__", TYPE_QUAL, RID_VOLATILE},
{"__alignof", ALIGNOF, NORID}, {"delete", DELETE, NORID,},
{"and_eq", ASSIGN, NORID,}, {"typeid", TYPEID, NORID,},
{"xor", '^', NORID,}, {"return", RETURN, NORID,},
{"__typeof__", TYPEOF, NORID},
{"compl", '~', NORID,},
{"public", VISSPEC, RID_PUBLIC,},
{"__asm__", GCC_ASM_KEYWORD, NORID},
{"switch", SWITCH, NORID,},
{"",},
{"friend", SCSPEC, RID_FRIEND,},
{"__typeof", TYPEOF, NORID},
{"",},
{"static_cast", STATIC_CAST, NORID,}, {"static_cast", STATIC_CAST, NORID,},
{"break", BREAK, NORID,},
{"namespace", NAMESPACE, NORID,},
{"__classof__", CLASSOF, NORID},
{"typedef", SCSPEC, RID_TYPEDEF,},
{"false", CXX_FALSE, NORID,}, {"false", CXX_FALSE, NORID,},
{"sizeof", SIZEOF, NORID,}, {"sizeof", SIZEOF, NORID,},
{"__headof", HEADOF, NORID},
{"for", FOR, NORID,},
{"",},
{"__label__", LABEL, NORID},
{"switch", SWITCH, NORID,},
{"virtual", SCSPEC, RID_VIRTUAL,},
{"or", OROR, NORID,}, {"or", OROR, NORID,},
{"__typeof__", TYPEOF, NORID},
{"this", THIS, NORID,},
{"",},
{"bitor", '|', NORID,},
{"float", TYPESPEC, RID_FLOAT,},
{"typename", TYPENAME_KEYWORD, NORID,},
{"__classof", CLASSOF, NORID},
{"short", TYPESPEC, RID_SHORT,},
{"delete", DELETE, NORID,},
{"double", TYPESPEC, RID_DOUBLE,}, {"double", TYPESPEC, RID_DOUBLE,},
{"",}, {"",},
{"new", NEW, NORID,},
{"typeid", TYPEID, NORID,},
{"",},
{"case", CASE, NORID,},
{"union", AGGR, RID_UNION,}, {"union", AGGR, RID_UNION,},
{"sigof", SIGOF, NORID /* Extension */,}, {"char", TYPESPEC, RID_CHAR,},
{"__typeof", TYPEOF, NORID},
{"struct", AGGR, RID_RECORD,}, {"struct", AGGR, RID_RECORD,},
{"volatile", TYPE_QUAL, RID_VOLATILE,}, {"or_eq", ASSIGN, NORID,},
{"enum", ENUM, NORID,},
{"int", TYPESPEC, RID_INT,},
{"const", TYPE_QUAL, RID_CONST,},
{"static", SCSPEC, RID_STATIC,},
{"reinterpret_cast", REINTERPRET_CAST, NORID,},
{"",},
{"explicit", SCSPEC, RID_EXPLICIT,},
{"__signed__", TYPESPEC, RID_SIGNED},
{"if", IF, NORID,},
{"__attribute", ATTRIBUTE, NORID},
{"short", TYPESPEC, RID_SHORT,},
{"__attribute__", ATTRIBUTE, NORID},
{"bitor", '|', NORID,},
{"signature", AGGR, RID_SIGNATURE /* Extension */,}, {"signature", AGGR, RID_SIGNATURE /* Extension */,},
{"while", WHILE, NORID,}, {"",},
{"return", RETURN, NORID,}, {"__sigof__", SIGOF, NORID /* Extension */,},
{"volatile", TYPE_QUAL, RID_VOLATILE,},
{"__label__", LABEL, NORID},
{"do", DO, NORID,},
{"",}, {"",},
{"__asm", GCC_ASM_KEYWORD, NORID}, {"__asm", GCC_ASM_KEYWORD, NORID},
{"protected", VISSPEC, RID_PROTECTED,}, {"protected", VISSPEC, RID_PROTECTED,},
{"reinterpret_cast", REINTERPRET_CAST, NORID,},
{"friend", SCSPEC, RID_FRIEND,},
{"",}, {"",},
{"do", DO, NORID,}, {"float", TYPESPEC, RID_FLOAT,},
{"auto", SCSPEC, RID_AUTO,},
{"asm", ASM_KEYWORD, NORID,},
{"compl", '~', NORID,},
{"public", VISSPEC, RID_PUBLIC,},
{"",},
{"mutable", SCSPEC, RID_MUTABLE,},
{"",},
{"signed", TYPESPEC, RID_SIGNED,},
{"",},
{"throw", THROW, NORID,},
{"and", ANDAND, NORID,},
{"",}, {"",}, {"",},
{"bitand", '&', NORID,},
{"const", TYPE_QUAL, RID_CONST,},
{"static", SCSPEC, RID_STATIC,},
{"headof", HEADOF, NORID,},
{"int", TYPESPEC, RID_INT,},
{"enum", ENUM, NORID,},
{"",},
{"__signed__", TYPESPEC, RID_SIGNED},
{"default", DEFAULT, NORID,},
{"",},
{"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
{"using", USING, NORID,}, {"using", USING, NORID,},
{"__attribute", ATTRIBUTE, NORID},
{"",}, {"",},
{"__attribute__", ATTRIBUTE, NORID}, {"const_cast", CONST_CAST, NORID,},
{"",}, {"",},
{"goto", GOTO, NORID,}, {"void", TYPESPEC, RID_VOID,},
{"operator", OPERATOR, NORID,}, {"break", BREAK, NORID,},
{"if", IF, NORID,}, {"namespace", NAMESPACE, NORID,},
{"continue", CONTINUE, NORID,},
{"explicit", SCSPEC, RID_EXPLICIT,},
{"",}, {"",},
{"class", AGGR, RID_CLASS,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"char", TYPESPEC, RID_CHAR,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"classof", CLASSOF, NORID,}, {"sigof", SIGOF, NORID /* Extension */,},
{"",}, {"",}, {"",},
{"this", THIS, NORID,},
{"",}, {"",}, {"",}, {"",},
{"and_eq", ASSIGN, NORID,},
{"",}, {"",}, {"",},
{"signed", TYPESPEC, RID_SIGNED,},
{"asm", ASM_KEYWORD, NORID,},
{"",}, {"",}, {"",},
{"mutable", SCSPEC, RID_MUTABLE,},
{"",}, {"",}, {"",},
{"__signed", TYPESPEC, RID_SIGNED},
{"class", AGGR, RID_CLASS,},
{"register", SCSPEC, RID_REGISTER,},
{"",}, {"",}, {"",},
{"and", ANDAND, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"long", TYPESPEC, RID_LONG,}, {"long", TYPESPEC, RID_LONG,},
{"",}, {"",}, {"",}, {"",}, {"default", DEFAULT, NORID,},
{"void", TYPESPEC, RID_VOID,}, {"operator", OPERATOR, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"overload", OVERLOAD, NORID,},
{"",}, {"",},
{"catch", CATCH, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",},
{"__signed", TYPESPEC, RID_SIGNED},
{"register", SCSPEC, RID_REGISTER,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"const_cast", CONST_CAST, NORID,},
{"",}, {"",},
{"dynamic_cast", DYNAMIC_CAST, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"inline", SCSPEC, RID_INLINE,},
{"",}, {"",}, {"",},
{"unsigned", TYPESPEC, RID_UNSIGNED,}, {"unsigned", TYPESPEC, RID_UNSIGNED,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"inline", SCSPEC, RID_INLINE,},
{"",},
{"bitand", '&', NORID,},
{"",},
{"goto", GOTO, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"dynamic_cast", DYNAMIC_CAST, NORID,},
{"",}, {"",}, {"",}, {"",}, {"",},
{"__signature__", AGGR, RID_SIGNATURE /* Extension */,},
{"",},
{"auto", SCSPEC, RID_AUTO,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",},
{"overload", OVERLOAD, NORID,},
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)

View File

@ -729,7 +729,7 @@ expand_virtual_init (binfo, decl)
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo)); vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));
assemble_external (vtbl); assemble_external (vtbl);
TREE_USED (vtbl) = 1; TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl); vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
decl = convert_pointer_to_real (vtype_binfo, decl); decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype); vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node) if (vtbl_ptr == error_mark_node)
@ -1075,6 +1075,8 @@ expand_member_init (exp, name, init)
INIT comes in two flavors: it is either a value which INIT comes in two flavors: it is either a value which
is to be stored in EXP, or it is a parameter list is to be stored in EXP, or it is a parameter list
to go to a constructor, which will operate on EXP. to go to a constructor, which will operate on EXP.
If INIT is not a parameter list for a constructor, then set
LOOKUP_ONLYCONVERTING.
If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of
the initializer, if FLAGS is 0, then it is the (init) form. the initializer, if FLAGS is 0, then it is the (init) form.
If `init' is a CONSTRUCTOR, then we emit a warning message, If `init' is a CONSTRUCTOR, then we emit a warning message,
@ -1113,19 +1115,23 @@ expand_aggr_init (exp, init, alias_this, flags)
{ {
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
int was_const = TREE_READONLY (exp); int was_const = TREE_READONLY (exp);
int was_volatile = TREE_THIS_VOLATILE (exp);
if (init == error_mark_node) if (init == error_mark_node)
return; return;
TREE_READONLY (exp) = 0; TREE_READONLY (exp) = 0;
TREE_THIS_VOLATILE (exp) = 0;
if (init && TREE_CODE (init) != TREE_LIST)
flags |= LOOKUP_ONLYCONVERTING;
if (TREE_CODE (type) == ARRAY_TYPE) if (TREE_CODE (type) == ARRAY_TYPE)
{ {
/* Must arrange to initialize each element of EXP /* Must arrange to initialize each element of EXP
from elements of INIT. */ from elements of INIT. */
int was_const_elts = TYPE_READONLY (TREE_TYPE (type));
tree itype = init ? TREE_TYPE (init) : NULL_TREE; tree itype = init ? TREE_TYPE (init) : NULL_TREE;
if (was_const_elts) if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))
{ {
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type); TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (init) if (init)
@ -1151,6 +1157,7 @@ expand_aggr_init (exp, init, alias_this, flags)
expand_vec_init (exp, exp, array_type_nelts (type), init, expand_vec_init (exp, exp, array_type_nelts (type), init,
init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1)); init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
TREE_TYPE (exp) = type; TREE_TYPE (exp) = type;
if (init) if (init)
TREE_TYPE (init) = itype; TREE_TYPE (init) = itype;
@ -1172,6 +1179,7 @@ expand_aggr_init (exp, init, alias_this, flags)
expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
init, alias_this, LOOKUP_NORMAL|flags); init, alias_this, LOOKUP_NORMAL|flags);
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
TREE_THIS_VOLATILE (exp) = was_volatile;
} }
static void static void
@ -1229,6 +1237,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
} }
else else
{ {
if (flags & LOOKUP_ONLYCONVERTING)
flags |= LOOKUP_NO_CONVERSION;
rval = build_method_call (exp, constructor_name_full (type), rval = build_method_call (exp, constructor_name_full (type),
parms, binfo, flags); parms, binfo, flags);
@ -1786,12 +1796,12 @@ build_member_call (cname, name, parmlist)
if (dont_use_this) if (dont_use_this)
{ {
basetype_path = TYPE_BINFO (type); basetype_path = TYPE_BINFO (type);
decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
} }
else if (current_class_decl == 0) else if (current_class_decl == 0)
{ {
dont_use_this = 1; dont_use_this = 1;
decl = build1 (NOP_EXPR, TYPE_POINTER_TO (type), error_mark_node); decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
} }
else else
{ {
@ -2192,7 +2202,8 @@ resolve_offset_ref (exp)
{ {
if (TREE_ADDRESSABLE (member) == 0) if (TREE_ADDRESSABLE (member) == 0)
{ {
cp_error_at ("member `%D' is non-static in static member function context", member); cp_error_at ("member `%D' is non-static but referenced as a static member",
member);
error ("at this point in file"); error ("at this point in file");
TREE_ADDRESSABLE (member) = 1; TREE_ADDRESSABLE (member) = 1;
} }
@ -3037,7 +3048,7 @@ build_new (placement, decl, init, use_global_new)
if (! use_global_new && TYPE_LANG_SPECIFIC (true_type) if (! use_global_new && TYPE_LANG_SPECIFIC (true_type)
&& (TYPE_GETS_NEW (true_type) & (1 << has_array))) && (TYPE_GETS_NEW (true_type) & (1 << has_array)))
rval = build_opfncall (code, LOOKUP_NORMAL, rval = build_opfncall (code, LOOKUP_NORMAL,
TYPE_POINTER_TO (true_type), size, placement); build_pointer_type (true_type), size, placement);
else if (placement) else if (placement)
{ {
rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN, rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
@ -3064,9 +3075,9 @@ build_new (placement, decl, init, use_global_new)
/* See comment above as to why this is disabled. */ /* See comment above as to why this is disabled. */
if (alignment) if (alignment)
{ {
rval = build (PLUS_EXPR, TYPE_POINTER_TO (true_type), rval, rval = build (PLUS_EXPR, build_pointer_type (true_type), rval,
alignment); alignment);
rval = build (BIT_AND_EXPR, TYPE_POINTER_TO (true_type), rval = build (BIT_AND_EXPR, build_pointer_type (true_type),
rval, build1 (BIT_NOT_EXPR, integer_type_node, rval, build1 (BIT_NOT_EXPR, integer_type_node,
alignment)); alignment));
} }
@ -3100,7 +3111,7 @@ build_new (placement, decl, init, use_global_new)
rval = convert (string_type_node, rval); /* lets not add void* and ints */ rval = convert (string_type_node, rval); /* lets not add void* and ints */
rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1)); rval = save_expr (build_binary_op (PLUS_EXPR, rval, extra, 1));
/* Store header info. */ /* Store header info. */
cookie = build_indirect_ref (build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type), cookie = build_indirect_ref (build (MINUS_EXPR, build_pointer_type (BI_header_type),
rval, extra), NULL_PTR); rval, extra), NULL_PTR);
exp1 = build (MODIFY_EXPR, void_type_node, exp1 = build (MODIFY_EXPR, void_type_node,
build_component_ref (cookie, nc_nelts_field_id, 0, 0), build_component_ref (cookie, nc_nelts_field_id, 0, 0),
@ -3187,8 +3198,13 @@ build_new (placement, decl, init, use_global_new)
/* In case of static initialization, SAVE_EXPR is good enough. */ /* In case of static initialization, SAVE_EXPR is good enough. */
rval = save_expr (rval); rval = save_expr (rval);
init = copy_to_permanent (init);
rval = copy_to_permanent (rval); rval = copy_to_permanent (rval);
init = copy_to_permanent (init);
init = expand_vec_init (decl, rval,
build_binary_op (MINUS_EXPR, nelts,
integer_one_node, 1),
init, 0);
init = copy_to_permanent (init);
static_aggregates = perm_tree_cons (init, rval, static_aggregates); static_aggregates = perm_tree_cons (init, rval, static_aggregates);
} }
else else
@ -3306,6 +3322,174 @@ build_new (placement, decl, init, use_global_new)
return rval; return rval;
} }
static tree
build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
use_global_delete)
tree base, maxindex, type;
tree auto_delete_vec, auto_delete;
int use_global_delete;
{
tree virtual_size;
tree ptype = build_pointer_type (type);
tree size_exp = size_in_bytes (type);
/* Temporary variables used by the loop. */
tree tbase, tbase_init;
/* This is the body of the loop that implements the deletion of a
single element, and moves temp variables to next elements. */
tree body;
/* This is the LOOP_EXPR that governs the deletion of the elements. */
tree loop;
/* This is the thing that governs what to do after the loop has run. */
tree deallocate_expr = 0;
/* This is the BIND_EXPR which holds the outermost iterator of the
loop. It is convenient to set this variable up and test it before
executing any other code in the loop.
This is also the containing expression returned by this function. */
tree controller = NULL_TREE;
/* This is the BLOCK to record the symbol binding for debugging. */
tree block;
if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
{
loop = integer_zero_node;
goto no_destructor;
}
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
tbase_init = build_modify_expr (tbase, NOP_EXPR,
fold (build (PLUS_EXPR, ptype,
base,
virtual_size)));
DECL_REGISTER (tbase) = 1;
controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
TREE_SIDE_EFFECTS (controller) = 1;
block = build_block (tbase, 0, 0, 0, 0);
add_block_current_level (block);
if (auto_delete != integer_zero_node
&& auto_delete != integer_two_node)
{
tree base_tbd = convert (ptype,
build_binary_op (MINUS_EXPR,
convert (ptr_type_node, base),
BI_header_size,
1));
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_tree_list (NULL_TREE,
build_x_delete (ptype, base_tbd,
2 | use_global_delete,
virtual_size));
body = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
auto_delete, integer_one_node),
body, integer_zero_node);
}
else
body = NULL_TREE;
body = tree_cons (NULL_TREE,
build_delete (ptype, tbase, auto_delete,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
body);
body = tree_cons (NULL_TREE,
build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
body);
body = tree_cons (NULL_TREE,
build (EXIT_EXPR, void_type_node,
build (EQ_EXPR, boolean_type_node, base, tbase)),
body);
loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
loop = tree_cons (NULL_TREE, tbase_init,
tree_cons (NULL_TREE, loop, NULL_TREE));
loop = build_compound_expr (loop);
no_destructor:
/* If the delete flag is one, or anything else with the low bit set,
delete the storage. */
if (auto_delete_vec == integer_zero_node
|| auto_delete_vec == integer_two_node)
deallocate_expr = integer_zero_node;
else
{
tree base_tbd;
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
if (! TYPE_VEC_NEW_USES_COOKIE (type))
/* no header */
base_tbd = base;
else
{
base_tbd = convert (ptype,
build_binary_op (MINUS_EXPR,
convert (string_type_node, base),
BI_header_size,
1));
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
}
deallocate_expr = build_x_delete (ptype, base_tbd,
2 | use_global_delete,
virtual_size);
if (auto_delete_vec != integer_one_node)
deallocate_expr = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
auto_delete_vec, integer_one_node),
deallocate_expr, integer_zero_node);
}
if (loop && deallocate_expr != integer_zero_node)
{
body = tree_cons (NULL_TREE, loop,
tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
body = build_compound_expr (body);
}
else
body = loop;
/* Outermost wrapper: If pointer is null, punt. */
body = build (COND_EXPR, void_type_node,
build (NE_EXPR, boolean_type_node, base, integer_zero_node),
body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body);
if (controller)
{
TREE_OPERAND (controller, 1) = body;
return controller;
}
else
return convert (void_type_node, body);
}
/* Build a tree to cleanup partially built arrays.
BASE is that starting address of the array.
COUNT is the count of objects that have been built, that need destroying.
TYPE is the type of elements in the array. */
static tree
build_array_eh_cleanup (base, count, type)
tree base, count, type;
{
tree expr = build_vec_delete_1 (base, count, type, integer_two_node,
integer_zero_node, 0);
return expr;
}
/* `expand_vec_init' performs initialization of a vector of aggregate /* `expand_vec_init' performs initialization of a vector of aggregate
types. types.
@ -3350,12 +3534,12 @@ expand_vec_init (decl, base, maxindex, init, from_array)
/* Set to zero in case size is <= 0. Optimizer will delete this if /* Set to zero in case size is <= 0. Optimizer will delete this if
it is not needed. */ it is not needed. */
rval = get_temp_regvar (TYPE_POINTER_TO (type), rval = get_temp_regvar (build_pointer_type (type),
convert (TYPE_POINTER_TO (type), null_pointer_node)); convert (build_pointer_type (type), null_pointer_node));
base = default_conversion (base); base = default_conversion (base);
base = convert (TYPE_POINTER_TO (type), base); base = convert (build_pointer_type (type), base);
expand_assignment (rval, base, 0, 0); expand_assignment (rval, base, 0, 0);
base = get_temp_regvar (TYPE_POINTER_TO (type), base); base = get_temp_regvar (build_pointer_type (type), base);
if (init != NULL_TREE if (init != NULL_TREE
&& TREE_CODE (init) == CONSTRUCTOR && TREE_CODE (init) == CONSTRUCTOR
@ -3364,7 +3548,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
/* Initialization of array from {...}. */ /* Initialization of array from {...}. */
tree elts = CONSTRUCTOR_ELTS (init); tree elts = CONSTRUCTOR_ELTS (init);
tree baseref = build1 (INDIRECT_REF, type, base); tree baseref = build1 (INDIRECT_REF, type, base);
tree baseinc = build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size); tree baseinc = build (PLUS_EXPR, build_pointer_type (type), base, size);
int host_i = TREE_INT_CST_LOW (maxindex); int host_i = TREE_INT_CST_LOW (maxindex);
if (IS_AGGR_TYPE (type)) if (IS_AGGR_TYPE (type))
@ -3441,6 +3625,8 @@ expand_vec_init (decl, base, maxindex, init, from_array)
expand_start_cond (build (GE_EXPR, boolean_type_node, expand_start_cond (build (GE_EXPR, boolean_type_node,
iterator, integer_zero_node), 0); iterator, integer_zero_node), 0);
if (TYPE_NEEDS_DESTRUCTOR (type))
start_protect ();
expand_start_loop_continue_elsewhere (1); expand_start_loop_continue_elsewhere (1);
if (from_array) if (from_array)
@ -3466,18 +3652,18 @@ expand_vec_init (decl, base, maxindex, init, from_array)
{ {
if (init != 0) if (init != 0)
sorry ("cannot initialize multi-dimensional array with initializer"); sorry ("cannot initialize multi-dimensional array with initializer");
expand_vec_init (decl, build1 (NOP_EXPR, TYPE_POINTER_TO (TREE_TYPE (type)), base), expand_vec_init (decl, build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), base),
array_type_nelts (type), 0, 0); array_type_nelts (type), 0, 0);
} }
else else
expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0); expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
expand_assignment (base, expand_assignment (base,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base, size), build (PLUS_EXPR, build_pointer_type (type), base, size),
0, 0); 0, 0);
if (base2) if (base2)
expand_assignment (base2, expand_assignment (base2,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0); build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
expand_loop_continue_here (); expand_loop_continue_here ();
expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node, expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one)); build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
@ -3489,6 +3675,13 @@ expand_vec_init (decl, base, maxindex, init, from_array)
use_variable (DECL_RTL (base2)); use_variable (DECL_RTL (base2));
} }
expand_end_loop (); expand_end_loop ();
if (TYPE_NEEDS_DESTRUCTOR (type))
end_protect (build_array_eh_cleanup (rval,
build_binary_op (MINUS_EXPR,
maxindex,
iterator,
1),
type));
expand_end_cond (); expand_end_cond ();
if (obey_regdecls) if (obey_regdecls)
use_variable (DECL_RTL (iterator)); use_variable (DECL_RTL (iterator));
@ -3848,7 +4041,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else else
this_auto_delete = integer_zero_node; this_auto_delete = integer_zero_node;
expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), addr, expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), addr,
this_auto_delete, flags, 0); this_auto_delete, flags, 0);
exprstmt = tree_cons (NULL_TREE, expr, exprstmt); exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
} }
@ -3862,10 +4055,10 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
continue; continue;
/* May be zero offset if other baseclasses are virtual. */ /* May be zero offset if other baseclasses are virtual. */
expr = fold (build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), expr = fold (build (PLUS_EXPR, build_pointer_type (BINFO_TYPE (base_binfo)),
addr, BINFO_OFFSET (base_binfo))); addr, BINFO_OFFSET (base_binfo)));
expr = build_delete (TYPE_POINTER_TO (BINFO_TYPE (base_binfo)), expr, expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
integer_zero_node, integer_zero_node,
flags, 0); flags, 0);
@ -3906,7 +4099,7 @@ build_vbase_delete (type, decl)
while (vbases) while (vbases)
{ {
tree this_addr = convert_force (TYPE_POINTER_TO (BINFO_TYPE (vbases)), tree this_addr = convert_force (build_pointer_type (BINFO_TYPE (vbases)),
addr, 0); addr, 0);
result = tree_cons (NULL_TREE, result = tree_cons (NULL_TREE,
build_delete (TREE_TYPE (this_addr), this_addr, build_delete (TREE_TYPE (this_addr), this_addr,
@ -3941,34 +4134,12 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
tree auto_delete_vec, auto_delete; tree auto_delete_vec, auto_delete;
int use_global_delete; int use_global_delete;
{ {
tree ptype, type, virtual_size; tree type;
/* Temporary variables used by the loop. */
tree tbase, size_exp, tbase_init;
/* This is the body of the loop that implements the deletion of a
single element, and moves temp variables to next elements. */
tree body;
/* This is the LOOP_EXPR that governs the deletion of the elements. */
tree loop;
/* This is the thing that governs what to do after the loop has run. */
tree deallocate_expr = 0;
/* This is the BIND_EXPR which holds the outermost iterator of the
loop. It is convenient to set this variable up and test it before
executing any other code in the loop.
This is also the containing expression returned by this function. */
tree controller = NULL_TREE;
/* This is the BLOCK to record the symbol binding for debugging. */
tree block;
if (TREE_CODE (base) == OFFSET_REF) if (TREE_CODE (base) == OFFSET_REF)
base = resolve_offset_ref (base); base = resolve_offset_ref (base);
ptype = TREE_TYPE (base); type = TREE_TYPE (base);
base = stabilize_reference (base); base = stabilize_reference (base);
@ -3976,23 +4147,23 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
if (TREE_SIDE_EFFECTS (base)) if (TREE_SIDE_EFFECTS (base))
base = save_expr (base); base = save_expr (base);
if (TREE_CODE (ptype) == POINTER_TYPE) if (TREE_CODE (type) == POINTER_TYPE)
{ {
/* Step back one from start of vector, and read dimension. */ /* Step back one from start of vector, and read dimension. */
tree cookie_addr = build (MINUS_EXPR, TYPE_POINTER_TO (BI_header_type), tree cookie_addr = build (MINUS_EXPR, build_pointer_type (BI_header_type),
base, BI_header_size); base, BI_header_size);
tree cookie = build_indirect_ref (cookie_addr, NULL_PTR); tree cookie = build_indirect_ref (cookie_addr, NULL_PTR);
maxindex = build_component_ref (cookie, nc_nelts_field_id, 0, 0); maxindex = build_component_ref (cookie, nc_nelts_field_id, 0, 0);
do do
ptype = TREE_TYPE (ptype); type = TREE_TYPE (type);
while (TREE_CODE (ptype) == ARRAY_TYPE); while (TREE_CODE (type) == ARRAY_TYPE);
} }
else if (TREE_CODE (ptype) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
{ {
/* get the total number of things in the array, maxindex is a bad name */ /* get the total number of things in the array, maxindex is a bad name */
maxindex = array_type_nelts_total (ptype); maxindex = array_type_nelts_total (type);
while (TREE_CODE (ptype) == ARRAY_TYPE) while (TREE_CODE (type) == ARRAY_TYPE)
ptype = TREE_TYPE (ptype); type = TREE_TYPE (type);
base = build_unary_op (ADDR_EXPR, base, 1); base = build_unary_op (ADDR_EXPR, base, 1);
} }
else else
@ -4000,129 +4171,7 @@ build_vec_delete (base, maxindex, elt_size, auto_delete_vec, auto_delete,
error ("type to vector delete is neither pointer or array type"); error ("type to vector delete is neither pointer or array type");
return error_mark_node; return error_mark_node;
} }
type = ptype;
ptype = TYPE_POINTER_TO (type);
size_exp = size_in_bytes (type); return build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
use_global_delete);
if (! IS_AGGR_TYPE (type) || ! TYPE_NEEDS_DESTRUCTOR (type))
{
loop = integer_zero_node;
goto no_destructor;
}
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
tbase = build_decl (VAR_DECL, NULL_TREE, ptype);
tbase_init = build_modify_expr (tbase, NOP_EXPR,
fold (build (PLUS_EXPR, ptype,
base,
virtual_size)));
DECL_REGISTER (tbase) = 1;
controller = build (BIND_EXPR, void_type_node, tbase, 0, 0);
TREE_SIDE_EFFECTS (controller) = 1;
block = build_block (tbase, 0, 0, 0, 0);
add_block_current_level (block);
if (auto_delete != integer_zero_node
&& auto_delete != integer_two_node)
{
tree base_tbd = convert (ptype,
build_binary_op (MINUS_EXPR,
convert (ptr_type_node, base),
BI_header_size,
1));
/* This is the real size */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
body = build_tree_list (NULL_TREE,
build_x_delete (ptype, base_tbd,
2 | use_global_delete,
virtual_size));
body = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
auto_delete, integer_one_node),
body, integer_zero_node);
}
else
body = NULL_TREE;
body = tree_cons (NULL_TREE,
build_delete (ptype, tbase, auto_delete,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1),
body);
body = tree_cons (NULL_TREE,
build_modify_expr (tbase, NOP_EXPR, build (MINUS_EXPR, ptype, tbase, size_exp)),
body);
body = tree_cons (NULL_TREE,
build (EXIT_EXPR, void_type_node,
build (EQ_EXPR, boolean_type_node, base, tbase)),
body);
loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
loop = tree_cons (NULL_TREE, tbase_init,
tree_cons (NULL_TREE, loop, NULL_TREE));
loop = build_compound_expr (loop);
no_destructor:
/* If the delete flag is one, or anything else with the low bit set,
delete the storage. */
if (auto_delete_vec == integer_zero_node
|| auto_delete_vec == integer_two_node)
deallocate_expr = integer_zero_node;
else
{
tree base_tbd;
/* The below is short by BI_header_size */
virtual_size = fold (size_binop (MULT_EXPR, size_exp, maxindex));
if (! TYPE_VEC_NEW_USES_COOKIE (type))
/* no header */
base_tbd = base;
else
{
base_tbd = convert (ptype,
build_binary_op (MINUS_EXPR,
convert (string_type_node, base),
BI_header_size,
1));
/* True size with header. */
virtual_size = size_binop (PLUS_EXPR, virtual_size, BI_header_size);
}
deallocate_expr = build_x_delete (ptype, base_tbd,
2 | use_global_delete,
virtual_size);
if (auto_delete_vec != integer_one_node)
deallocate_expr = build (COND_EXPR, void_type_node,
build (BIT_AND_EXPR, integer_type_node,
auto_delete_vec, integer_one_node),
deallocate_expr, integer_zero_node);
}
if (loop && deallocate_expr != integer_zero_node)
{
body = tree_cons (NULL_TREE, loop,
tree_cons (NULL_TREE, deallocate_expr, NULL_TREE));
body = build_compound_expr (body);
}
else
body = loop;
/* Outermost wrapper: If pointer is null, punt. */
body = build (COND_EXPR, void_type_node,
build (NE_EXPR, boolean_type_node, base, integer_zero_node),
body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body);
if (controller)
{
TREE_OPERAND (controller, 1) = body;
return controller;
}
else
return convert (void_type_node, body);
} }

View File

@ -1559,8 +1559,8 @@ reinit_parse_for_method (yychar, decl)
output if something goes wrong. This should really be cleaned up somehow, output if something goes wrong. This should really be cleaned up somehow,
without loss of clarity. */ without loss of clarity. */
void void
reinit_parse_for_block (yychar, obstackp, is_template) reinit_parse_for_block (pyychar, obstackp, is_template)
int yychar; int pyychar;
struct obstack *obstackp; struct obstack *obstackp;
int is_template; int is_template;
{ {
@ -1572,23 +1572,35 @@ reinit_parse_for_block (yychar, obstackp, is_template)
int look_for_semicolon = 0; int look_for_semicolon = 0;
int look_for_lbrac = 0; int look_for_lbrac = 0;
if (yychar == '{') if (pyychar == '{')
obstack_1grow (obstackp, '{'); obstack_1grow (obstackp, '{');
else if (yychar == '=') else if (pyychar == '=')
look_for_semicolon = 1; look_for_semicolon = 1;
else if (yychar != ':' && (yychar != RETURN || is_template)) else if (pyychar == ':')
{
obstack_1grow (obstackp, pyychar);
look_for_lbrac = 1;
blev = 0;
}
else if (pyychar == RETURN && !is_template)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
blev = 0;
}
else if (pyychar == TRY && !is_template)
{
obstack_grow (obstackp, "try", 3);
look_for_lbrac = 1;
blev = 0;
}
else
{ {
yyerror (is_template yyerror (is_template
? "parse error in template specification" ? "parse error in template specification"
: "parse error in method specification"); : "parse error in method specification");
obstack_1grow (obstackp, '{'); obstack_1grow (obstackp, '{');
} }
else
{
obstack_1grow (obstackp, yychar);
look_for_lbrac = 1;
blev = 0;
}
if (nextchar != EOF) if (nextchar != EOF)
{ {
@ -1640,7 +1652,26 @@ reinit_parse_for_block (yychar, obstackp, is_template)
{ {
blev--; blev--;
if (blev == 0 && !look_for_semicolon) if (blev == 0 && !look_for_semicolon)
goto done; {
if (pyychar == TRY)
{
if (peekyylex () == CATCH)
{
yylex ();
obstack_grow (obstackp, " catch ", 7);
look_for_lbrac = 1;
}
else
{
yychar = '{';
goto done;
}
}
else
{
goto done;
}
}
} }
else if (c == '\\') else if (c == '\\')
{ {
@ -1783,7 +1814,8 @@ cons_up_default_function (type, full_name, kind)
if (retref) if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator); declarator = build_parse_node (ADDR_EXPR, declarator);
fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
} }
if (fn == void_type_node) if (fn == void_type_node)
@ -2278,8 +2310,8 @@ check_newline ()
} }
#endif #endif
#endif #endif
goto skipline;
} }
goto skipline;
} }
else if (c == 'd') else if (c == 'd')
{ {
@ -2817,6 +2849,9 @@ identifier_type (decl)
void void
see_typename () see_typename ()
{ {
looking_for_typename = 1;
if (yychar < 0)
if ((yychar = yylex()) < 0) yychar = 0;
looking_for_typename = 0; looking_for_typename = 0;
if (yychar == IDENTIFIER) if (yychar == IDENTIFIER)
{ {
@ -2920,8 +2955,6 @@ do_identifier (token)
if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id)) if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
{ {
tree shadowed = DECL_SHADOWED_FOR_VAR (id); tree shadowed = DECL_SHADOWED_FOR_VAR (id);
if (!shadowed)
shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
if (shadowed) if (shadowed)
{ {
if (!DECL_ERROR_REPORTED (id)) if (!DECL_ERROR_REPORTED (id))
@ -3143,6 +3176,12 @@ real_yylex ()
*p++ = c; *p++ = c;
c = getc (finput); c = getc (finput);
} }
if (linemode && c == '\n')
{
put_back (c);
c = EOF;
}
} }
else else
{ {
@ -4668,7 +4707,10 @@ handle_sysv_pragma ()
handle_pragma_token (NULL_PTR, NULL_TREE); handle_pragma_token (NULL_PTR, NULL_TREE);
return; return;
default: default:
abort (); handle_pragma_token (NULL_PTR, NULL_TREE);
while (yylex () != END_OF_LINE)
/* continue */;
return;
} }
} }
} }

View File

@ -165,14 +165,6 @@ report_type_mismatch (cp, parmtypes, name_kind)
cp->function); cp->function);
return; return;
case -3:
if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))))
cp_error ("call to const %s `%#D' with non-const object", name_kind,
cp->function);
else
cp_error ("call to non-const %s `%#D' with const object", name_kind,
cp->function);
return;
case -2: case -2:
cp_error ("too few arguments for %s `%#D'", name_kind, cp->function); cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
return; return;
@ -180,14 +172,15 @@ report_type_mismatch (cp, parmtypes, name_kind)
cp_error ("too many arguments for %s `%#D'", name_kind, cp->function); cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
return; return;
case 0: case 0:
if (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE) if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE)
{ break;
/* Happens when we have an ambiguous base class. */ case -3:
my_friendly_assert (get_binfo (DECL_CLASS_CONTEXT (cp->function), /* Happens when the implicit object parameter is rejected. */
TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))), 1) == error_mark_node, my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
241); 241);
return; cp_error ("call to non-const %s `%#D' with const object",
} name_kind, cp->function);
return;
} }
ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function)); ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
@ -512,6 +505,12 @@ build_overload_value (type, value)
sorry ("template instantiation with pointer to method that is too complex"); sorry ("template instantiation with pointer to method that is too complex");
return; return;
} }
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value);
numeric_output_need_bar = 1;
return;
}
value = TREE_OPERAND (value, 0); value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL) if (TREE_CODE (value) == VAR_DECL)
{ {
@ -1803,7 +1802,9 @@ make_thunk (function, delta)
{ {
thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl));
DECL_RESULT (thunk) DECL_RESULT (thunk)
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type)); = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type)));
TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type));
TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type));
make_function_rtl (thunk); make_function_rtl (thunk);
DECL_INITIAL (thunk) = function; DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta; THUNK_DELTA (thunk) = delta;
@ -2249,7 +2250,7 @@ synthesize_method (fndecl)
input_filename = DECL_SOURCE_FILE (fndecl); input_filename = DECL_SOURCE_FILE (fndecl);
interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base); interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
interface_only = CLASSTYPE_INTERFACE_ONLY (base); interface_only = CLASSTYPE_INTERFACE_ONLY (base);
start_function (NULL_TREE, fndecl, NULL_TREE, 1); start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
store_parm_decls (); store_parm_decls ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])

View File

@ -131,7 +131,7 @@ empty_parms ()
/* SCO include files test "ASM", so use something else. */ /* SCO include files test "ASM", so use something else. */
%token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %token SIZEOF ENUM /* STRUCT UNION */ IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD GCC_ASM_KEYWORD TYPEOF ALIGNOF %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD GCC_ASM_KEYWORD TYPEOF ALIGNOF
%token HEADOF CLASSOF SIGOF %token SIGOF
%token ATTRIBUTE EXTENSION LABEL %token ATTRIBUTE EXTENSION LABEL
/* the reserved words... C++ extensions */ /* the reserved words... C++ extensions */
@ -204,17 +204,17 @@ empty_parms ()
%type <ttype> direct_notype_declarator direct_after_type_declarator %type <ttype> direct_notype_declarator direct_after_type_declarator
%type <ttype> structsp opt.component_decl_list component_decl_list %type <ttype> structsp opt.component_decl_list component_decl_list
%type <ttype> component_decl components component_declarator %type <ttype> component_decl component_decl_1 components notype_components
%type <ttype> notype_components notype_component_declarator %type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0 %type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> notype_component_declarator0 component_decl_1
%type <ttype> enumlist enumerator %type <ttype> enumlist enumerator
%type <ttype> type_id absdcl type_quals %type <ttype> type_id absdcl type_quals
%type <ttype> direct_abstract_declarator conversion_declarator %type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_type_id new_declarator direct_new_declarator %type <ttype> new_type_id new_declarator direct_new_declarator
%type <ttype> xexpr parmlist parms parm bad_parm full_parm %type <ttype> xexpr parmlist parms parm bad_parm full_parm
%type <ttype> identifiers_or_typenames %type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr %type <ttype> fcast_or_absdcl regcast_or_absdcl
%type <ttype> expr_or_declarator complex_notype_declarator %type <ttype> expr_or_declarator complex_notype_declarator
%type <ttype> notype_unqualified_id unqualified_id qualified_id %type <ttype> notype_unqualified_id unqualified_id qualified_id
%type <ttype> overqualified_id notype_qualified_id any_id %type <ttype> overqualified_id notype_qualified_id any_id
@ -227,13 +227,13 @@ empty_parms ()
%token <ttype> PRE_PARSED_CLASS_DECL %token <ttype> PRE_PARSED_CLASS_DECL
%type <ttype> fn.def1 /* Not really! */ %type <ttype> fn.def1 /* Not really! */
%type <ttype> fn.def2 return_id %type <ttype> fn.def2 return_id
%type <itype> ctor_initializer_opt
%type <ttype> named_class_head named_class_head_sans_basetype %type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> unnamed_class_head %type <ttype> unnamed_class_head
%type <ttype> class_head base_class_list %type <ttype> class_head base_class_list
%type <itype> base_class_access_list %type <itype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1 %type <ttype> base_class maybe_base_class_list base_class.1
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers %type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
%type <ttype> component_declarator0
%type <ttype> operator_name %type <ttype> operator_name
%type <ttype> object aggr %type <ttype> object aggr
%type <itype> new delete %type <itype> new delete
@ -273,7 +273,12 @@ empty_parms ()
%{ %{
/* List of types and structure classes of the current declaration. */ /* List of types and structure classes of the current declaration. */
static tree current_declspecs; static tree current_declspecs;
static tree prefix_attributes = NULL_TREE; /* List of prefix attributes in effect.
Prefix attributes are parsed by the reserved_declspecs and declmods
rules. They create a list that contains *both* declspecs and attrs. */
/* ??? It is not clear yet that all cases where an attribute can now appear in
a declspec list have been updated. */
static tree prefix_attributes;
/* When defining an aggregate, this is the most recent one being defined. */ /* When defining an aggregate, this is the most recent one being defined. */
static tree current_aggr; static tree current_aggr;
@ -331,8 +336,7 @@ lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); } { if (pending_lang_change) do_pending_lang_change(); }
extdef extdef
{ if (! toplevel_bindings_p () && ! pseudo_global_level_p()) { if (! toplevel_bindings_p () && ! pseudo_global_level_p())
pop_everything (); pop_everything (); }
prefix_attributes = NULL_TREE; }
; ;
extdef: extdef:
@ -423,6 +427,10 @@ template_type_parm:
} }
| aggr identifier | aggr identifier
{ $$ = build_tree_list ($1, $2); goto ttpa; } { $$ = build_tree_list ($1, $2); goto ttpa; }
| TYPENAME_KEYWORD
{ $$ = build_tree_list (class_type_node, NULL_TREE); }
| TYPENAME_KEYWORD identifier
{ $$ = build_tree_list (class_type_node, $2); }
; ;
template_parm: template_parm:
@ -496,7 +504,7 @@ template_def:
momentary = suspend_momentary (); momentary = suspend_momentary ();
d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0, d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0,
$3); $3);
cplus_decl_attributes (d, $5, prefix_attributes); cplus_decl_attributes (d, $5, /*prefix_attributes*/NULL_TREE);
cp_finish_decl (d, NULL_TREE, $4, 0, 0); cp_finish_decl (d, NULL_TREE, $4, 0, 0);
end_template_decl ($1, d, 0, def); end_template_decl ($1, d, 0, def);
if (def) if (def)
@ -507,15 +515,13 @@ template_def:
declarator exception_specification_opt maybeasm maybe_attribute declarator exception_specification_opt maybeasm maybe_attribute
fn_tmpl_end fn_tmpl_end
{ {
tree d; tree d, specs, attrs;
int momentary; int momentary;
int def = ($7 != ';'); int def = ($7 != ';');
split_specs_attrs ($2, &specs, &attrs);
current_declspecs = $2;
momentary = suspend_momentary (); momentary = suspend_momentary ();
d = start_decl ($<ttype>3, current_declspecs, d = start_decl ($<ttype>3, specs, 0, $<ttype>4);
0, $<ttype>4); cplus_decl_attributes (d, $6, attrs);
cplus_decl_attributes (d, $6, prefix_attributes);
cp_finish_decl (d, NULL_TREE, $5, 0, 0); cp_finish_decl (d, NULL_TREE, $5, 0, 0);
end_template_decl ($1, d, 0, def); end_template_decl ($1, d, 0, def);
if (def) if (def)
@ -528,9 +534,11 @@ template_def:
} }
| template_header declmods notype_declarator fn_tmpl_end | template_header declmods notype_declarator fn_tmpl_end
{ {
tree d, specs, attrs;
int def = ($4 != ';'); int def = ($4 != ';');
tree d = start_decl ($<ttype>3, $<ttype>2, 0, NULL_TREE); split_specs_attrs ($2, &specs, &attrs);
cplus_decl_attributes (d, NULL_TREE, prefix_attributes); d = start_decl ($<ttype>3, specs, 0, NULL_TREE);
cplus_decl_attributes (d, NULL_TREE, attrs);
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
end_template_decl ($1, d, 0, def); end_template_decl ($1, d, 0, def);
if (def) if (def)
@ -555,9 +563,10 @@ datadef:
{} {}
/* Normal case to make fast: "const i;". */ /* Normal case to make fast: "const i;". */
| declmods notype_declarator ';' | declmods notype_declarator ';'
{ tree d; { tree d, specs, attrs;
d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE); split_specs_attrs ($1, &specs, &attrs);
cplus_decl_attributes (d, NULL_TREE, prefix_attributes); d = start_decl ($<ttype>2, specs, 0, NULL_TREE);
cplus_decl_attributes (d, NULL_TREE, attrs);
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
} }
| typed_declspecs initdecls ';' | typed_declspecs initdecls ';'
@ -566,9 +575,10 @@ datadef:
} }
/* Normal case: make this fast. */ /* Normal case: make this fast. */
| typed_declspecs declarator ';' | typed_declspecs declarator ';'
{ tree d; { tree d, specs, attrs;
d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE); split_specs_attrs ($1, &specs, &attrs);
cplus_decl_attributes (d, NULL_TREE, prefix_attributes); d = start_decl ($<ttype>2, specs, 0, NULL_TREE);
cplus_decl_attributes (d, NULL_TREE, attrs);
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
note_list_got_semicolon ($<ttype>$); note_list_got_semicolon ($<ttype>$);
} }
@ -577,7 +587,8 @@ datadef:
| explicit_instantiation ';' | explicit_instantiation ';'
| typed_declspecs ';' | typed_declspecs ';'
{ {
tree t = $<ttype>$; tree t, attrs;
split_specs_attrs ($1, &t, &attrs);
shadow_tag (t); shadow_tag (t);
if (TREE_CODE (t) == TREE_LIST if (TREE_CODE (t) == TREE_LIST
&& TREE_PURPOSE (t) == NULL_TREE) && TREE_PURPOSE (t) == NULL_TREE)
@ -599,42 +610,35 @@ datadef:
| ';' | ';'
; ;
ctor_initializer_opt:
nodecls
{ $$ = 0; }
| base_init
{ $$ = 1; }
;
maybe_return_init:
/* empty */
| return_init
| return_init ';'
;
eat_saved_input:
/* empty */
| END_OF_SAVED_INPUT
;
fndef: fndef:
fn.def1 base_init compstmt_or_error fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ {
finish_function (lineno, 1, 0); finish_function (lineno, (int)$3, 0);
/* finish_function performs these three statements:
expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 1, 0);
expand_end_bindings (0, 0, 0);
poplevel (0, 0, 1);
*/
if ($<ttype>$) process_next_inline ($<ttype>$); if ($<ttype>$) process_next_inline ($<ttype>$);
} }
| fn.def1 return_init base_init compstmt_or_error | fn.def1 maybe_return_init function_try_block
{ {
finish_function (lineno, 1, 0);
/* finish_function performs these three statements:
expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 1, 0);
expand_end_bindings (0, 0, 0);
poplevel (0, 0, 1);
*/
if ($<ttype>$) process_next_inline ($<ttype>$); if ($<ttype>$) process_next_inline ($<ttype>$);
} }
| fn.def1 nodecls compstmt_or_error eat_saved_input
{ finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); }
| fn.def1 return_init ';' nodecls compstmt_or_error
{ finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); }
| fn.def1 return_init nodecls compstmt_or_error
{ finish_function (lineno, 0, 0);
if ($<ttype>$) process_next_inline ($<ttype>$); }
| typed_declspecs declarator error | typed_declspecs declarator error
{} {}
| declmods notype_declarator error | declmods notype_declarator error
@ -645,22 +649,26 @@ fndef:
fn.def1: fn.def1:
typed_declspecs declarator exception_specification_opt typed_declspecs declarator exception_specification_opt
{ if (! start_function ($$, $2, $3, 0)) { tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
if (! start_function (specs, $2, $3, attrs, 0))
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
| declmods notype_declarator exception_specification_opt | declmods notype_declarator exception_specification_opt
{ if (! start_function ($$, $2, $3, 0)) { tree specs = strip_attrs ($1);
if (! start_function (specs, $2, $3, NULL_TREE, 0))
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
| notype_declarator exception_specification_opt | notype_declarator exception_specification_opt
{ if (! start_function (NULL_TREE, $$, $2, 0)) { if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0))
YYERROR1; YYERROR1;
reinit_parse_for_function (); reinit_parse_for_function ();
$$ = NULL_TREE; } $$ = NULL_TREE; }
| PRE_PARSED_FUNCTION_DECL | PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($$), NULL_TREE, 1); { start_function (NULL_TREE, TREE_VALUE ($$),
NULL_TREE, NULL_TREE, 1);
reinit_parse_for_function (); } reinit_parse_for_function (); }
; ;
@ -668,9 +676,9 @@ fn.def1:
reduce/reduce conflict introduced by these rules. */ reduce/reduce conflict introduced by these rules. */
fn.def2: fn.def2:
typed_declspecs '(' parmlist ')' type_quals exception_specification_opt typed_declspecs '(' parmlist ')' type_quals exception_specification_opt
{ { tree specs = strip_attrs ($1);
$$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $3, $5); $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs), $3, $5);
$$ = start_method (TREE_CHAIN ($1), $$, $6); $$ = start_method (TREE_CHAIN (specs), $$, $6);
rest_of_mdef: rest_of_mdef:
if (! $$) if (! $$)
YYERROR1; YYERROR1;
@ -678,16 +686,18 @@ fn.def2:
yychar = YYLEX; yychar = YYLEX;
reinit_parse_for_method (yychar, $$); } reinit_parse_for_method (yychar, $$); }
| typed_declspecs LEFT_RIGHT type_quals exception_specification_opt | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt
{ { tree specs = strip_attrs ($1);
$$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), $$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
empty_parms (), $3); empty_parms (), $3);
$$ = start_method (TREE_CHAIN ($1), $$, $4); $$ = start_method (TREE_CHAIN (specs), $$, $4);
goto rest_of_mdef; goto rest_of_mdef;
} }
| typed_declspecs declarator exception_specification_opt | typed_declspecs declarator exception_specification_opt
{ $$ = start_method ($$, $2, $3); goto rest_of_mdef; } { tree specs = strip_attrs ($1);
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
| declmods notype_declarator exception_specification_opt | declmods notype_declarator exception_specification_opt
{ $$ = start_method ($$, $2, $3); goto rest_of_mdef; } { tree specs = strip_attrs ($1);
$$ = start_method (specs, $2, $3); goto rest_of_mdef; }
| notype_declarator exception_specification_opt | notype_declarator exception_specification_opt
{ $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; } { $$ = start_method (NULL_TREE, $$, $2); goto rest_of_mdef; }
; ;
@ -804,11 +814,13 @@ explicit_instantiation:
TEMPLATE specialization template_instantiation TEMPLATE specialization template_instantiation
{ do_type_instantiation ($3 ? $3 : $2, NULL_TREE); } { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
| TEMPLATE typed_declspecs declarator | TEMPLATE typed_declspecs declarator
{ do_function_instantiation ($2, $3, NULL_TREE); } { tree specs = strip_attrs ($2);
do_function_instantiation (specs, $3, NULL_TREE); }
| SCSPEC TEMPLATE specialization template_instantiation | SCSPEC TEMPLATE specialization template_instantiation
{ do_type_instantiation ($4 ? $4 : $3, $1); } { do_type_instantiation ($4 ? $4 : $3, $1); }
| SCSPEC TEMPLATE typed_declspecs declarator | SCSPEC TEMPLATE typed_declspecs declarator
{ do_function_instantiation ($3, $4, $1); } { tree specs = strip_attrs ($3);
do_function_instantiation (specs, $4, $1); }
; ;
template_type: template_type:
@ -969,7 +981,8 @@ condition:
current_declspecs = $1; current_declspecs = $1;
$<itype>6 = suspend_momentary (); $<itype>6 = suspend_momentary ();
$<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3); $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3);
cplus_decl_attributes ($<ttype>$, $5, prefix_attributes); cplus_decl_attributes ($<ttype>$, $5,
/*prefix_attributes*/ NULL_TREE);
} }
init init
{ {
@ -1160,8 +1173,8 @@ regcast_or_absdcl:
; ;
cast_expr: cast_expr:
sub_cast_expr unary_expr
| regcast_or_absdcl sub_cast_expr %prec UNARY | regcast_or_absdcl unary_expr %prec UNARY
{ $$ = reparse_absdcl_as_casts ($$, $2); } { $$ = reparse_absdcl_as_casts ($$, $2); }
| regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY | regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY
{ {
@ -1176,29 +1189,6 @@ cast_expr:
} }
; ;
sub_cast_expr:
unary_expr
| HEADOF '(' expr ')'
{ $$ = build_headof ($3); }
| CLASSOF '(' expr ')'
{ $$ = build_classof ($3); }
| CLASSOF '(' TYPENAME ')'
{ if (is_aggr_typedef ($3, 1))
{
tree type = IDENTIFIER_TYPE_VALUE ($3);
if (! IS_SIGNATURE(type))
$$ = CLASSTYPE_RTTI (type);
else
{
sorry ("signature name as argument of `classof'");
$$ = error_mark_node;
}
}
else
$$ = error_mark_node;
}
;
expr_no_commas: expr_no_commas:
cast_expr cast_expr
/* Handle general members. */ /* Handle general members. */
@ -1736,10 +1726,6 @@ object: primary '.'
} }
; ;
setattrs: /* empty */
{ prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
;
decl: decl:
/* Normal case: make this fast. */ /* Normal case: make this fast. */
typespec declarator ';' typespec declarator ';'
@ -1752,10 +1738,12 @@ decl:
note_got_semicolon ($1); note_got_semicolon ($1);
} }
| typed_declspecs declarator ';' | typed_declspecs declarator ';'
{ tree d = $1; { tree d, specs, attrs;
int yes = suspend_momentary (); int yes;
d = start_decl ($2, d, 0, NULL_TREE); split_specs_attrs ($1, &specs, &attrs);
cplus_decl_attributes (d, NULL_TREE, prefix_attributes); yes = suspend_momentary ();
d = start_decl ($2, specs, 0, NULL_TREE);
cplus_decl_attributes (d, NULL_TREE, attrs);
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
resume_momentary (yes); resume_momentary (yes);
note_list_got_semicolon ($1); note_list_got_semicolon ($1);
@ -1816,7 +1804,8 @@ type_id:
/* Declspecs which contain at least one type specifier or typedef name. /* Declspecs which contain at least one type specifier or typedef name.
(Just `const' or `volatile' is not enough.) (Just `const' or `volatile' is not enough.)
A typedef'd name following these is taken as a name to be declared. */ A typedef'd name following these is taken as a name to be declared.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
typed_declspecs: typed_declspecs:
typed_typespecs %prec EMPTY typed_typespecs %prec EMPTY
@ -1852,15 +1841,16 @@ reserved_declspecs:
warning ("`%s' is not at beginning of declaration", warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2)); IDENTIFIER_POINTER ($2));
$$ = decl_tree_cons (NULL_TREE, $2, $$); } $$ = decl_tree_cons (NULL_TREE, $2, $$); }
| reserved_declspecs attributes setattrs | reserved_declspecs attributes
{ $$ = $1; } { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
| attributes setattrs | attributes
{ $$ = NULL_TREE; } { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
; ;
/* List of just storage classes and type modifiers. /* List of just storage classes and type modifiers.
A declaration can start with just this, but then it cannot be used A declaration can start with just this, but then it cannot be used
to redeclare a typedef-name. */ to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
declmods: declmods:
nonempty_type_quals %prec EMPTY nonempty_type_quals %prec EMPTY
@ -1876,13 +1866,12 @@ declmods:
IDENTIFIER_POINTER ($2)); IDENTIFIER_POINTER ($2));
$$ = decl_tree_cons (NULL_TREE, $2, $$); $$ = decl_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); } TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes setattrs | declmods attributes
{ $$ = $1; } { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
| attributes setattrs | attributes
{ $$ = NULL_TREE; } { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
; ;
/* Used instead of declspecs where storage classes are not allowed /* Used instead of declspecs where storage classes are not allowed
(that is, for typenames and structure components). (that is, for typenames and structure components).
@ -1916,11 +1905,11 @@ typespec: structsp
| complete_type_name | complete_type_name
| TYPEOF '(' expr ')' | TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3); { $$ = TREE_TYPE ($3);
if (pedantic) if (pedantic && !in_system_header)
pedwarn ("ANSI C++ forbids `typeof'"); } pedwarn ("ANSI C++ forbids `typeof'"); }
| TYPEOF '(' type_id ')' | TYPEOF '(' type_id ')'
{ $$ = groktypename ($3); { $$ = groktypename ($3);
if (pedantic) if (pedantic && !in_system_header)
pedwarn ("ANSI C++ forbids `typeof'"); } pedwarn ("ANSI C++ forbids `typeof'"); }
| SIGOF '(' expr ')' | SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3); { tree type = TREE_TYPE ($3);
@ -1983,7 +1972,8 @@ maybeasm:
initdcl0: initdcl0:
declarator exception_specification_opt maybeasm maybe_attribute '=' declarator exception_specification_opt maybeasm maybe_attribute '='
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
if (TREE_CODE (current_declspecs) != TREE_LIST) if (TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs); current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec) if (have_extern_spec && !used_extern_spec)
@ -2002,7 +1992,8 @@ initdcl0:
$$ = $<itype>5; } $$ = $<itype>5; }
| declarator exception_specification_opt maybeasm maybe_attribute | declarator exception_specification_opt maybeasm maybe_attribute
{ tree d; { tree d;
current_declspecs = $<ttype>0; split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
if (TREE_CODE (current_declspecs) != TREE_LIST) if (TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs); current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec) if (have_extern_spec && !used_extern_spec)
@ -2033,7 +2024,8 @@ initdcl:
notype_initdcl0: notype_initdcl0:
notype_declarator exception_specification_opt maybeasm maybe_attribute '=' notype_declarator exception_specification_opt maybeasm maybe_attribute '='
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<itype>5 = suspend_momentary (); $<itype>5 = suspend_momentary ();
$<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2); $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); } cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
@ -2043,7 +2035,8 @@ notype_initdcl0:
$$ = $<itype>5; } $$ = $<itype>5; }
| notype_declarator exception_specification_opt maybeasm maybe_attribute | notype_declarator exception_specification_opt maybeasm maybe_attribute
{ tree d; { tree d;
current_declspecs = $<ttype>0; split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$$ = suspend_momentary (); $$ = suspend_momentary ();
d = start_decl ($<ttype>1, current_declspecs, 0, $2); d = start_decl ($<ttype>1, current_declspecs, 0, $2);
cplus_decl_attributes (d, $4, prefix_attributes); cplus_decl_attributes (d, $4, prefix_attributes);
@ -2053,6 +2046,7 @@ notype_initdcl0:
nomods_initdcl0: nomods_initdcl0:
notype_declarator exception_specification_opt maybeasm maybe_attribute '=' notype_declarator exception_specification_opt maybeasm maybe_attribute '='
{ current_declspecs = NULL_TREE; { current_declspecs = NULL_TREE;
prefix_attributes = NULL_TREE;
$<itype>5 = suspend_momentary (); $<itype>5 = suspend_momentary ();
$<ttype>$ = start_decl ($1, current_declspecs, 1, $2); $<ttype>$ = start_decl ($1, current_declspecs, 1, $2);
cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); } cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
@ -2063,6 +2057,7 @@ nomods_initdcl0:
| notype_declarator exception_specification_opt maybeasm maybe_attribute | notype_declarator exception_specification_opt maybeasm maybe_attribute
{ tree d; { tree d;
current_declspecs = NULL_TREE; current_declspecs = NULL_TREE;
prefix_attributes = NULL_TREE;
$$ = suspend_momentary (); $$ = suspend_momentary ();
d = start_decl ($1, current_declspecs, 0, $2); d = start_decl ($1, current_declspecs, 0, $2);
cplus_decl_attributes (d, $4, prefix_attributes); cplus_decl_attributes (d, $4, prefix_attributes);
@ -2333,23 +2328,22 @@ class_head: unnamed_class_head | named_class_head ;
maybe_base_class_list: maybe_base_class_list:
%prec EMPTY /* empty */ %prec EMPTY /* empty */
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
| ':' %prec EMPTY | ':' see_typename %prec EMPTY
{ yyungetc(':', 1); $$ = NULL_TREE; } { yyungetc(':', 1); $$ = NULL_TREE; }
| ':' base_class_list %prec EMPTY | ':' see_typename base_class_list %prec EMPTY
{ $$ = $2; } { $$ = $3; }
; ;
base_class_list: base_class_list:
base_class base_class
| base_class_list ',' base_class | base_class_list ',' see_typename base_class
{ $$ = chainon ($$, $3); } { $$ = chainon ($$, $4); }
; ;
base_class: base_class:
base_class.1 base_class.1
{ {
tree type; tree type;
do_base_class1:
type = IDENTIFIER_TYPE_VALUE ($$); type = IDENTIFIER_TYPE_VALUE ($$);
if (! is_aggr_typedef ($$, 1)) if (! is_aggr_typedef ($$, 1))
$$ = NULL_TREE; $$ = NULL_TREE;
@ -2373,14 +2367,13 @@ base_class:
else else
$$ = build_tree_list ((tree)access_default, $$); $$ = build_tree_list ((tree)access_default, $$);
} }
| base_class_access_list base_class.1 | base_class_access_list see_typename base_class.1
{ {
tree type; tree type;
do_base_class2: type = IDENTIFIER_TYPE_VALUE ($3);
type = IDENTIFIER_TYPE_VALUE ($2);
if (current_aggr == signature_type_node) if (current_aggr == signature_type_node)
error ("access and source specifiers not allowed in signature"); error ("access and source specifiers not allowed in signature");
if (! is_aggr_typedef ($2, 1)) if (! is_aggr_typedef ($3, 1))
$$ = NULL_TREE; $$ = NULL_TREE;
else if (current_aggr == signature_type_node else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type))) && (! type) && (! IS_SIGNATURE (type)))
@ -2392,7 +2385,7 @@ base_class:
{ {
sorry ("signature inheritance, base type `%s' ignored", sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER ($$)); IDENTIFIER_POINTER ($$));
$$ = build_tree_list ((tree)access_public, $2); $$ = build_tree_list ((tree)access_public, $3);
} }
else if (type && IS_SIGNATURE (type)) else if (type && IS_SIGNATURE (type))
{ {
@ -2400,7 +2393,7 @@ base_class:
$$ = NULL_TREE; $$ = NULL_TREE;
} }
else else
$$ = build_tree_list ((tree) $$, $2); $$ = build_tree_list ((tree) $$, $3);
} }
; ;
@ -2453,12 +2446,12 @@ base_class.1:
; ;
base_class_access_list: base_class_access_list:
VISSPEC VISSPEC see_typename
| SCSPEC | SCSPEC see_typename
{ if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL]) { if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL])
sorry ("non-virtual access"); sorry ("non-virtual access");
$$ = access_default_virtual; } $$ = access_default_virtual; }
| base_class_access_list VISSPEC | base_class_access_list VISSPEC see_typename
{ int err = 0; { int err = 0;
if ($2 == access_protected) if ($2 == access_protected)
{ {
@ -2484,7 +2477,7 @@ base_class_access_list:
$$ = access_private_virtual; $$ = access_private_virtual;
} }
} }
| base_class_access_list SCSPEC | base_class_access_list SCSPEC see_typename
{ if ($2 != ridpointers[(int)RID_VIRTUAL]) { if ($2 != ridpointers[(int)RID_VIRTUAL])
sorry ("non-virtual access"); sorry ("non-virtual access");
if ($$ == access_public) if ($$ == access_public)
@ -2610,6 +2603,7 @@ component_decl_list:
component_decl: component_decl:
component_decl_1 ';' component_decl_1 ';'
{ }
| component_decl_1 '}' | component_decl_1 '}'
{ error ("missing ';' before right brace"); { error ("missing ';' before right brace");
yyungetc ('}', 0); } yyungetc ('}', 0); }
@ -2617,6 +2611,10 @@ component_decl:
/* note that INLINE is like a TYPESPEC */ /* note that INLINE is like a TYPESPEC */
| fn.def2 ':' /* base_init compstmt */ | fn.def2 ':' /* base_init compstmt */
{ $$ = finish_method ($$); } { $$ = finish_method ($$); }
| fn.def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
| fn.def2 RETURN /* base_init compstmt */
{ $$ = finish_method ($$); }
| fn.def2 '{' /* nodecls compstmt */ | fn.def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); } { $$ = finish_method ($$); }
| ';' | ';'
@ -2628,16 +2626,12 @@ component_decl_1:
speed; we need to call grok_x_components for enums, so the speed; we need to call grok_x_components for enums, so the
speedup would be insignificant. */ speedup would be insignificant. */
typed_declspecs components typed_declspecs components
{ { $$ = grok_x_components ($1, $2); }
$$ = grok_x_components ($$, $2);
}
| declmods notype_components | declmods notype_components
{ { $$ = grok_x_components ($1, $2); }
$$ = grok_x_components ($$, $2);
}
| notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init | notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $2, $5, $3); { $$ = grokfield ($$, NULL_TREE, $2, $5, $3,
cplus_decl_attributes ($$, $4, prefix_attributes); } build_tree_list ($4, NULL_TREE)); }
| ':' expr_no_commas | ':' expr_no_commas
{ $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); } { $$ = grokbitfield (NULL_TREE, NULL_TREE, $2); }
| error | error
@ -2652,20 +2646,25 @@ component_decl_1:
member? In other words, is "bar" an after_type_declarator or a member? In other words, is "bar" an after_type_declarator or a
parmlist? */ parmlist? */
| typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init | typed_declspecs '(' parmlist ')' type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), { tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
$3, $5); $3, $5);
$$ = grokfield ($$, TREE_CHAIN ($1), $6, $9, $7); $$ = grokfield ($$, TREE_CHAIN (specs), $6, $9, $7,
cplus_decl_attributes ($$, $8, prefix_attributes); } build_tree_list ($8, attrs)); }
| typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init | typed_declspecs LEFT_RIGHT type_quals exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = build_parse_node (CALL_EXPR, TREE_VALUE ($1), { tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
$$ = build_parse_node (CALL_EXPR, TREE_VALUE (specs),
empty_parms (), $3); empty_parms (), $3);
$$ = grokfield ($$, TREE_CHAIN ($1), $4, $7, $5); $$ = grokfield ($$, TREE_CHAIN (specs), $4, $7, $5,
cplus_decl_attributes ($$, $6, prefix_attributes); } build_tree_list ($6, attrs)); }
| using_decl | using_decl
{ $$ = do_class_using_decl ($1); } { $$ = do_class_using_decl ($1); }
; ;
/* The case of exactly one component is handled directly by component_decl. */ /* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */
components: components:
/* empty: possibly anonymous */ /* empty: possibly anonymous */
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
@ -2708,34 +2707,44 @@ component_declarator:
after_type_component_declarator0: after_type_component_declarator0:
after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
$$ = grokfield ($$, current_declspecs, $2, $5, $3); &prefix_attributes);
cplus_decl_attributes ($$, $4, prefix_attributes); } $<ttype>0 = current_declspecs;
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
build_tree_list ($4, prefix_attributes)); }
| TYPENAME ':' expr_no_commas maybe_attribute | TYPENAME ':' expr_no_commas maybe_attribute
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>0 = current_declspecs;
$$ = grokbitfield ($$, current_declspecs, $3); $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); } cplus_decl_attributes ($$, $4, prefix_attributes); }
; ;
notype_component_declarator0: notype_component_declarator0:
notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
$$ = grokfield ($$, current_declspecs, $2, $5, $3); &prefix_attributes);
cplus_decl_attributes ($$, $4, prefix_attributes); } $<ttype>0 = current_declspecs;
$$ = grokfield ($$, current_declspecs, $2, $5, $3,
build_tree_list ($4, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute | IDENTIFIER ':' expr_no_commas maybe_attribute
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>0 = current_declspecs;
$$ = grokbitfield ($$, current_declspecs, $3); $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); } cplus_decl_attributes ($$, $4, prefix_attributes); }
| ':' expr_no_commas maybe_attribute | ':' expr_no_commas maybe_attribute
{ current_declspecs = $<ttype>0; { split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>0 = current_declspecs;
$$ = grokbitfield (NULL_TREE, current_declspecs, $2); $$ = grokbitfield (NULL_TREE, current_declspecs, $2);
cplus_decl_attributes ($$, $3, prefix_attributes); } cplus_decl_attributes ($$, $3, prefix_attributes); }
; ;
after_type_component_declarator: after_type_component_declarator:
after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init after_type_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, current_declspecs, $2, $5, $3); { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
cplus_decl_attributes ($$, $4, prefix_attributes); } build_tree_list ($4, prefix_attributes)); }
| TYPENAME ':' expr_no_commas maybe_attribute | TYPENAME ':' expr_no_commas maybe_attribute
{ $$ = grokbitfield ($$, current_declspecs, $3); { $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); } cplus_decl_attributes ($$, $4, prefix_attributes); }
@ -2743,8 +2752,8 @@ after_type_component_declarator:
notype_component_declarator: notype_component_declarator:
notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init notype_declarator exception_specification_opt maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, current_declspecs, $2, $5, $3); { $$ = grokfield ($$, current_declspecs, $2, $5, $3,
cplus_decl_attributes ($$, $4, prefix_attributes); } build_tree_list ($4, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute | IDENTIFIER ':' expr_no_commas maybe_attribute
{ $$ = grokbitfield ($$, current_declspecs, $3); { $$ = grokbitfield ($$, current_declspecs, $3);
cplus_decl_attributes ($$, $4, prefix_attributes); } cplus_decl_attributes ($$, $4, prefix_attributes); }
@ -2926,8 +2935,12 @@ complex_direct_notype_declarator:
| direct_notype_declarator '[' ']' | direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); } { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
| notype_qualified_id | notype_qualified_id
{ push_nested_class (TREE_TYPE (OP0 ($$)), 3); { if (TREE_TYPE (OP0 ($$)) != current_class_type)
TREE_COMPLEXITY ($$) = current_class_depth; } {
push_nested_class (TREE_TYPE (OP0 ($$)), 3);
TREE_COMPLEXITY ($$) = current_class_depth;
}
}
; ;
qualified_id: qualified_id:
@ -3193,8 +3206,7 @@ stmt:
simple_stmt: simple_stmt:
decl decl
{ finish_stmt (); { finish_stmt (); }
prefix_attributes = NULL_TREE; }
| expr ';' | expr ';'
{ {
tree expr = $1; tree expr = $1;
@ -3435,6 +3447,23 @@ simple_stmt:
| try_block | try_block
; ;
function_try_block:
TRY
{
if (! current_function_parms_stored)
store_parm_decls ();
expand_start_early_try_stmts ();
}
ctor_initializer_opt compstmt_or_error
{ expand_end_try_stmts ();
expand_start_all_catch (); }
handler_seq
{
expand_end_all_catch ();
finish_function (lineno, (int)$3, 0);
}
;
try_block: try_block:
TRY TRY
{ expand_start_try_stmts (); } { expand_start_try_stmts (); }
@ -3655,10 +3684,12 @@ parms_comma:
named_parm: named_parm:
/* /*
typed_declspecs dont_see_typename '*' IDENTIFIER typed_declspecs dont_see_typename '*' IDENTIFIER
{ $$ = build_tree_list ($$, build_parse_node (INDIRECT_REF, $4)); { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, build_parse_node (INDIRECT_REF, $4));
see_typename (); } see_typename (); }
| typed_declspecs dont_see_typename '&' IDENTIFIER | typed_declspecs dont_see_typename '&' IDENTIFIER
{ $$ = build_tree_list ($$, build_parse_node (ADDR_EXPR, $4)); { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, build_parse_node (ADDR_EXPR, $4));
see_typename (); } see_typename (); }
| TYPENAME IDENTIFIER | TYPENAME IDENTIFIER
{ $$ = build_tree_list (get_decl_list ($$), $2); } { $$ = build_tree_list (get_decl_list ($$), $2); }
@ -3668,17 +3699,21 @@ named_parm:
/* Here we expand typed_declspecs inline to avoid mis-parsing of /* Here we expand typed_declspecs inline to avoid mis-parsing of
TYPESPEC IDENTIFIER. */ TYPESPEC IDENTIFIER. */
typed_declspecs1 declarator typed_declspecs1 declarator
{ $$ = build_tree_list ($$, $2); } { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, $2); }
| typed_typespecs declarator | typed_typespecs declarator
{ $$ = build_tree_list ($$, $2); } { $$ = build_tree_list ($$, $2); }
| typespec declarator | typespec declarator
{ $$ = build_tree_list (get_decl_list ($$), $2); } { $$ = build_tree_list (get_decl_list ($$), $2); }
| typed_declspecs1 absdcl | typed_declspecs1 absdcl
{ $$ = build_tree_list ($$, $2); } { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, $2); }
| typed_declspecs1 %prec EMPTY | typed_declspecs1 %prec EMPTY
{ $$ = build_tree_list ($$, NULL_TREE); } { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, NULL_TREE); }
| declmods notype_declarator | declmods notype_declarator
{ $$ = build_tree_list ($$, $2); } { tree specs = strip_attrs ($1);
$$ = build_tree_list (specs, $2); }
; ;
full_parm: full_parm:

View File

@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA. */
#include "defaults.h" #include "defaults.h"
extern struct obstack permanent_obstack; extern struct obstack permanent_obstack;
extern tree grokdeclarator ();
extern int lineno; extern int lineno;
extern char *input_filename; extern char *input_filename;
@ -102,7 +101,7 @@ process_template_parm (list, next)
my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260); my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */ /* is a const-param */
parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE); PARM, 0, NULL_TREE, NULL_TREE);
/* A template parameter is not modifiable. */ /* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1; TREE_READONLY (parm) = 1;
if (IS_AGGR_TYPE (TREE_TYPE (parm))) if (IS_AGGR_TYPE (TREE_TYPE (parm)))
@ -239,7 +238,7 @@ end_template_decl (d1, d2, is_class, defn)
my_friendly_assert (code == BIT_NOT_EXPR my_friendly_assert (code == BIT_NOT_EXPR
|| code == OP_IDENTIFIER || code == OP_IDENTIFIER
|| code == SCOPE_REF, 264); || code == SCOPE_REF, 264);
d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE); d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);
decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2), decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
TREE_TYPE (d2)); TREE_TYPE (d2));
DECL_TEMPLATE_RESULT (decl) = d2; DECL_TEMPLATE_RESULT (decl) = d2;
@ -407,12 +406,6 @@ coerce_template_parms (parms, arglist, in_decl)
} }
if (is_type) if (is_type)
val = groktypename (arg); val = groktypename (arg);
else if (TREE_CODE (arg) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument", arg);
error ("because it is the address of an object with static linkage");
val = error_mark_node;
}
else else
{ {
tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0), tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
@ -431,14 +424,41 @@ coerce_template_parms (parms, arglist, in_decl)
arg); arg);
val = error_mark_node; val = error_mark_node;
} }
else if (TREE_CODE (val) == ADDR_EXPR) else if (POINTER_TYPE_P (TREE_TYPE (val))
&& ! integer_zerop (val)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != OFFSET_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != METHOD_TYPE)
{ {
tree a = TREE_OPERAND (val, 0); t = val;
if ((TREE_CODE (a) == VAR_DECL STRIP_NOPS (t);
|| TREE_CODE (a) == FUNCTION_DECL) if (TREE_CODE (t) == ADDR_EXPR)
&& ! DECL_PUBLIC (a))
{ {
cp_error ("address of non-extern `%E' cannot be used as template argument", a); tree a = TREE_OPERAND (t, 0);
STRIP_NOPS (a);
if (TREE_CODE (a) == STRING_CST)
{
cp_error ("string literal %E is not a valid template argument", a);
error ("because it is the address of an object with static linkage");
val = error_mark_node;
}
else if (TREE_CODE (a) != VAR_DECL
&& TREE_CODE (a) != FUNCTION_DECL)
goto bad;
else if (! DECL_PUBLIC (a))
{
cp_error ("address of non-extern `%E' cannot be used as template argument", a);
val = error_mark_node;
}
}
else
{
bad:
cp_error ("`%E' is not a valid template argument", t);
error ("it must be %s%s with external linkage",
TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE
? "a pointer to " : "",
TREE_CODE (TREE_TYPE (TREE_TYPE (val))) == FUNCTION_TYPE
? "a function" : "an object");
val = error_mark_node; val = error_mark_node;
} }
} }
@ -1714,11 +1734,9 @@ instantiate_template (tmpl, targ_ptr)
if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
&& DECL_STATIC_FUNCTION_P (fndecl)) && DECL_STATIC_FUNCTION_P (fndecl))
{ {
tree olddecl = DECL_RESULT (tmpl);
revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL); revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
/* Chop off the this pointer that grokclassfn so kindly added /* Chop off the this pointer that grokclassfn so kindly added
for us (it didn't know yet if the fn was static or not). */ for us (it didn't know yet if the fn was static or not). */
DECL_ARGUMENTS (olddecl) = TREE_CHAIN (DECL_ARGUMENTS (olddecl));
DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
} }
@ -1726,7 +1744,7 @@ instantiate_template (tmpl, targ_ptr)
/* If we have a preexisting version of this function, don't expand /* If we have a preexisting version of this function, don't expand
the template version, use the other instead. */ the template version, use the other instead. */
if (TREE_STATIC (fndecl)) if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
{ {
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl); SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0; p = (struct pending_inline *)0;
@ -1888,12 +1906,13 @@ overload_template_name (id, classlevel)
#endif #endif
} }
extern struct pending_input *to_be_restored;
/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */ /* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
void void
end_template_instantiation (name) end_template_instantiation (name)
tree name; tree name;
{ {
extern struct pending_input *to_be_restored;
tree t, decl; tree t, decl;
processing_template_defn--; processing_template_defn--;
@ -2502,7 +2521,8 @@ void
do_function_instantiation (declspecs, declarator, storage) do_function_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage; tree declspecs, declarator, storage;
{ {
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0); tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0,
NULL_TREE, NULL_TREE);
tree name; tree name;
tree fn; tree fn;
tree result = NULL_TREE; tree result = NULL_TREE;

View File

@ -428,6 +428,18 @@ get_vbase (parent, binfo, depth)
return rval; return rval;
} }
/* Convert EXPR to a virtual base class of type TYPE. We know that
EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that
the type of what expr points to has a virtual base of type TYPE. */
tree
convert_pointer_to_vbase (type, expr)
tree type;
tree expr;
{
tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))), NULL_PTR);
return convert_pointer_to_real (vb, expr);
}
/* This is the newer recursive depth first search routine. */ /* This is the newer recursive depth first search routine. */
#if 0 /* unused */ #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
@ -2117,16 +2129,17 @@ 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 virtuals = BINFO_VIRTUALS (binfo);
tree tmp = TREE_CHAIN (BINFO_VIRTUALS (binfo));
while (tmp) skip_rtti_stuff (&virtuals);
while (virtuals)
{ {
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp)); tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
tree base_fndecl = TREE_OPERAND (base_pfn, 0); tree base_fndecl = TREE_OPERAND (base_pfn, 0);
if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl)) if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals); abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
tmp = TREE_CHAIN (tmp); virtuals = TREE_CHAIN (virtuals);
} }
} }
return abstract_virtuals; return abstract_virtuals;
@ -2139,7 +2152,7 @@ tree
get_abstract_virtuals (type) get_abstract_virtuals (type)
tree type; tree type;
{ {
tree vbases, tmp; tree vbases;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type); tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
/* First get all from non-virtual bases. */ /* First get all from non-virtual bases. */
@ -2148,17 +2161,17 @@ get_abstract_virtuals (type)
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases)) for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases))
{ {
if (! BINFO_VIRTUALS (vbases)) tree virtuals = BINFO_VIRTUALS (vbases);
continue;
tmp = TREE_CHAIN (BINFO_VIRTUALS (vbases)); skip_rtti_stuff (&virtuals);
while (tmp)
while (virtuals)
{ {
tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (tmp)); tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
tree base_fndecl = TREE_OPERAND (base_pfn, 0); tree base_fndecl = TREE_OPERAND (base_pfn, 0);
if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl)) if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals); abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
tmp = TREE_CHAIN (tmp); virtuals = TREE_CHAIN (virtuals);
} }
} }
return nreverse (abstract_virtuals); return nreverse (abstract_virtuals);
@ -2293,7 +2306,7 @@ convert_pointer_to_single_level (to_type, expr)
last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0); last = get_binfo (to_type, TREE_TYPE (TREE_TYPE (expr)), 0);
BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived; BINFO_INHERITANCE_CHAIN (last) = binfo_of_derived;
BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE; BINFO_INHERITANCE_CHAIN (binfo_of_derived) = NULL_TREE;
return build_vbase_path (PLUS_EXPR, TYPE_POINTER_TO (to_type), expr, last, 1); return build_vbase_path (PLUS_EXPR, build_pointer_type (to_type), expr, last, 1);
} }
/* The main function which implements depth first search. /* The main function which implements depth first search.
@ -2517,7 +2530,7 @@ dfs_find_vbases (binfo)
tree binfo = binfo_member (vbase, vbase_types); tree binfo = binfo_member (vbase, vbase_types);
CLASSTYPE_SEARCH_SLOT (vbase) CLASSTYPE_SEARCH_SLOT (vbase)
= (char *) build (PLUS_EXPR, TYPE_POINTER_TO (vbase), = (char *) build (PLUS_EXPR, build_pointer_type (vbase),
vbase_decl_ptr, BINFO_OFFSET (binfo)); vbase_decl_ptr, BINFO_OFFSET (binfo));
} }
} }
@ -2549,7 +2562,7 @@ dfs_init_vbase_pointers (binfo)
this_vbase_ptr = vbase_decl_ptr_intermediate; this_vbase_ptr = vbase_decl_ptr_intermediate;
if (TYPE_POINTER_TO (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr))) if (build_pointer_type (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr)))
my_friendly_abort (125); my_friendly_abort (125);
while (fields && DECL_NAME (fields) while (fields && DECL_NAME (fields)
@ -2620,6 +2633,18 @@ virtual_context (fndecl, t, vbase)
tree path; tree path;
if (get_base_distance (DECL_CLASS_CONTEXT (fndecl), t, 0, &path) < 0) if (get_base_distance (DECL_CLASS_CONTEXT (fndecl), t, 0, &path) < 0)
{ {
/* DECL_CLASS_CONTEXT can be ambiguous in t. */
if (get_base_distance (DECL_CLASS_CONTEXT (fndecl), vbase, 0, &path) >= 0)
{
while (path)
{
/* Not sure if checking path == vbase is necessary here, but just in
case it is. */
if (TREE_VIA_VIRTUAL (path) || path == vbase)
return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
path = BINFO_INHERITANCE_CHAIN (path);
}
}
/* This shouldn't happen, I don't want errors! */ /* This shouldn't happen, I don't want errors! */
warning ("recoverable compiler error, fixups for virtual function"); warning ("recoverable compiler error, fixups for virtual function");
return vbase; return vbase;
@ -2666,10 +2691,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
*vbase_offsets = delta; *vbase_offsets = delta;
} }
/* Skip RTTI fake object. */ n = skip_rtti_stuff (&virtuals);
n = 1;
if (virtuals)
virtuals = TREE_CHAIN (virtuals);
while (virtuals) while (virtuals)
{ {
tree current_fndecl = TREE_VALUE (virtuals); tree current_fndecl = TREE_VALUE (virtuals);
@ -2831,10 +2854,9 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
else else
{ {
#if 1 #if 1
tree vb = get_vbase (TREE_TYPE (vbases), TYPE_BINFO (TREE_TYPE (vbase_decl)), addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
NULL_PTR);
addr = convert_pointer_to_real (vb, vbase_decl_ptr);
#else #else
/* This should should never work better than the above. (mrs) */
tree vbinfo = get_binfo (TREE_TYPE (vbases), tree vbinfo = get_binfo (TREE_TYPE (vbases),
TREE_TYPE (vbase_decl), TREE_TYPE (vbase_decl),
0); 0);
@ -3069,13 +3091,107 @@ note_debug_info_needed (type)
/* Subroutines of push_class_decls (). */ /* Subroutines of push_class_decls (). */
/* Add in a decl to the envelope. */
static void
envelope_add_decl (type, decl, values)
tree type, decl, *values;
{
tree context, *tmp;
tree name = DECL_NAME (decl);
int dont_add = 0;
/* virtual base names are always unique. */
if (VBASE_NAME_P (name))
*values = NULL_TREE;
/* Possible ambiguity. If its defining type(s)
is (are all) derived from us, no problem. */
else if (*values && TREE_CODE (*values) != TREE_LIST)
{
tree value = *values;
/* Only complain if we shadow something we can access. */
if (warn_shadow && TREE_CODE (decl) == FUNCTION_DECL
&& ((DECL_LANG_SPECIFIC (*values)
&& DECL_CLASS_CONTEXT (value) == current_class_type)
|| ! TREE_PRIVATE (value)))
/* Should figure out access control more accurately. */
{
cp_warning_at ("member `%#D' is shadowed", value);
cp_warning_at ("by member function `%#D'", decl);
warning ("in this context");
}
context = (TREE_CODE (value) == FUNCTION_DECL
&& DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
if (context == type)
{
if (TREE_CODE (value) == TYPE_DECL
&& DECL_ARTIFICIAL (value))
*values = NULL_TREE;
else
dont_add = 1;
}
else if (context && TYPE_DERIVES_FROM (context, type))
{
/* Don't add in *values to list */
*values = NULL_TREE;
}
else
*values = build_tree_list (NULL_TREE, value);
}
else
for (tmp = values; *tmp;)
{
tree value = TREE_VALUE (*tmp);
my_friendly_assert (TREE_CODE (value) != TREE_LIST, 999);
context = (TREE_CODE (value) == FUNCTION_DECL
&& DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
if (context && TYPE_DERIVES_FROM (context, type))
{
/* remove *tmp from list */
*tmp = TREE_CHAIN (*tmp);
}
else
tmp = &TREE_CHAIN (*tmp);
}
if (! dont_add)
{
/* Put the new contents in our envelope. */
if (TREE_CODE (decl) == FUNCTION_DECL)
{
*values = tree_cons (name, decl, *values);
TREE_NONLOCAL_FLAG (*values) = 1;
TREE_TYPE (*values) = unknown_type_node;
}
else
{
if (*values)
{
*values = tree_cons (NULL_TREE, decl, *values);
/* Mark this as a potentially ambiguous member. */
/* Leaving TREE_TYPE blank is intentional.
We cannot use `error_mark_node' (lookup_name)
or `unknown_type_node' (all member functions use this). */
TREE_NONLOCAL_FLAG (*values) = 1;
}
else
*values = decl;
}
}
}
/* Add the instance variables which this class contributed to the /* Add the instance variables which this class contributed to the
current class binding contour. When a redefinition occurs, current class binding contour. When a redefinition occurs, if the
if the redefinition is strictly within a single inheritance path, redefinition is strictly within a single inheritance path, we just
we just overwrite (in the case of a data field) or overwrite the old declaration with the new. If the fields are not
cons (in the case of a member function) the old declaration with within a single inheritance path, we must cons them.
the new. If the fields are not within a single inheritance path,
we must cons them in either case.
In order to know what decls are new (stemming from the current In order to know what decls are new (stemming from the current
invocation of push_class_decls) we enclose them in an "envelope", invocation of push_class_decls) we enclose them in an "envelope",
@ -3114,123 +3230,25 @@ dfs_pushdecls (binfo)
continue; continue;
} }
#if 0
if (TREE_CODE (fields) != TYPE_DECL)
{
DECL_PUBLIC (fields) = 0;
DECL_PROTECTED (fields) = 0;
DECL_PRIVATE (fields) = 0;
}
#endif
if (DECL_NAME (fields)) if (DECL_NAME (fields))
{ {
tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)); tree name = DECL_NAME (fields);
tree class_value = IDENTIFIER_CLASS_VALUE (name);
/* If the class value is an envelope of the kind described in /* If the class value is not an envelope of the kind described in
the comment above, we try to rule out possible ambiguities. the comment above, we create a new envelope. */
If we can't do that, keep a TREE_LIST with possibly ambiguous if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
decls in there. */ || TREE_PURPOSE (class_value) == NULL_TREE
if (class_value && TREE_CODE (class_value) == TREE_LIST || TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
&& TREE_PURPOSE (class_value) != NULL_TREE
&& (TREE_CODE (TREE_PURPOSE (class_value))
!= IDENTIFIER_NODE))
{
tree value = TREE_PURPOSE (class_value);
tree context;
/* Possible ambiguity. If its defining type(s)
is (are all) derived from us, no problem. */
if (TREE_CODE (value) != TREE_LIST)
{
context = (TREE_CODE (value) == FUNCTION_DECL
&& DECL_VIRTUAL_P (value))
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
if (context == type)
{
if (TREE_CODE (value) == TYPE_DECL
&& DECL_ARTIFICIAL (value))
value = fields;
/* else the old value wins */
}
else if (context && TYPE_DERIVES_FROM (context, type))
value = fields;
else
value = tree_cons (NULL_TREE, fields,
build_tree_list (NULL_TREE, value));
}
else
{
/* All children may derive from us, in which case
there is no problem. Otherwise, we have to
keep lists around of what the ambiguities might be. */
tree values;
int problem = 0;
for (values = value; values; values = TREE_CHAIN (values))
{
tree sub_values = TREE_VALUE (values);
if (TREE_CODE (sub_values) == TREE_LIST)
{
for (; sub_values; sub_values = TREE_CHAIN (sub_values))
{
register tree list_mbr = TREE_VALUE (sub_values);
context = (TREE_CODE (list_mbr) == FUNCTION_DECL
&& DECL_VIRTUAL_P (list_mbr))
? DECL_CLASS_CONTEXT (list_mbr)
: DECL_CONTEXT (list_mbr);
if (! TYPE_DERIVES_FROM (context, type))
{
value = tree_cons (NULL_TREE, TREE_VALUE (values), value);
problem = 1;
break;
}
}
}
else
{
context = (TREE_CODE (sub_values) == FUNCTION_DECL
&& DECL_VIRTUAL_P (sub_values))
? DECL_CLASS_CONTEXT (sub_values)
: DECL_CONTEXT (sub_values);
if (context && ! TYPE_DERIVES_FROM (context, type))
{
value = tree_cons (NULL_TREE, values, value);
problem = 1;
break;
}
}
}
if (! problem) value = fields;
}
/* Mark this as a potentially ambiguous member. */
if (TREE_CODE (value) == TREE_LIST)
{
/* Leaving TREE_TYPE blank is intentional.
We cannot use `error_mark_node' (lookup_name)
or `unknown_type_node' (all member functions use this). */
TREE_NONLOCAL_FLAG (value) = 1;
}
/* Put the new contents in our envelope. */
TREE_PURPOSE (class_value) = value;
}
else
{ {
/* See comment above for a description of envelopes. */ /* See comment above for a description of envelopes. */
tree envelope = tree_cons (fields, class_value, closed_envelopes = tree_cons (NULL_TREE, class_value,
closed_envelopes); closed_envelopes);
IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
closed_envelopes = envelope; class_value = IDENTIFIER_CLASS_VALUE (name);
IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) = envelope;
} }
envelope_add_decl (type, fields, &TREE_PURPOSE (class_value));
} }
} }
@ -3241,78 +3259,32 @@ dfs_pushdecls (binfo)
methods = &TREE_VEC_ELT (method_vec, 1); methods = &TREE_VEC_ELT (method_vec, 1);
end = TREE_VEC_END (method_vec); end = TREE_VEC_END (method_vec);
/* This does not work for multiple inheritance yet. */
while (methods != end) while (methods != end)
{ {
/* This will cause lookup_name to return a pointer /* This will cause lookup_name to return a pointer
to the tree_list of possible methods of this name. to the tree_list of possible methods of this name. */
If the order is a problem, we can nreverse them. */ tree name = DECL_NAME (*methods);
tree tmp; tree class_value = IDENTIFIER_CLASS_VALUE (name);
tree class_value = IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods));
if (class_value && TREE_CODE (class_value) == TREE_LIST /* If the class value is not an envelope of the kind described in
&& TREE_PURPOSE (class_value) != NULL_TREE the comment above, we create a new envelope. */
&& TREE_CODE (TREE_PURPOSE (class_value)) != IDENTIFIER_NODE) if (class_value == NULL_TREE || TREE_CODE (class_value) != TREE_LIST
|| TREE_PURPOSE (class_value) == NULL_TREE
|| TREE_CODE (TREE_PURPOSE (class_value)) == IDENTIFIER_NODE)
{ {
tree old = TREE_PURPOSE (class_value);
maybe_push_cache_obstack ();
if (TREE_CODE (old) == TREE_LIST)
tmp = tree_cons (DECL_NAME (*methods), *methods, old);
else
{
/* Only complain if we shadow something we can access. */
if (old
&& warn_shadow
&& ((DECL_LANG_SPECIFIC (old)
&& DECL_CLASS_CONTEXT (old) == current_class_type)
|| ! TREE_PRIVATE (old)))
/* Should figure out access control more accurately. */
{
cp_warning_at ("member `%#D' is shadowed", old);
cp_warning_at ("by member function `%#D'", *methods);
warning ("in this context");
}
tmp = build_tree_list (DECL_NAME (*methods), *methods);
}
pop_obstacks ();
TREE_TYPE (tmp) = unknown_type_node;
#if 0
TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
#endif
TREE_NONLOCAL_FLAG (tmp) = 1;
/* Put the new contents in our envelope. */
TREE_PURPOSE (class_value) = tmp;
}
else
{
maybe_push_cache_obstack ();
tmp = build_tree_list (DECL_NAME (*methods), *methods);
pop_obstacks ();
TREE_TYPE (tmp) = unknown_type_node;
#if 0
TREE_OVERLOADED (tmp) = DECL_OVERLOADED (*methods);
#endif
TREE_NONLOCAL_FLAG (tmp) = 1;
/* See comment above for a description of envelopes. */ /* See comment above for a description of envelopes. */
closed_envelopes = tree_cons (tmp, class_value, closed_envelopes = tree_cons (NULL_TREE, class_value,
closed_envelopes); closed_envelopes);
IDENTIFIER_CLASS_VALUE (DECL_NAME (*methods)) = closed_envelopes; IDENTIFIER_CLASS_VALUE (name) = closed_envelopes;
class_value = IDENTIFIER_CLASS_VALUE (name);
} }
#if 0
tmp = *methods; /* Here we try to rule out possible ambiguities.
while (tmp != 0) If we can't do that, keep a TREE_LIST with possibly ambiguous
{ decls in there. */
DECL_PUBLIC (tmp) = 0; maybe_push_cache_obstack ();
DECL_PROTECTED (tmp) = 0; envelope_add_decl (type, *methods, &TREE_PURPOSE (class_value));
DECL_PRIVATE (tmp) = 0; pop_obstacks ();
tmp = DECL_CHAIN (tmp);
}
#endif
methods++; methods++;
} }
@ -3370,41 +3342,6 @@ push_class_decls (type)
tree id; tree id;
struct obstack *ambient_obstack = current_obstack; struct obstack *ambient_obstack = current_obstack;
#if 0
tree tags = CLASSTYPE_TAGS (type);
while (tags)
{
tree code_type_node;
tree tag;
switch (TREE_CODE (TREE_VALUE (tags)))
{
case ENUMERAL_TYPE:
code_type_node = enum_type_node;
break;
case RECORD_TYPE:
code_type_node = record_type_node;
break;
case CLASS_TYPE:
code_type_node = class_type_node;
break;
case UNION_TYPE:
code_type_node = union_type_node;
break;
default:
my_friendly_abort (297);
}
tag = xref_tag (code_type_node, TREE_PURPOSE (tags),
TYPE_BINFO_BASETYPE (TREE_VALUE (tags), 0), 0);
#if 0 /* not yet, should get fixed properly later */
pushdecl (make_type_decl (TREE_PURPOSE (tags), TREE_VALUE (tags)));
#else
pushdecl (build_decl (TYPE_DECL, TREE_PURPOSE (tags), TREE_VALUE (tags)));
#endif
}
#endif
search_stack = push_search_level (search_stack, &search_obstack); search_stack = push_search_level (search_stack, &search_obstack);
id = TYPE_IDENTIFIER (type); id = TYPE_IDENTIFIER (type);

View File

@ -942,12 +942,12 @@ build_signature_method_call (basetype, instance, function, parms)
deflt_call = build_function_call (pfn, parms); deflt_call = build_function_call (pfn, parms);
} }
new_object_ptr = build (PLUS_EXPR, TYPE_POINTER_TO (basetype), new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
convert (ptrdiff_type_node, object_ptr), convert (ptrdiff_type_node, object_ptr),
convert (ptrdiff_type_node, delta)); convert (ptrdiff_type_node, delta));
parms = tree_cons (NULL_TREE, parms = tree_cons (NULL_TREE,
convert (TYPE_POINTER_TO (basetype), object_ptr), convert (build_pointer_type (basetype), object_ptr),
TREE_CHAIN (parms)); TREE_CHAIN (parms));
new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms)); new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
@ -956,7 +956,7 @@ build_signature_method_call (basetype, instance, function, parms)
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))); tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
build_type_variant (TYPE_POINTER_TO (basetype), build_type_variant (build_pointer_type (basetype),
TYPE_READONLY (old_this), TYPE_READONLY (old_this),
TYPE_VOLATILE (old_this)); TYPE_VOLATILE (old_this));

View File

@ -245,6 +245,13 @@ extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope; tree got_scope;
tree got_object; tree got_object;
int
peekyylex()
{
scan_tokens (0);
return nth_token (0)->yychar;
}
int int
yylex() yylex()
{ {

View File

@ -236,7 +236,7 @@ build_cplus_new (type, init, with_cleanup_p)
{ {
TREE_OPERAND (rval, 2) = error_mark_node; TREE_OPERAND (rval, 2) = error_mark_node;
rval = build (WITH_CLEANUP_EXPR, type, rval, 0, rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
build_delete (TYPE_POINTER_TO (type), build_delete (build_pointer_type (type),
build_unary_op (ADDR_EXPR, slot, 0), build_unary_op (ADDR_EXPR, slot, 0),
integer_two_node, integer_two_node,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0)); LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
@ -1318,7 +1318,7 @@ void
debug_binfo (elem) debug_binfo (elem)
tree elem; tree elem;
{ {
int i; unsigned HOST_WIDE_INT n;
tree virtuals; tree virtuals;
fprintf (stderr, "type \"%s\"; offset = %d\n", fprintf (stderr, "type \"%s\"; offset = %d\n",
@ -1332,20 +1332,17 @@ debug_binfo (elem)
fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n"); fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem); virtuals = BINFO_VIRTUALS (elem);
if (virtuals != 0)
{ n = skip_rtti_stuff (&virtuals);
/* skip the rtti type descriptor entry */
virtuals = TREE_CHAIN (virtuals);
}
i = 1;
while (virtuals) while (virtuals)
{ {
tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
fprintf (stderr, "%s [%d =? %d]\n", fprintf (stderr, "%s [%d =? %d]\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); n, TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
++n;
virtuals = TREE_CHAIN (virtuals); virtuals = TREE_CHAIN (virtuals);
i += 1;
} }
} }
@ -1567,11 +1564,11 @@ id_cmp (p1, p2)
return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2); return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
} }
/* Build the FUNCTION_TYPE or METHOD_TYPE which may raise exceptions /* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */ listed in RAISES. */
tree tree
build_exception_variant (ctype, type, raises) build_exception_variant (type, raises)
tree ctype, type; tree type;
tree raises; tree raises;
{ {
int i; int i;
@ -1903,3 +1900,96 @@ break_out_target_exprs (t)
{ {
return mapcar (t, bot_manip); return mapcar (t, bot_manip);
} }
tree
unsave_expr (expr)
tree expr;
{
tree t;
t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
return t;
}
/* Modify a tree in place so that all the evaluate only once things
are cleared out. Return the EXPR given. */
tree
unsave_expr_now (expr)
tree expr;
{
enum tree_code code;
register int i;
if (expr == NULL_TREE)
return expr;
code = TREE_CODE (expr);
switch (code)
{
case SAVE_EXPR:
SAVE_EXPR_RTL (expr) = NULL_RTX;
break;
case TARGET_EXPR:
sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
break;
case RTL_EXPR:
warning ("RTL_EXPR reused inside UNSAVE_EXPR");
RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
break;
case CALL_EXPR:
CALL_EXPR_RTL (expr) = NULL_RTX;
if (TREE_OPERAND (expr, 1)
&& TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
{
tree exp = TREE_OPERAND (expr, 1);
while (exp)
{
unsave_expr_now (TREE_VALUE (exp));
exp = TREE_CHAIN (exp);
}
}
break;
case WITH_CLEANUP_EXPR:
warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
RTL_EXPR_RTL (expr) = NULL_RTX;
break;
}
switch (TREE_CODE_CLASS (code))
{
case 'c': /* a constant */
case 't': /* a type node */
case 'x': /* something random, like an identifier or an ERROR_MARK. */
case 'd': /* A decl node */
case 'b': /* A block node */
return expr;
case 'e': /* an expression */
case 'r': /* a reference */
case 's': /* an expression with side effects */
case '<': /* a comparison expression */
case '2': /* a binary arithmetic expression */
case '1': /* a unary arithmetic expression */
for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
unsave_expr_now (TREE_OPERAND (expr, i));
return expr;
default:
my_friendly_abort (999);
}
}
/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
by itself. */
int
cp_expand_decl_cleanup (decl, cleanup)
tree decl, cleanup;
{
return expand_decl_cleanup (decl, unsave_expr (cleanup));
}

View File

@ -440,7 +440,7 @@ common_type (t1, t2)
{ {
rval = build_function_type (valtype, p2); rval = build_function_type (valtype, p2);
if ((raises = TYPE_RAISES_EXCEPTIONS (t2))) if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
rval = build_exception_variant (NULL_TREE, rval, raises); rval = build_exception_variant (rval, raises);
return build_type_attribute_variant (rval, attributes); return build_type_attribute_variant (rval, attributes);
} }
raises = TYPE_RAISES_EXCEPTIONS (t1); raises = TYPE_RAISES_EXCEPTIONS (t1);
@ -448,12 +448,12 @@ common_type (t1, t2)
{ {
rval = build_function_type (valtype, p1); rval = build_function_type (valtype, p1);
if (raises) if (raises)
rval = build_exception_variant (NULL_TREE, rval, raises); rval = build_exception_variant (rval, raises);
return build_type_attribute_variant (rval, attributes); return build_type_attribute_variant (rval, attributes);
} }
rval = build_function_type (valtype, commonparms (p1, p2)); rval = build_function_type (valtype, commonparms (p1, p2));
rval = build_exception_variant (NULL_TREE, rval, raises); rval = build_exception_variant (rval, raises);
return build_type_attribute_variant (rval, attributes); return build_type_attribute_variant (rval, attributes);
} }
@ -498,7 +498,7 @@ common_type (t1, t2)
t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2))); t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2)));
t3 = common_type (t1, t2); t3 = common_type (t1, t2);
t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3)); t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3));
t1 = build_exception_variant (basetype, t3, raises); t1 = build_exception_variant (t3, raises);
} }
else else
compiler_error ("common_type called with uncommon method types"); compiler_error ("common_type called with uncommon method types");
@ -672,9 +672,9 @@ comptypes (type1, type2, strict)
return 0; return 0;
case OFFSET_TYPE: case OFFSET_TYPE:
val = (comptypes (TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t1)), val = (comptypes (build_pointer_type (TYPE_OFFSET_BASETYPE (t1)),
TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t2)), strict) build_pointer_type (TYPE_OFFSET_BASETYPE (t2)), strict)
&& comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)); && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict));
break; break;
case METHOD_TYPE: case METHOD_TYPE:
@ -686,11 +686,9 @@ comptypes (type1, type2, strict)
to something expecting a derived member (or member function), to something expecting a derived member (or member function),
but not vice-versa! */ but not vice-versa! */
val = (comptypes (TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t2)), val = (comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)
TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict) && compparms (TYPE_ARG_TYPES (t1),
&& comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict) TYPE_ARG_TYPES (t2), strict));
&& compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)),
TREE_CHAIN (TYPE_ARG_TYPES (t2)), strict));
break; break;
case POINTER_TYPE: case POINTER_TYPE:
@ -742,7 +740,7 @@ comptypes (type1, type2, strict)
break; break;
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
return 1; return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
case UNINSTANTIATED_P_TYPE: case UNINSTANTIATED_P_TYPE:
if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2)) if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
@ -813,7 +811,30 @@ comp_target_types (ttl, ttr, nptrs)
return comp_ptr_ttypes (ttl, ttr); return comp_ptr_ttypes (ttl, ttr);
} }
return comp_target_types (ttl, ttr, nptrs - 1); /* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
if (TREE_CODE (ttl) == FUNCTION_TYPE || TREE_CODE (ttl) == METHOD_TYPE)
return comp_target_types (ttl, ttr, nptrs - 1);
/* Make sure that the cv-quals change only in the same direction as
the target type. */
{
int t;
int c = TYPE_READONLY (ttl) - TYPE_READONLY (ttr);
int v = TYPE_VOLATILE (ttl) - TYPE_VOLATILE (ttr);
if ((c > 0 && v < 0) || (c < 0 && v > 0))
return 0;
if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr))
return (c + v < 0) ? -1 : 1;
t = comp_target_types (ttl, ttr, nptrs - 1);
if ((t == 1 && c + v >= 0) || (t == -1 && c + v <= 0))
return t;
return 0;
}
} }
if (TREE_CODE (ttr) == REFERENCE_TYPE) if (TREE_CODE (ttr) == REFERENCE_TYPE)
@ -852,9 +873,9 @@ comp_target_types (ttl, ttr, nptrs)
{ {
if (nptrs < 0) if (nptrs < 0)
return 0; return 0;
if (comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0)) if (comptypes (build_pointer_type (ttl), build_pointer_type (ttr), 0))
return 1; return 1;
if (comptypes (TYPE_POINTER_TO (ttr), TYPE_POINTER_TO (ttl), 0)) if (comptypes (build_pointer_type (ttr), build_pointer_type (ttl), 0))
return -1; return -1;
return 0; return 0;
} }
@ -1408,7 +1429,7 @@ decay_conversion (exp)
inner); inner);
TREE_REFERENCE_EXPR (inner) = 1; TREE_REFERENCE_EXPR (inner) = 1;
} }
return convert (TYPE_POINTER_TO (TREE_TYPE (type)), inner); return convert (build_pointer_type (TREE_TYPE (type)), inner);
} }
if (TREE_CODE (exp) == COMPOUND_EXPR) if (TREE_CODE (exp) == COMPOUND_EXPR)
@ -1845,11 +1866,15 @@ build_indirect_ref (ptr, errorstring)
if (ptr == current_class_decl) if (ptr == current_class_decl)
return C_C_D; return C_C_D;
ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1); if (IS_AGGR_TYPE (type))
if (ptr)
{ {
pointer = ptr; ptr = build_expr_type_conversion (WANT_POINTER, pointer, 1);
type = TREE_TYPE (pointer);
if (ptr)
{
pointer = ptr;
type = TREE_TYPE (pointer);
}
} }
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE) if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
@ -2144,7 +2169,7 @@ build_x_function_call (function, params, decl)
return error_mark_node; return error_mark_node;
} }
/* Yow: call from a static member function. */ /* Yow: call from a static member function. */
decl = build1 (NOP_EXPR, TYPE_POINTER_TO (current_class_type), decl = build1 (NOP_EXPR, build_pointer_type (current_class_type),
error_mark_node); error_mark_node);
decl = build_indirect_ref (decl, NULL_PTR); decl = build_indirect_ref (decl, NULL_PTR);
} }
@ -2223,14 +2248,14 @@ build_x_function_call (function, params, decl)
/* Explicitly named method? */ /* Explicitly named method? */
if (TREE_CODE (function) == FUNCTION_DECL) if (TREE_CODE (function) == FUNCTION_DECL)
ctypeptr = TYPE_POINTER_TO (DECL_CLASS_CONTEXT (function)); ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function));
/* Expression with ptr-to-method type? It could either be a plain /* Expression with ptr-to-method type? It could either be a plain
usage, or it might be a case where the ptr-to-method is being usage, or it might be a case where the ptr-to-method is being
passed in as an argument. */ passed in as an argument. */
else if (TYPE_PTRMEMFUNC_P (fntype)) else if (TYPE_PTRMEMFUNC_P (fntype))
{ {
tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (fntype))); tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
ctypeptr = TYPE_POINTER_TO (rec); ctypeptr = build_pointer_type (rec);
} }
/* Unexpected node type? */ /* Unexpected node type? */
else else
@ -2273,25 +2298,27 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{ {
tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)); tree fntype, index, e1, delta, delta2, e2, e3, aref, vtbl;
tree index = save_expr (build_component_ref (function,
index_identifier,
0, 0));
tree e1 = build (GT_EXPR, boolean_type_node, index,
convert (delta_type_node, integer_zero_node));
tree delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, 0, 0));
tree delta2 = DELTA2_FROM_PTRMEMFUNC (function);
tree e2;
tree e3;
tree aref, vtbl;
tree instance; tree instance;
tree instance_ptr = *instance_ptrptr; tree instance_ptr = *instance_ptrptr;
if (TREE_SIDE_EFFECTS (instance_ptr)) if (TREE_SIDE_EFFECTS (instance_ptr))
instance_ptr = save_expr (instance_ptr); instance_ptr = save_expr (instance_ptr);
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
index = save_expr (build_component_ref (function,
index_identifier,
0, 0));
e1 = build (GT_EXPR, boolean_type_node, index,
convert (delta_type_node, integer_zero_node));
delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, 0, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
/* convert down to the right base, before using the instance. */ /* convert down to the right base, before using the instance. */
instance instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)), = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
@ -4409,11 +4436,11 @@ unary_complex_lvalue (code, arg)
targ = arg; targ = arg;
else else
targ = build_cplus_new (TREE_TYPE (arg), arg, 1); targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
return build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)), targ); return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
} }
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF) if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
return build (SAVE_EXPR, TYPE_POINTER_TO (TREE_TYPE (arg)), return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
TREE_OPERAND (targ, 0), current_function_decl, NULL); TREE_OPERAND (targ, 0), current_function_decl, NULL);
/* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case /* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case
@ -4516,6 +4543,8 @@ mark_addressable (exp)
TREE_ADDRESSABLE (x) = 1; TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1; TREE_USED (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
if (asm_out_file)
assemble_external (x);
return 1; return 1;
default: default:
@ -4747,7 +4776,7 @@ build_conditional_expr (ifexp, op1, op2)
cp_pedwarn ("`%T' and `%T' converted to `%T *' in conditional expression", cp_pedwarn ("`%T' and `%T' converted to `%T *' in conditional expression",
type1, type2, result_type); type1, type2, result_type);
result_type = TYPE_POINTER_TO (result_type); result_type = build_pointer_type (result_type);
} }
} }
else else
@ -5016,6 +5045,9 @@ tree build_const_cast (type, expr)
tree intype = TREE_TYPE (expr); tree intype = TREE_TYPE (expr);
tree t1, t2; tree t1, t2;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
if (TYPE_PTRMEMFUNC_P (type)) if (TYPE_PTRMEMFUNC_P (type))
type = TYPE_PTRMEMFUNC_FN_TYPE (type); type = TYPE_PTRMEMFUNC_FN_TYPE (type);
if (TYPE_PTRMEMFUNC_P (intype)) if (TYPE_PTRMEMFUNC_P (intype))
@ -6353,6 +6385,23 @@ build_ptrmemfunc (type, pfn, force)
npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn)); npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
if (integer_zerop (nindex)) if (integer_zerop (nindex))
pfn = integer_zero_node; pfn = integer_zero_node;
else if (integer_zerop (fold (size_binop (PLUS_EXPR, nindex, integer_one_node))))
{
tree e3;
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
pfn = build1 (NOP_EXPR, type, npfn);
TREE_CONSTANT (pfn) = TREE_CONSTANT (npfn);
u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
tree_cons (NULL_TREE, nindex,
tree_cons (NULL_TREE, u, NULL_TREE))));
e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
return e3;
}
else else
{ {
sorry ("value casting of variable nonnull pointer to member functions not supported"); sorry ("value casting of variable nonnull pointer to member functions not supported");
@ -6623,7 +6672,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (ctt < 0) if (ctt < 0)
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl); rhstype, type);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node && TYPE_MAIN_VARIANT (ttr) == void_type_node
@ -7388,6 +7437,11 @@ c_expand_return (retval)
{ {
store_expr (result, original_result_rtx, 0); store_expr (result, original_result_rtx, 0);
expand_cleanups_to (NULL_TREE); expand_cleanups_to (NULL_TREE);
use_variable (DECL_RTL (result));
if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
expand_goto (ctor_label);
else
expand_null_return ();
} }
else if (retval && retval != result) else if (retval && retval != result)
{ {
@ -7408,12 +7462,6 @@ c_expand_return (retval)
} }
else else
expand_return (result); expand_return (result);
use_variable (DECL_RTL (result));
if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
expand_goto (ctor_label);
else
expand_null_return ();
} }
else else
{ {
@ -7530,15 +7578,20 @@ comp_ptr_ttypes_real (to, from, constp)
if (TREE_CODE (to) != TREE_CODE (from)) if (TREE_CODE (to) != TREE_CODE (from))
return 0; return 0;
if (TYPE_READONLY (from) > TYPE_READONLY (to) /* Const and volatile mean something different for function types,
|| TYPE_VOLATILE (from) > TYPE_VOLATILE (to)) so the usual checks are not appropriate. */
return 0; if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
if (TYPE_READONLY (from) > TYPE_READONLY (to)
|| TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
return 0;
if (! constp if (! constp
&& (TYPE_READONLY (to) > TYPE_READONLY (from) && (TYPE_READONLY (to) > TYPE_READONLY (from)
|| TYPE_VOLATILE (to) > TYPE_READONLY (from))) || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
return 0; return 0;
constp &= TYPE_READONLY (to); constp &= TYPE_READONLY (to);
}
if (TREE_CODE (to) != POINTER_TYPE) if (TREE_CODE (to) != POINTER_TYPE)
return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1); return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);

View File

@ -884,9 +884,15 @@ digest_init (type, init, tail)
if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE) if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)
{ {
if (raw_constructor) if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type))
{
cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
type, init);
return error_mark_node;
}
else if (raw_constructor)
return process_init_constructor (type, init, (tree *)0); return process_init_constructor (type, init, (tree *)0);
else if (TYPE_NEEDS_CONSTRUCTING (type)) else if (TYPE_NON_AGGREGATE_CLASS (type))
{ {
/* This can only be reached when caller is initializing /* This can only be reached when caller is initializing
ARRAY_TYPE. In that case, we don't want to convert ARRAY_TYPE. In that case, we don't want to convert