Commit e1cd6e56 by Mike Stump

53rd Cygnus<->FSF merge

From-SVN: r8794
parent 43238b97
......@@ -47,6 +47,7 @@ extern tree unary_complex_lvalue ();
static struct harshness_code convert_harshness ();
#define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG))
#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG))
#define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG))
#define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG))
#define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG))
......@@ -117,6 +118,7 @@ convert_harshness (type, parmtype, parm)
struct harshness_code h;
register enum tree_code codel;
register enum tree_code coder;
int lvalue;
h.code = 0;
h.distance = 0;
......@@ -136,7 +138,12 @@ convert_harshness (type, parmtype, parm)
if (parm)
parm = convert_from_reference (parm);
parmtype = TREE_TYPE (parmtype);
lvalue = 1;
}
else if (parm)
lvalue = lvalue_p (parm);
else
lvalue = 0;
codel = TREE_CODE (type);
coder = TREE_CODE (parmtype);
......@@ -300,6 +307,14 @@ convert_harshness (type, parmtype, parm)
if (coder == VOID_TYPE)
return EVIL_RETURN (h);
if (codel == BOOLEAN_TYPE)
{
if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE
|| coder == POINTER_TYPE || coder == OFFSET_TYPE)
return STD_RETURN (h);
return EVIL_RETURN (h);
}
if (INTEGRAL_CODE_P (codel))
{
/* Control equivalence of ints an enums. */
......@@ -375,11 +390,10 @@ convert_harshness (type, parmtype, parm)
register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
int penalty = 4 * (ttl != ttr);
/* Anything converts to void *. void * converts to anything.
Since these may be `const void *' (etc.) use VOID_TYPE
instead of void_type_node. Otherwise, the targets must be the same,
except that we do allow (at some cost) conversion between signed and
unsigned pointer types. */
/* Anything converts to void *. Since this may be `const void *'
(etc.) use VOID_TYPE instead of void_type_node. Otherwise, the
targets must be the same, except that we do allow (at some cost)
conversion between signed and unsigned pointer types. */
if ((TREE_CODE (ttl) == METHOD_TYPE
|| TREE_CODE (ttl) == FUNCTION_TYPE)
......@@ -396,7 +410,8 @@ convert_harshness (type, parmtype, parm)
}
#if 1
if (TREE_CODE (ttl) != VOID_TYPE && TREE_CODE (ttr) != VOID_TYPE)
if (TREE_CODE (ttl) != VOID_TYPE
&& (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
{
if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
{
......@@ -404,7 +419,7 @@ convert_harshness (type, parmtype, parm)
ttr = unsigned_type (ttr);
penalty = 10;
}
if (! comp_target_types (ttl, ttr, 0))
if (comp_target_types (ttl, ttr, 0) <= 0)
return EVIL_RETURN (h);
}
#else
......@@ -414,7 +429,7 @@ convert_harshness (type, parmtype, parm)
&& (ttl = unsigned_type (ttl),
ttr = unsigned_type (ttr),
penalty = 10, 0))
|| (comp_target_types (ttl, ttr, 0))))
|| (comp_target_types (ttl, ttr, 0) > 0)))
return EVIL_RETURN (h);
#endif
......@@ -503,14 +518,21 @@ convert_harshness (type, parmtype, parm)
ttl = TREE_TYPE (type);
/* When passing a non-const argument into a const reference (or vice
versa), dig it a little, so a non-const reference is preferred
over this one. (mrs) */
if (TYPE_READONLY (ttl) != constp
|| TYPE_VOLATILE (ttl) != volatilep)
penalty = 2;
else
penalty = 0;
/* 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);
......@@ -520,98 +542,17 @@ convert_harshness (type, parmtype, parm)
form = TREE_CODE (intype);
}
if (ttl == intype && penalty == 0)
return ZERO_RETURN (h);
else
penalty = 2;
ttr = intype;
/* If the initializer is not an lvalue, then it does not
matter if we make life easier for the programmer
by creating a temporary variable with which to
hold the result. */
if (parm && (INTEGRAL_CODE_P (coder)
|| coder == REAL_TYPE)
&& ! lvalue_p (parm))
{
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty > 2 || h.code != 0)
h.code |= STD_CODE;
else
h.code |= TRIVIAL_CODE;
h.distance = 0;
return h;
}
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
{
ttl = unsigned_type (ttl);
ttr = intype = unsigned_type (intype);
penalty += 2;
}
if (ttl == ttr)
{
if (penalty > 2)
{
h.code = STD_CODE;
h.distance = 0;
}
else
{
h.code = TRIVIAL_CODE;
/* We set this here so that build_overload_call_real will be
able to see the penalty we found, rather than just looking
at a TRIVIAL_CODE with no other information. */
h.int_penalty = penalty;
}
return h;
}
/* Maybe handle conversion to base here? */
/* Pointers to voids always convert for pointers. But
make them less natural than more specific matches. */
if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
if (TREE_TYPE (ttl) == void_type_node
|| TREE_TYPE (ttr) == void_type_node)
{
h.code = STD_CODE;
h.distance = 0;
return h;
}
}
/* Here it does matter. If this conversion is from derived to base,
allow it. Otherwise, types must be compatible in the strong sense. */
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
int b_or_d = get_base_distance (ttl, ttr, 0, 0);
if (b_or_d < 0)
{
b_or_d = get_base_distance (ttr, ttl, 0, 0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
}
/* Say that this conversion is relatively painless.
If it turns out that there is a user-defined X(X&)
constructor, then that will be invoked, but that's
preferable to dealing with other user-defined conversions
that may produce surprising results. */
else
h.distance = b_or_d;
h.code = STD_CODE;
return h;
}
if (comp_target_types (ttl, intype, 1))
{
if (penalty)
h.code = STD_CODE;
h.distance = 0;
return h;
h.code = QUAL_CODE;
h.int_penalty = penalty;
}
return h;
}
if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{
......@@ -631,6 +572,15 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h);
}
int
can_convert (to, from)
tree to, from;
{
struct harshness_code h;
h = convert_harshness (to, from, NULL_TREE);
return h.code < USER_CODE;
}
#ifdef DEBUG_MATCHING
static char *
print_harshness (h)
......@@ -2134,6 +2084,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype_path = TREE_VALUE (basetype_path);
basetype = BINFO_TYPE (basetype_path);
#if 0
/* Cast the instance variable if necessary. */
if (basetype != TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
......@@ -2152,6 +2103,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
the access-control rewrite will make this change more cleanly. */
if (TREE_VALUE (parms) == error_mark_node)
return error_mark_node;
#endif
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
function = DECL_CHAIN (function);
......@@ -2208,19 +2160,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& (cp->h.code & USER_CODE))
continue;
/* If we used default parameters, we must
check to see whether anyone else might
use them also, and report a possible
ambiguity. */
if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)
&& cp->harshness[len].distance == 0
&& cp->h.code < best)
{
if (! DECL_STATIC_FUNCTION_P (function))
TREE_VALUE (parms) = cp->arg;
if (best == 1)
goto found_and_maybe_warn;
}
cp++;
}
}
......
......@@ -114,6 +114,14 @@ extern int pedantic;
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type)
/* Record in each node resulting from a binary operator
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(exp, code) \
(TREE_COMPLEXITY (exp) = (int)(code))
/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
next exception handler. */
......@@ -271,7 +279,8 @@ extern int interface_only, interface_unknown;
extern int flag_elide_constructors;
/* Nonzero means handle things in ANSI, instead of GNU fashion. */
/* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
extern int flag_ansi;
......@@ -369,9 +378,6 @@ enum languages { lang_c, lang_cplusplus };
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
#define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
enum conversion_type { ptr_conv, constptr_conv, int_conv,
real_conv, last_conversion_type };
/* Statistics show that while the GNU C++ compiler may generate
thousands of different types during a compilation run, it
generates relatively few (tens) of classtypes. Because of this,
......@@ -492,7 +498,6 @@ struct lang_type
union tree_node *friend_classes;
char *mi_matrix;
union tree_node *conversions[last_conversion_type];
union tree_node *rtti;
......@@ -657,6 +662,12 @@ struct lang_type
/* List of lists of member functions defined in this class. */
#define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE)
/* The first type conversion operator in the class (the others can be
searched with TREE_CHAIN), or the first non-constructor function if
there are no type conversion operators. */
#define CLASSTYPE_FIRST_CONVERSION(NODE) \
TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
/* Pointer from any member function to the head of the list of
member functions of the type that member function belongs to. */
#define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
......@@ -807,12 +818,6 @@ struct lang_type
a type is derived from another or not. */
#define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
/* If there is exactly one conversion to a non-void, non-const pointer type,
remember that here. If there are more than one, put
`error_mark_node' here. If there are none, this holds NULL_TREE. */
#define CLASSTYPE_CONVERSION(NODE,KIND) \
(TYPE_LANG_SPECIFIC(NODE)->conversions[(int) KIND])
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
/* whether this can be globalized. */
......@@ -2243,6 +2248,7 @@ extern void print_search_statistics PROTO((void));
extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
extern tree lookup_conversions PROTO((tree));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));
......
......@@ -64,6 +64,10 @@ static int global_temp_name_counter;
/* Flag used when debugging spew.c */
extern int spew_debug;
/* Functions called along with real static constructors and destructors. */
tree static_ctors, static_dtors;
/* C (and C++) language-specific option variables. */
......@@ -80,6 +84,10 @@ int flag_short_double;
int flag_no_asm;
/* Nonzero means don't recognize any extension keywords. */
int flag_no_gnu_keywords;
/* Nonzero means don't recognize the non-ANSI builtin functions. */
int flag_no_builtin;
......@@ -99,11 +107,12 @@ int flag_signed_bitfields = 1;
/* Nonzero means handle `#ident' directives. 0 means ignore them. */
int flag_no_ident = 0;
int flag_no_ident;
/* Nonzero means disable GNU extensions. */
/* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
int flag_ansi = 0;
int flag_ansi;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
......@@ -113,13 +122,13 @@ int flag_implement_inlines = 1;
/* Nonzero means do emit exported implementations of templates, instead of
multiple static copies in each file that needs a definition. */
int flag_external_templates = 0;
int flag_external_templates;
/* Nonzero means that the decision to emit or not emit the implementation of a
template depends on where the template is instantiated, rather than where
it is defined. */
int flag_alt_external_templates = 0;
int flag_alt_external_templates;
/* Nonzero means that implicit instantiations will be emitted if needed. */
......@@ -139,7 +148,7 @@ int warn_ctor_dtor_privacy = 1;
Also causes output of vtables to be controlled by whether
we seen the class's first non-inline virtual function. */
int flag_vtable_thunks = 0;
int flag_vtable_thunks;
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
......@@ -198,7 +207,7 @@ int warn_conversion;
/* Warn if adding () is suggested. */
int warn_parentheses = 1;
int warn_parentheses;
/* Non-zero means warn in function declared in derived class has the
same name as a virtual in the base class, but fails to match the
......@@ -229,6 +238,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
/* Nonzero for -fno-strict-prototype switch: do not consider empty
argument prototype to mean function takes no arguments. */
int flag_strict_prototype = 2;
int strict_prototype = 1;
int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1;
......@@ -303,7 +313,7 @@ int flag_gc;
/* Controls whether compiler generates 'type descriptor' that give
run-time type information. */
int flag_rtti = 0;
int flag_rtti;
/* Nonzero if we wish to output cross-referencing information
for the GNU class browser. */
......@@ -319,21 +329,28 @@ extern int flag_gnu_xref;
In general, it is `reasonable' to assume that for many programs,
and better code can be generated in that case. */
int flag_assume_nonnull_objects;
int flag_assume_nonnull_objects = 1;
/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
objects. */
int flag_huge_objects;
/* Nonzero if we want to conserve space in the .o files. We do this
by putting uninitialized data and runtime initialized data into
.common instead of .data at the expense of not flaging multiple
definitions. */
int flag_conserve_space;
/* Nonzero if we want to obey access control semantics. */
int flag_access_control = 1;
/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */
int flag_operator_names;
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
......@@ -355,7 +372,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"labels-ok", &flag_labels_ok, 1},
{"stats", &flag_detailed_statistics, 1},
{"this-is-variable", &flag_this_is_variable, 1},
{"strict-prototype", &strict_prototypes_lang_cplusplus, 1},
{"strict-prototype", &flag_strict_prototype, 1},
{"all-virtual", &flag_all_virtual, 1},
{"memoize-lookups", &flag_memoize_lookups, 1},
{"elide-constructors", &flag_elide_constructors, 1},
......@@ -376,7 +393,9 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
{"vtable-thunks", &flag_vtable_thunks, 1},
{"short-temps", &flag_short_temps, 1},
{"access-control", &flag_access_control, 1},
{"nonansi-builtins", &flag_no_nonansi_builtin, 0}
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1}
};
/* Decode the string P as a language-specific option.
......@@ -552,6 +571,7 @@ lang_decode_option (p)
warn_ctor_dtor_privacy = setting;
warn_switch = setting;
warn_format = setting;
warn_parentheses = setting;
warn_missing_braces = setting;
warn_extern_inline = setting;
warn_nonvdtor = setting;
......@@ -569,8 +589,8 @@ lang_decode_option (p)
else return 0;
}
else if (!strcmp (p, "-ansi"))
flag_no_asm = 1, dollars_in_ident = 0, flag_no_nonansi_builtin = 1,
flag_ansi = 1;
dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1,
flag_no_gnu_keywords = 1, flag_operator_names = 1;
#ifdef SPEW_DEBUG
/* Undocumented, only ever used when you're invoking cc1plus by hand, since
it's probably safe to assume no sane person would ever want to use this
......@@ -2674,10 +2694,10 @@ finish_file ()
we'll need here. */
push_lang_context (lang_name_c);
/* Set up the name of the file-level functions we may need. */
/* Use a global object (which is already required to be unique over
the program) rather than the file name (which imposes extra
constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */
if (static_ctors || vars || have_exception_handlers)
needs_messing_up = 1;
if (static_dtors)
needs_cleaning = 1;
/* See if we really need the hassle. */
while (vars && needs_cleaning == 0)
......@@ -2740,6 +2760,10 @@ finish_file ()
vars = TREE_CHAIN (vars);
}
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
NULL_TREE));
expand_end_bindings (getdecls(), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
......@@ -2753,7 +2777,7 @@ finish_file ()
mess_up:
/* Must do this while we think we are at the top level. */
vars = nreverse (static_aggregates);
if (vars != NULL_TREE || have_exception_handlers)
if (needs_messing_up)
{
fnname = get_file_function_name ('I');
start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
......@@ -2797,6 +2821,7 @@ finish_file ()
the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
#if 0
if (init)
{
if (TREE_CODE (init) == VAR_DECL)
......@@ -2815,7 +2840,6 @@ finish_file ()
&& CONSTRUCTOR_ELTS (init) == NULL_TREE)
init = NULL_TREE;
}
#if 0
else if (TREE_TYPE (decl) == TREE_TYPE (init))
{
#if 1
......@@ -2828,9 +2852,9 @@ finish_file ()
init = DECL_INITIAL (init);
#endif /* 1 */
}
#endif /* 0 */
}
}
#endif /* 0 */
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0);
......@@ -2865,6 +2889,10 @@ finish_file ()
expand_cleanups_to (old_cleanups);
}
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
NULL_TREE));
expand_end_bindings (getdecls(), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
......
......@@ -43,7 +43,12 @@ tree builtin_return_address_fndecl;
#define TRY_NEW_EH
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
#ifdef _IBMR2
#ifndef __rs6000
#define __rs6000
#endif
#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm)
#define TRY_NEW_EH
#endif
#endif
......@@ -123,6 +128,16 @@ expand_throw (exp)
#else
/* Make 'label' the first numbered label of the current function */
void
make_first_label(label)
rtx label;
{
if (CODE_LABEL_NUMBER(label) < get_first_label_num())
set_new_first_and_last_label_num (CODE_LABEL_NUMBER(label),
max_label_num());
}
static int
doing_eh (do_warn)
int do_warn;
......@@ -236,9 +251,16 @@ void
exception_section ()
{
#ifdef ASM_OUTPUT_SECTION_NAME
named_section (".gcc_except_table");
named_section (NULL_TREE, ".gcc_except_table");
#else
if (flag_pic)
data_section ();
else
#if defined(__rs6000)
data_section ();
#else
text_section ();
readonly_data_section ();
#endif
#endif
}
......@@ -576,6 +598,10 @@ push_eh_entry (stack)
entry->exception_handler_label = gen_label_rtx ();
pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry->start_label) = 1;
LABEL_PRESERVE_P (entry->end_label) = 1;
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
entry->finalization = NULL_TREE;
node->entry = entry;
......@@ -794,9 +820,9 @@ init_exception_processing ()
saved_throw_value = gen_rtx (REG, Pmode, 5);
#endif
#ifdef __rs6000
saved_pc = gen_rtx (REG, Pmode, 12);
saved_throw_type = gen_rtx (REG, Pmode, 13);
saved_throw_value = gen_rtx (REG, Pmode, 14);
saved_pc = gen_rtx (REG, Pmode, 13);
saved_throw_type = gen_rtx (REG, Pmode, 14);
saved_throw_value = gen_rtx (REG, Pmode, 15);
#endif
#ifdef __hppa
saved_pc = gen_rtx (REG, Pmode, 5);
......@@ -813,6 +839,11 @@ init_exception_processing ()
saved_throw_type = gen_rtx (REG, Pmode, 17);
saved_throw_value = gen_rtx (REG, Pmode, 18);
#endif
#ifdef __arm
saved_pc = gen_rtx (REG, Pmode, 7);
saved_throw_type = gen_rtx (REG, Pmode, 8);
saved_throw_value = gen_rtx (REG, Pmode, 9);
#endif
new_eh_queue (&ehqueue);
new_eh_queue (&eh_table_output_queue);
new_eh_stack (&ehstack);
......@@ -958,7 +989,13 @@ expand_start_all_catch ()
entry->end_label = gen_label_rtx ();
entry->exception_handler_label = gen_label_rtx ();
entry->finalization = TerminateFunctionCall;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry->start_label) = 1;
LABEL_PRESERVE_P (entry->end_label) = 1;
LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
emit_label (entry->end_label);
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
......@@ -969,6 +1006,7 @@ expand_start_all_catch ()
/* Will this help us not stomp on it? */
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
make_first_label(throw_label);
emit_jump (throw_label);
emit_label (entry->exception_handler_label);
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
......@@ -992,6 +1030,7 @@ expand_end_all_catch ()
emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
Pmode,
top_label_entry (&caught_return_label_stack)));
make_first_label(throw_label);
emit_jump (throw_label);
/* Find the start of the catch block. */
......@@ -1052,7 +1091,13 @@ expand_leftover_cleanups ()
entry.end_label = label;
entry.exception_handler_label = gen_label_rtx ();
entry.finalization = TerminateFunctionCall;
assemble_external (TREE_OPERAND (Terminate, 0));
pop_rtl_from_perm ();
LABEL_PRESERVE_P (entry.start_label) = 1;
LABEL_PRESERVE_P (entry.end_label) = 1;
LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
emit_label (label);
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
......@@ -1063,6 +1108,7 @@ expand_leftover_cleanups ()
/* Will this help us not stomp on it? */
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
make_first_label(throw_label);
emit_jump (throw_label);
emit_label (entry.exception_handler_label);
expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
......@@ -1143,6 +1189,7 @@ expand_start_catch_block (declspecs, declarator)
NULL_TREE));
catch_match_fcall = build_function_call (CatchMatch, params);
call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
assemble_external (TREE_OPERAND (CatchMatch, 0));
return_value_rtx =
hard_function_value (integer_type_node, catch_match_fcall);
......@@ -1192,6 +1239,7 @@ void expand_end_catch_block ()
emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
Pmode,
top_label_entry (&caught_return_label_stack)));
make_first_label(throw_label);
emit_jump (throw_label);
/* No associated finalization. */
entry.finalization = NULL_TREE;
......@@ -1210,6 +1258,10 @@ void expand_end_catch_block ()
entry.start_label = start_protect_label_rtx;
entry.end_label = end_protect_label_rtx;
LABEL_PRESERVE_P (entry.start_label) = 1;
LABEL_PRESERVE_P (entry.end_label) = 1;
LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
/* These set up a call to throw the caught exception into the outer
context. */
enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
......@@ -1279,6 +1331,7 @@ do_unwind (throw_label)
gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
do_function_call (Unwind, params, NULL_TREE);
assemble_external (TREE_OPERAND (Unwind, 0));
emit_barrier ();
#endif
#if m88k
......@@ -1304,9 +1357,18 @@ do_unwind (throw_label)
(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
#endif
#endif
#ifdef __arm
if (flag_omit_frame_pointer)
sorry ("this implementation of exception handling requires a frame pointer");
emit_move_insn (stack_pointer_rtx,
gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -8)));
emit_move_insn (hard_frame_pointer_rtx,
gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -12)));
#endif
}
/* is called from expand_excpetion_blocks () to generate the code in a function
/* is called from expand_exception_blocks () to generate the code in a function
to "throw" if anything in the function needs to preform a throw.
expands "throw" as the following psuedo code:
......@@ -1333,12 +1395,14 @@ expand_builtin_throw ()
rtx unwind_and_throw = gen_label_rtx ();
rtx goto_unwind_and_throw = gen_label_rtx ();
make_first_label(throw_label);
emit_label (throw_label);
/* search for an exception handler for the saved_pc */
return_val_rtx = do_function_call (FirstExceptionMatch,
tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
ptr_type_node);
assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
/* did we find one? */
emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
......@@ -1354,9 +1418,15 @@ expand_builtin_throw ()
emit_label (gotta_rethrow_it);
/* call to __builtin_return_address () */
#ifdef __arm
/* This replaces a 'call' to __builtin_return_address */
return_val_rtx = gen_reg_rtx (Pmode);
emit_move_insn (return_val_rtx, gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -4)));
#else
params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fcall = build_function_call (BuiltinReturnAddress, params);
return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
#endif
/* did __builtin_return_address () return a valid address? */
emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
......@@ -1364,20 +1434,35 @@ expand_builtin_throw ()
emit_jump_insn (gen_beq (gotta_call_terminate));
#ifdef __arm
/* On the ARM, '__builtin_return_address', must have 4
subtracted from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));
/* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit
mode, the condition codes must be masked out of the return value, or else
they will confuse BuiltinReturnAddress. This does not apply to ARM6 and
later processors when running in 32 bit mode. */
if (!TARGET_6)
emit_insn (gen_rtx (SET, SImode, return_val_rtx, gen_rtx (AND, SImode, return_val_rtx, GEN_INT (0x03fffffc))));
#else
#ifndef sparc
/* On the SPARC, __builtin_return_address is already -8, no need to
subtract any more from it. */
emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
#endif
#endif
/* yes it did */
emit_move_insn (saved_pc, return_val_rtx);
do_unwind (throw_label);
make_first_label(throw_label);
emit_jump (throw_label);
/* no it didn't --> therefore we need to call terminate */
emit_label (gotta_call_terminate);
do_function_call (Terminate, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Terminate, 0));
}
......@@ -1424,7 +1509,7 @@ expand_exception_blocks ()
1. Allocate space to save the current PC onto the stack.
2. Generate and emit a label and save its address into the
newly allocate stack space since we can't save the pc directly.
newly allocated stack space since we can't save the pc directly.
3. If this is the first call to throw in this function:
generate a label for the throw block
4. jump to the throw block label. */
......@@ -1476,6 +1561,7 @@ expand_throw (exp)
/* This part is easy, as we dont' have to do anything else. */
}
make_first_label(throw_label);
emit_jump (throw_label);
}
......
......@@ -19,8 +19,10 @@ __headof__, HEADOF, NORID
__inline, SCSPEC, RID_INLINE
__inline__, SCSPEC, RID_INLINE
__label__, LABEL, NORID
__signature__, AGGR, RID_SIGNATURE /* Extension */,
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
__sigof__, SIGOF, NORID /* Extension */,
__typeof, TYPEOF, NORID
__typeof__, TYPEOF, NORID
__volatile, TYPE_QUAL, RID_VOLATILE
......
......@@ -2376,9 +2376,9 @@ add_friend (type, decl)
{
if (decl == TREE_VALUE (friends))
{
cp_pedwarn ("`%D' is already a friend of class `%T'",
cp_warning ("`%D' is already a friend of class `%T'",
decl, type);
cp_pedwarn_at ("previous friend declaration of `%D'",
cp_warning_at ("previous friend declaration of `%D'",
TREE_VALUE (friends));
return;
}
......@@ -2948,12 +2948,15 @@ build_new (placement, decl, init, use_global_new)
else
size = size_in_bytes (type);
if (true_type == void_type_node)
{
error ("invalid type for new: `void'");
return error_mark_node;
}
if (TYPE_SIZE (true_type) == 0)
{
if (true_type == void_type_node)
error ("invalid type for new: `void'");
else
incomplete_type_error (0, true_type);
incomplete_type_error (0, true_type);
return error_mark_node;
}
......
......@@ -403,6 +403,8 @@ void
init_lex ()
{
extern char *(*decl_printable_name) ();
extern int flag_no_gnu_keywords;
extern int flag_operator_names;
int i;
......@@ -788,23 +790,21 @@ init_lex ()
}
#endif
if (! (flag_gc || flag_rtti))
if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
{
UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof");
}
if (! flag_handle_signatures)
if (! flag_handle_signatures || flag_no_gnu_keywords)
{
/* Easiest way to not recognize signature
handling extensions... */
UNSET_RESERVED_WORD ("signature");
UNSET_RESERVED_WORD ("sigof");
}
if (flag_no_asm)
UNSET_RESERVED_WORD ("asm");
if (flag_no_asm || flag_traditional)
if (flag_no_asm || flag_no_gnu_keywords)
UNSET_RESERVED_WORD ("typeof");
if (!flag_ansi)
if (! flag_operator_names)
{
/* These are new ANSI keywords that may break code. */
UNSET_RESERVED_WORD ("and");
......@@ -815,6 +815,8 @@ init_lex ()
UNSET_RESERVED_WORD ("or");
UNSET_RESERVED_WORD ("xor");
}
if (! flag_traditional)
UNSET_RESERVED_WORD ("overload");
token_count = init_parse ();
interface_unknown = 1;
......@@ -4211,7 +4213,7 @@ real_yylex ()
goto tryagain;
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= (1 << width))
pedwarn ("escape sequence out of range for character");
warning ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
if (isprint (c))
c = MAP_CHARACTER (c);
......@@ -4328,7 +4330,7 @@ real_yylex ()
if (!wide_flag
&& TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
&& c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
pedwarn ("escape sequence out of range for character");
warning ("escape sequence out of range for character");
}
else if (c == '\n')
{
......@@ -4483,7 +4485,7 @@ real_yylex ()
}
else if ((c == '-') && (c1 == '>'))
{
nextchar = skip_white_space (getch ());
nextchar = getch ();
if (nextchar == '*')
{
nextchar = -1;
......@@ -4510,11 +4512,22 @@ real_yylex ()
value = MIN_MAX;
nextchar = c1;
}
if (flag_ansi)
if (pedantic)
pedwarn ("use of `operator %s' is not standard C++",
token_buffer);
goto done;
}
/* digraphs */
else if (c == '<' && c1 == '%')
{ value = '{'; goto done; }
else if (c == '<' && c1 == ':')
{ value = '['; goto done; }
else if (c == '%' && c1 == '>')
{ value = '}'; goto done; }
else if (c == '%' && c1 == ':')
{ value = '#'; goto done; }
else if (c == ':' && c1 == '>')
{ value = ']'; goto done; }
nextchar = c1;
token_buffer[1] = 0;
......
......@@ -123,6 +123,7 @@ extern int looking_for_template;
/* Tell the lexer where to look for names. */
extern tree got_scope;
extern tree got_object;
/* Pending language change.
Positive is push count, negative is pop count. */
......
......@@ -1246,7 +1246,8 @@ expr_no_commas:
| expr_no_commas '?' xexpr ':' expr_no_commas
{ $$ = build_x_conditional_expr ($$, $3, $5); }
| expr_no_commas '=' expr_no_commas
{ $$ = build_modify_expr ($$, NOP_EXPR, $3); }
{ $$ = build_modify_expr ($$, NOP_EXPR, $3);
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
| expr_no_commas ASSIGN expr_no_commas
{ register tree rval;
if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
......@@ -1333,7 +1334,12 @@ primary:
| string
{ $$ = combine_strings ($$); }
| '(' expr ')'
{ $$ = $2; }
{ char class = TREE_CODE_CLASS (TREE_CODE ($2));
if (class == 'e' || class == '1'
|| class == '2' || class == '<')
/* This inhibits warnings in truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
$$ = $2; }
| '(' error ')'
{ $$ = error_mark_node; }
| '('
......@@ -1538,11 +1544,14 @@ primary:
| overqualified_id LEFT_RIGHT
{ $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
| object unqualified_id %prec UNARY
{ $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
{ got_object = NULL_TREE;
$$ = build_component_ref ($$, $2, NULL_TREE, 1); }
| object qualified_id %prec UNARY
{ $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
{ got_object = NULL_TREE;
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')'
{
got_object = NULL_TREE;
#if 0
/* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done
......@@ -1558,6 +1567,7 @@ primary:
}
| object unqualified_id LEFT_RIGHT
{
got_object = NULL_TREE;
#if 0
/* This is a future direction of this code, but because
build_x_function_call cannot always undo what is done
......@@ -1573,6 +1583,7 @@ primary:
}
| object qualified_id '(' nonnull_exprlist ')'
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{
warning ("signature name in scope resolution ignored");
......@@ -1584,6 +1595,7 @@ primary:
}
| object qualified_id LEFT_RIGHT
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
{
warning ("signature name in scope resolution ignored");
......@@ -1595,14 +1607,16 @@ primary:
}
/* p->int::~int() is valid -- 12.4 */
| object '~' TYPESPEC LEFT_RIGHT
{
{
got_object = NULL_TREE;
if (TREE_CODE (TREE_TYPE ($1))
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
cp_error ("`%E' is not of type `%T'", $1, $3);
$$ = convert (void_type_node, $1);
}
| object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
{
{
got_object = NULL_TREE;
if ($2 != $5)
cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
if (TREE_CODE (TREE_TYPE ($1))
......@@ -1610,6 +1624,11 @@ primary:
cp_error ("`%E' is not of type `%T'", $1, $2);
$$ = convert (void_type_node, $1);
}
| object error
{
got_object = NULL_TREE;
$$ = error_mark_node;
}
;
/* Not needed for now.
......@@ -1690,9 +1709,11 @@ nodecls:
;
object: primary '.'
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT
{
$$ = build_x_arrow ($$);
$$ = build_x_arrow ($$);
got_object = TREE_TYPE ($$);
}
;
......@@ -3288,7 +3309,7 @@ simple_stmt:
else if (success == 2)
{
cp_error ("duplicate case value `%E'", $2);
cp_error_at ("`%E' previously used here", duplicate);
cp_error_at ("previously used here", duplicate);
}
else if (success == 3)
warning ("case value out of range");
......
......@@ -1257,6 +1257,8 @@ tsubst (t, args, nargs, in_decl)
type = newtype;
fnargs = copy_node (DECL_ARGUMENTS (t));
TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
/* In this case we need "in-charge" flag saying whether
this constructor is responsible for initialization
of virtual baseclasses or not. */
......@@ -1419,7 +1421,7 @@ tsubst (t, args, nargs, in_decl)
r = build_lang_decl (FUNCTION_DECL, r, type);
DECL_ASSEMBLER_NAME (r) = a;
}
else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r))
else if (TREE_STATIC (r))
{
/* This overrides the template version, use it. */
return r;
......@@ -1718,7 +1720,7 @@ instantiate_template (tmpl, targ_ptr)
/* If we have a preexisting version of this function, don't expand
the template version, use the other instead. */
if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))
if (TREE_STATIC (fndecl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
p = (struct pending_inline *)0;
......@@ -2448,7 +2450,7 @@ do_function_instantiation (declspecs, declarator, storage)
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
int i, dummy;
int i, dummy = 0;
i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl)),
......@@ -2460,6 +2462,7 @@ do_function_instantiation (declspecs, declarator, storage)
else
result = instantiate_template (fn, targs);
}
free (targs);
}
}
if (! result)
......
......@@ -1089,18 +1089,29 @@ lookup_field (xbasetype, name, protect, want_type)
entry = 0;
rval = lookup_field_1 (type, name);
if (rval || lookup_fnfields_here (type, name)>=0)
{
rval_binfo = basetype_path;
rval_binfo_h = rval_binfo;
}
if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
rval = NULL_TREE;
if (rval)
if (rval || lookup_fnfields_here (type, name) >= 0)
{
if (protect)
if (rval)
{
if (want_type)
{
if (TREE_CODE (rval) != TYPE_DECL)
{
rval = purpose_member (name, CLASSTYPE_TAGS (type));
if (rval)
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
}
}
else
{
if (TREE_CODE (rval) == TYPE_DECL
&& lookup_fnfields_here (type, name) >= 0)
rval = NULL_TREE;
}
}
if (protect && rval)
{
if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
this_v = compute_access (basetype_path, rval);
......@@ -1259,12 +1270,33 @@ lookup_field (xbasetype, name, protect, want_type)
if (entry)
TREE_VALUE (entry) = rval;
if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL))
if (rval_binfo)
{
rval = NULL_TREE;
errstr = 0;
type = BINFO_TYPE (rval_binfo);
if (rval)
{
if (want_type)
{
if (TREE_CODE (rval) != TYPE_DECL)
{
rval = purpose_member (name, CLASSTYPE_TAGS (type));
if (rval)
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
}
}
else
{
if (TREE_CODE (rval) == TYPE_DECL
&& lookup_fnfields_here (type, name) >= 0)
rval = NULL_TREE;
}
}
}
if (rval == NULL_TREE)
errstr = 0;
/* If this FIELD_DECL defines its own access level, deal with that. */
if (rval && errstr == 0
&& ((protect&1) || entry)
......@@ -1948,11 +1980,51 @@ get_matching_virtual (binfo, fndecl, dtorp)
== TYPE_READONLY (instptr_type))
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
{
if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
if (comptypes (brettype, drettype, 1))
/* OK */;
else if
(TREE_CODE (brettype) == TREE_CODE (drettype)
&& (TREE_CODE (brettype) == POINTER_TYPE
|| TREE_CODE (brettype) == REFERENCE_TYPE)
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)),
TYPE_MAIN_VARIANT (TREE_TYPE (drettype)),
0))
/* covariant return type */
{
tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype);
if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d))
{
tree binfo = get_binfo (b, d, 1);
if (binfo != error_mark_node
&& ! BINFO_OFFSET_ZEROP (binfo))
sorry ("adjusting pointers for covariant returns");
}
if (TYPE_READONLY (d) > TYPE_READONLY (b))
{
cp_error ("return type of `%#D' adds const", fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
}
else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
{
cp_error ("return type of `%#D' adds volatile",
fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
}
}
else if (IS_AGGR_TYPE_2 (brettype, drettype)
&& comptypes (brettype, drettype, 0))
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
cp_error (" with `%#D'", fndecl);
}
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
{
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error_at ("overriding definition as `%#D'", tmp);
cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
break;
......@@ -2192,7 +2264,7 @@ dfs_walk (binfo, fn, qfn)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
if ((*qfn)(base_binfo))
if (qfn == 0 || (*qfn)(base_binfo))
{
if (fn == dfs_init_vbase_pointers)
{
......@@ -2800,8 +2872,14 @@ dfs_pushdecls (binfo)
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
if (context && (context == type
|| TYPE_DERIVES_FROM (context, type)))
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,
......@@ -3210,3 +3288,24 @@ reinit_search_statistics ()
n_outer_fields_searched = 0;
n_contexts_saved = 0;
}
static tree conversions;
static void
add_conversions (binfo)
tree binfo;
{
tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
tmp = TREE_CHAIN (tmp))
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
conversions);
}
tree
lookup_conversions (type)
tree type;
{
conversions = NULL_TREE;
dfs_walk (TYPE_BINFO (type), add_conversions, 0);
return conversions;
}
......@@ -242,6 +242,7 @@ int looking_for_template;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
tree got_object;
int
yylex()
......@@ -316,7 +317,7 @@ yylex()
if (lastiddecl != trrr)
{
lastiddecl = trrr;
if (got_scope)
if (got_scope || got_object)
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
}
break;
......@@ -334,8 +335,11 @@ yylex()
lastiddecl = trrr;
got_scope = NULL_TREE;
/* and fall through to... */
case IDENTIFIER_DEFN:
case TYPENAME:
case TYPENAME_DEFN:
case PTYPENAME:
case PTYPENAME_DEFN:
consume_token ();
if (looking_for_typename > 0)
looking_for_typename--;
......
......@@ -102,6 +102,11 @@ lvalue_p (ref)
case COMPOUND_EXPR:
return lvalue_p (TREE_OPERAND (ref, 1));
case MAX_EXPR:
case MIN_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)));
}
return 0;
......@@ -570,9 +575,13 @@ layout_vbasetypes (rec, max)
BINFO_OFFSET (vbase_types) = offset;
if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
const_size += MAX (BITS_PER_UNIT,
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
{
/* Every virtual baseclass takes a least a UNIT, so that we can
take it's address and get something different for each base. */
const_size += MAX (BITS_PER_UNIT,
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
}
else if (var_size == 0)
var_size = TYPE_SIZE (basetype);
else
......@@ -581,6 +590,15 @@ layout_vbasetypes (rec, max)
vbase_types = TREE_CHAIN (vbase_types);
}
if (const_size)
{
/* Because a virtual base might take a single byte above,
we have to re-adjust the total size to make sure it it
a multiple of the alignment. */
/* Give the whole object the alignment it wants. */
const_size = CEIL (const_size, record_align) * record_align;
}
/* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN
here, as that is for this class, without any virtual base classes. */
TYPE_ALIGN (rec) = record_align;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment