53rd Cygnus<->FSF merge

From-SVN: r8794
This commit is contained in:
Mike Stump 1995-01-24 08:19:58 +00:00
parent 43238b97ad
commit e1cd6e56ad
18 changed files with 1308 additions and 880 deletions

View File

@ -1,18 +1,381 @@
Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com>
* pt.c (tsubst): When we copy a node, don't forget to copy
TREE_CHAIN, we use it later.
Mon Jan 23 03:33:47 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (convert_for_assignment): Initialize variable before use.
Fri Jan 20 01:17:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* g++.c (main): Link with both libstdc++ and libg++ if called as
something ending with "g++", otherwise only libstdc++. Move -lm to
the end of the line.
Thu Jan 19 15:43:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (build_method_call): Don't mess with 'this' before calling
compute_conversion_costs.
Wed Jan 18 15:40:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* search.c (get_matching_virtual): Give line number for previous
declaration.
* call.c (convert_harshness): Handle conversions to references
better.
* cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*.
Wed Jan 18 15:21:38 1995 Mike Stump <mrs@cygnus.com>
* class.c (instantiate_type): Use DECL_CHAIN to walk lists instead,
as the TREE_CHAIN for methods will take us to the next differently
named function, DECL_CHAIN won't.
Wed Jan 18 14:26:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* tree.c (lvalue_p): Handle {MIN,MAX}_EXPR.
* decl2.c (lang_decode_option): -Wall implies -Wparentheses.
warn_parentheses defaults to 0.
* decl.c (grokparms): Put back call to require_instantiated_type.
Tue Jan 17 19:56:15 1995 Mike Stump <mrs@cygnus.com>
* except.c (exception_section): Use the data section on the rs6000.
Change calling convention for named_section.
Wed Jan 17 18:20:57 1994 Fergus Henderson <fjh@munta.cs.mu.oz.au>
* cp-tree.h : Make if (x=0) warn with wall
* parse.y : Make if (x=0) warn with wall
Tue Jan 17 14:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cvt.c (cp_convert): Just call truthvalue_conversion to convert to
* decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS,
BITS_PER_UNIT otherwise.
* search.c (get_matching_virtual): Don't check the binfo if the
types are the same.
* cvt.c (cp_convert): Just call truthvalue_conversion to convert to
bool.
Mon Jan 16 13:28:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* various: Use boolean_type_node, boolean_true_node,
boolean_false_node.
* various: Use boolean_type_node, boolean_true_node,
boolean_false_node.
* search.c (get_matching_virtual): Allow covariant returns that
don't require pointer adjustment.
* typeck.c (build_conditional_expr): Don't call default_conversion
on ifexp.
* cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR.
* decl.c (grokdeclarator): Upgrade warning about &const to pedwarn.
Sun Jan 15 22:17:32 1995 dcb@lovat.fmrco.COM (David Binderman)
* pt.c (do_function_instantiation): Free targs once we're done.
Sun Jan 15 22:17:32 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
(init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
for bool.
* decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
(init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
for bool.
Sat Jan 14 05:33:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl2.c (finish_file): We need to mess up if there are any
variables in the list, not just if there is one with a constructor.
Fri Jan 13 14:42:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR.
(finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR.
(finish_function): Trust rest_of_compilation.
* decl2.c (finish_file): Also call functions designated as static
constructors/destructors.
* decl.c (grokdeclarator): Allow access decls of operator functions.
(grokparms): Only do convert_for_initialization if the initializer
has a type.
(duplicate_decls): Put back push_obstacks_nochange call.
* lex.c (real_yylex): Downgrade complaint about the escape sequence
being too large from pedwarn to warning.
* decl.c (grokdeclarator): Don't complain about long long in system
headers.
* lex.c (real_yylex): Handle digraphs.
Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (init_decl_processing): -f{no-,}strict-prototype only
affects C linkage declarations now.
* typeck.c (comp_target_types): Grok simple contravariant conversions.
(common_type): t1 and t2 are interchangeable.
* various: Test return value of comp_target_types differently in
different places; it now returns -1 for a contravariant conversion
(which is fine in symmetric cases).
(common_type): Prefer long double to double even when
they have the same precision.
* decl.c (grokparms): Call convert_for_initialization to check
default arguments.
* init.c (build_new): void_type_node has a size (of 0).
* decl.c (decls_match): Also check for agreement of TREE_READONLY
and TREE_THIS_VOLATILE.
(push_class_level_binding): Properly handle shadowing of
nested tags by fields.
* search.c (dfs_pushdecls): Ditto.
* decl2.c (finish_file): Don't second-guess self-initialization.
* cvt.c (convert_to_reference): Work with expr directly, rather than
a copy.
* decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs.
* init.c (add_friend): Downgrade duplicate friend message from
pedwarn to warning.
* decl.c (duplicate_decls): Push obstacks before calling common_type.
Thu Jan 12 17:15:21 1995 Michael Ben-Gershon <mybg@cs.huji.ac.il>
* except.c (push_eh_entry): set LABEL_PRESERVE_P flag for
exception table labels.
(expand_start_all_catch): Ditto.
(expand_leftover_cleanups): Ditto.
(expand_end_catch_block): Ditto.
* except.c (make_first_label): new function.
(expand_start_all_catch): add a call to make_first_label() before
using a label as a jump destination.
(expand_end_all_catch): Ditto.
(expand_leftover_cleanups): Ditto.
(expand_end_catch_block): Ditto.
(expand_builtin_throw): Ditto.
(expand_throw): Ditto.
* except.c: Add ARM processor support for exception handling.
Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
(complete_array_type): Copy code from C frontend.
* lex.c (real_yylex): Don't multiply the length of a wide string
literal by WCHAR_BYTES.
* decl.c (pushdecl): Check for redeclaration of wchar_t here.
(duplicate_decls): Instead of here.
(define_label): Complain about a label named wchar_t.
(grokdeclarator): Complain about declarations of
operator-function-ids as non-functions.
* typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in
COMPOUND_EXPRs.
(build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR.
* lex.c (real_yylex): Don't skip whitespace when reading the next
character after ->.
Wed Jan 11 16:32:49 1995 Mike Stump <mrs@cygnus.com>
* except.c: Allow cc1plus to be built with native compiler on rs6000.
(expand_start_all_catch): Add assemble_external calls for various
routines we call.
(expand_leftover_cleanups): Ditto.
(expand_start_catch_block): Ditto.
(do_unwind): Ditto.
(expand_builtin_throw): Ditto.
Wed Jan 11 01:05:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (pushtag): Only look for a previous decl in the current
binding level. Use explicit global scope in DECL_NESTED_TYPENAME.
* gxx.gperf: Add __signature__ and __sigof__ keywords.
* decl2.c (lang_decode_option): -ansi does not set flag_no_asm. It
does set flag_no_gnu_keywords and flag_operator_names.
* lex.c (init_lex): 'overload' is not a keyword unless -traditional.
Unset extension keywords if -fno-gnu-keywords.
Allow operator names ('bitand') if -foperator-names.
Never unset 'asm'; -fno-asm only affects 'typeof'.
* decl.c (lookup_name_real): The got_object special lookup only
applies to types.
Tue Jan 10 18:07:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set.
* parse.y (primary): Unset got_object after all rules that use the
'object' nonterminal.
(object): Set got_object.
* lex.h: Declare got_object.
* decl.c (lookup_name_real): Also lookup names in the context of an
object specified.
Tue Jan 10 14:30:30 1995 Mike Stump <mrs@cygnus.com>
* typeck.c (get_member_function_from_ptrfunc): Use ptrdiff_type_node
for things that have to be added to pointers, not size_type. Cures
problems with pointer to members on Alphas.
(build_binary_op_nodefault): Ditto.
(get_delta_difference_: Ditto.
(build_ptrmemfunc): Ditto.
Tue Jan 10 01:49:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing
it.
* typeck.c (build_component_ref): Don't build up a COMPONENT_REF
when dealing with overloaded member functions; just act like
build_offset_ref.
(commonparms): Remove misleading comment.
* decl.c (duplicate_decls): Complain about repeated default
arguments here.
(redeclaration_error_message): Instead of here.
(pushdecl): Complain about missing default arguments here.
(grokparms): Instead of here.
(lookup_name_current_level): Also match on DECL_ASSEMBLER_NAME.
(grok_reference_init): Do not complain about missing initializer if
declared 'extern'.
* search.c (lookup_field): Don't return a TYPE_DECL if there is a
function alternative and want_type is not set.
Mon Jan 9 18:16:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* decl.c (pushtag): Don't set TYPE_NAME to an identifier. Do push
the decl when the type has no TYPE_NAME.
(lookup_nested_type): Don't assume that type has TYPE_NAME set.
(lookup_name_real): Call lookup_field with want_type =
prefer_type.
* search.c (lookup_field): Handle want_type properly in the presence
of fields with the same name.
* decl.c (set_nested_typename): Set nested name for file-scope types
to include leading ::.
(pushdecl): Set the nested typename if the decl doesn't have one,
rather than if the type's canonical decl doesn't have one.
Mon Jan 9 16:48:16 1995 Steve Chamberlain (sac@jonny.cygnus.com)
* typeck.c (pointer_int_sum): Use offset size when calculating
index expression.
Mon Jan 9 03:44:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck.c (convert_for_assignment): Complain about contravariance
violation here.
(comp_target_types): Instead of here.
(build_unary_op): resolve_offset_ref before checking for a valid
type.
* spew.c (yylex): Decrement looking_for_typename after we see a
_DEFN.
* decl.c (pushdecl): Don't install an artificial TYPE_DECL in
IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
* typeck.c (convert_for_assignment): Converting pointers to bool
does not need a cast.
Sun Jan 8 18:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* class.c (instantiate_type): Initialize nsubsts parm.
* pt.c (do_function_instantiation): Ditto.
Sat Jan 7 14:37:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* pt.c (tsubst): Use TREE_STATIC instead of DECL_INLINE &&
DECL_SAVED_INSNS to determine whether or not we've seen a definition
of this function.
(instantiate_template): Ditto.
* call.c (convert_harshness): Allow const reference binding when
called from the overloading code, but not when called from
can_convert (since it isn't a conversion).
(convert_harshness): Put back some disabled code.
Fri Jan 6 14:10:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (convert_harshness): There is no implicit conversion from
void* to other pointer types (unless the parameter is (void*)0).
(convert_harshness): Non-lvalues do not convert to reference types.
* class.c (finish_struct_methods): Still set
TYPE_HAS_{INT,REAL}_CONVERSION.
* call.c (can_convert): Don't use aggregate initialization.
* cp-tree.h: Declare lookup_conversions.
Thu Jan 5 21:08:00 1995 Mike Stump <mrs@cygnus.com>
* parse.y (simple_stmt): Fix duplicate case value error messages to
be more readable.
Wed Jan 4 16:44:19 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* cvt.c (build_type_conversion): Total rewrite to use
convert_harshness instead of reproducing conversion logic here. Now
much shorter.
* call.c (convert_harshness): Support conversions to bool.
(can_convert): Checks whether a conversion is less harsh
than USER_CODE, for build_type_conversion.
* search.c (add_conversions): Function for passing to dfs_walk which
adds all the type conversion operators in the current type to a list.
(lookup_conversions): Calls dfs_walk with add_conversions and return
the list.
(dfs_walk): Don't require a qfn.
* cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery.
(CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC.
* class.c (finish_struct_bits): Lose CLASSTYPE_CONVERSIONS hackery.
(grow_method): A separate function for building onto the growing
method vector.
(finish_struct_methods): Use it. Put all type conversion operators
right after the constructors. Perhaps we should sort the methods
alphabetically?
Mon Jan 2 14:42:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* call.c (build_method_call): Lose another misleading shortcut.
Fri Dec 30 17:57:30 1994 Mike Stump <mrs@cygnus.com>
* gc.c (build_bltn_desc): Handle bool as a built-in type.
Fri Dec 30 14:20:21 1994 Mike Stump <mrs@cygnus.com>
* tree.c (layout_vbasetypes): Ensure that we don't loose alignment
on the complete type because of small virtual bases.
Fri Dec 30 12:22:29 1994 Mike Stump <mrs@cygnus.com>

View File

@ -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;
}
/* Maybe handle conversion to base here? */
if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
h = convert_harshness (ttl, ttr, NULL_TREE);
if (penalty && h.code == 0)
{
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;
}
/* 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)
{
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++;
}
}

View File

@ -1687,63 +1687,6 @@ finish_struct_bits (t, max_has_virtual)
}
}
/* Need to test METHOD_VEC here in case all methods
(conversions and otherwise) are inherited. */
if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE)
{
tree first_conversions[last_conversion_type];
tree last_conversions[last_conversion_type];
enum conversion_type conv_index;
tree *tmp;
int i;
bzero ((char *) first_conversions, sizeof (first_conversions));
bzero ((char *) last_conversions, sizeof (last_conversions));
for (tmp = &TREE_VEC_ELT (method_vec, 1);
tmp != TREE_VEC_END (method_vec); tmp += 1)
{
/* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR]. */
if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp)))
{
tree fntype = TREE_TYPE (*tmp);
tree return_type = TREE_TYPE (fntype);
my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171);
if (typecode_p (return_type, POINTER_TYPE))
{
if (TYPE_READONLY (TREE_TYPE (return_type)))
conv_index = constptr_conv;
else
conv_index = ptr_conv;
}
else if (typecode_p (return_type, INTEGER_TYPE)
|| typecode_p (return_type, BOOLEAN_TYPE)
|| typecode_p (return_type, ENUMERAL_TYPE))
{
TYPE_HAS_INT_CONVERSION (t) = 1;
conv_index = int_conv;
}
else if (typecode_p (return_type, REAL_TYPE))
{
TYPE_HAS_REAL_CONVERSION (t) = 1;
conv_index = real_conv;
}
else
continue;
if (first_conversions[(int) conv_index] == NULL_TREE)
first_conversions[(int) conv_index] = *tmp;
last_conversions[(int) conv_index] = *tmp;
}
}
for (i = 0; i < (int) last_conversion_type; i++)
if (first_conversions[i] != last_conversions[i])
CLASSTYPE_CONVERSION (t, i) = error_mark_node;
else
CLASSTYPE_CONVERSION (t, i) = first_conversions[i];
}
/* If this type has constructors, force its mode to be BLKmode,
and force its TREE_ADDRESSABLE bit to be nonzero. */
if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t))
@ -1761,6 +1704,57 @@ finish_struct_bits (t, max_has_virtual)
}
}
/* Add FN to the method_vec growing on the class_obstack. Used by
finish_struct_methods. */
static void
grow_method (fn)
tree fn;
{
tree method_vec = (tree)obstack_base (&class_obstack);
tree *testp = &TREE_VEC_ELT (method_vec, 0);
if (*testp == NULL_TREE)
testp++;
while (((HOST_WIDE_INT) testp
< (HOST_WIDE_INT) obstack_next_free (&class_obstack))
&& DECL_NAME (*testp) != DECL_NAME (fn))
testp++;
if ((HOST_WIDE_INT) testp
< (HOST_WIDE_INT) obstack_next_free (&class_obstack))
{
tree x, prev_x;
for (x = *testp; x; x = DECL_CHAIN (x))
{
if (DECL_NAME (fn) == ansi_opname[(int) DELETE_EXPR]
|| DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR])
{
/* ANSI C++ June 5 1992 WP 12.5.5.1 */
cp_error_at ("`%D' overloaded", fn);
cp_error_at ("previous declaration as `%D' here", x);
}
if (DECL_ASSEMBLER_NAME (fn)==DECL_ASSEMBLER_NAME (x))
{
/* We complain about multiple destructors on sight,
so we do not repeat the warning here. Friend-friend
ambiguities are warned about outside this loop. */
if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn)))
cp_error_at ("ambiguous method `%#D' in structure", fn);
break;
}
prev_x = x;
}
if (x == 0)
{
if (*testp)
DECL_CHAIN (prev_x) = fn;
else
*testp = fn;
}
}
else
obstack_ptr_grow (&class_obstack, fn);
}
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
@ -1769,10 +1763,12 @@ finish_struct_bits (t, max_has_virtual)
Data Structure: List of method lists. The outer list is a
TREE_LIST, whose TREE_PURPOSE field is the field name and the
TREE_VALUE is the TREE_CHAIN of the FUNCTION_DECLs. Friends are
chained in the same way as member functions, but they live in the
TREE_TYPE field of the outer list. That allows them to be quickly
deleted, and requires no extra storage.
TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN
links the entire list of methods for TYPE_METHODS. Friends are
chained in the same way as member functions (? TREE_CHAIN or
DECL_CHAIN), but they live in the TREE_TYPE field of the outer
list. That allows them to be quickly deleted, and requires no
extra storage.
If there are any constructors/destructors, they are moved to the
front of the list. This makes pushclass more efficient.
@ -1789,6 +1785,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
int nonprivate_method;
{
tree method_vec;
tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields);
tree lastp;
tree name = constructor_name (t);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@ -1802,17 +1800,15 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
obstack_free (&class_obstack, method_vec);
obstack_blank (&class_obstack, sizeof (struct tree_vec));
while (fn_fields)
/* First fill in entry 0 with the constructors, and the next few with
type conversion operators (if any). */
for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp))
{
/* NEXT Pointer, TEST Pointer, and BASE Pointer. */
tree nextp, *testp;
tree fn_name = DECL_NAME (fn_fields);
if (fn_name == NULL_TREE)
fn_name = name;
nextp = TREE_CHAIN (fn_fields);
TREE_CHAIN (fn_fields) = NULL_TREE;
/* Clear out this flag.
@@ Doug may figure out how to break
@ -1840,8 +1836,45 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
}
}
/* Constructors are handled easily in search routines. */
DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
TREE_VEC_ELT (method_vec, 0) = fn_fields;
}
else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
else if (IDENTIFIER_TYPENAME_P (fn_name))
{
tree return_type = TREE_TYPE (TREE_TYPE (fn_fields));
if (typecode_p (return_type, INTEGER_TYPE)
|| typecode_p (return_type, BOOLEAN_TYPE)
|| typecode_p (return_type, ENUMERAL_TYPE))
TYPE_HAS_INT_CONVERSION (t) = 1;
else if (typecode_p (return_type, REAL_TYPE))
TYPE_HAS_REAL_CONVERSION (t) = 1;
grow_method (fn_fields);
}
else
{
lastp = fn_fields;
continue;
}
TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields);
TREE_CHAIN (fn_fields) = NULL_TREE;
}
fn_fields = TREE_CHAIN (save_fn_fields);
while (fn_fields)
{
tree nextp;
tree fn_name = DECL_NAME (fn_fields);
if (fn_name == NULL_TREE)
fn_name = name;
nextp = TREE_CHAIN (fn_fields);
TREE_CHAIN (fn_fields) = NULL_TREE;
if (fn_name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
@ -1854,65 +1887,12 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
}
}
/* Constructors are handled easily in search routines. */
if (fn_name == name)
{
DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
TREE_VEC_ELT (method_vec, 0) = fn_fields;
}
else
{
testp = &TREE_VEC_ELT (method_vec, 0);
if (*testp == NULL_TREE)
testp++;
while (((HOST_WIDE_INT) testp
< (HOST_WIDE_INT) obstack_next_free (&class_obstack))
&& DECL_NAME (*testp) != fn_name)
testp++;
if ((HOST_WIDE_INT) testp
< (HOST_WIDE_INT) obstack_next_free (&class_obstack))
{
tree x, prev_x;
for (x = *testp; x; x = DECL_CHAIN (x))
{
if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]
|| DECL_NAME (fn_fields)
== ansi_opname[(int) VEC_DELETE_EXPR])
{
/* ANSI C++ June 5 1992 WP 12.5.5.1 */
cp_error_at ("`%D' overloaded", fn_fields);
cp_error_at ("previous declaration as `%D' here", x);
}
if (DECL_ASSEMBLER_NAME (fn_fields)==DECL_ASSEMBLER_NAME (x))
{
/* We complain about multiple destructors on sight,
so we do not repeat the warning here. Friend-friend
ambiguities are warned about outside this loop. */
if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))
cp_error_at ("ambiguous method `%#D' in structure",
fn_fields);
break;
}
prev_x = x;
}
if (x == 0)
{
if (*testp)
DECL_CHAIN (prev_x) = fn_fields;
else
*testp = fn_fields;
}
}
else
{
obstack_ptr_grow (&class_obstack, fn_fields);
method_vec = (tree)obstack_base (&class_obstack);
}
}
grow_method (fn_fields);
fn_fields = nextp;
}
/* Update in case method_vec has moved. */
method_vec = (tree)obstack_base (&class_obstack);
TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
- (&TREE_VEC_ELT (method_vec, 0));
obstack_finish (&class_obstack);
@ -4737,7 +4717,7 @@ instantiate_type (lhstype, rhs, complain)
/* First look for an exact match */
while (field && TREE_TYPE (field) != lhstype)
field = TREE_CHAIN (field);
field = DECL_CHAIN (field);
if (field)
{
TREE_OPERAND (rhs, 1) = field;
@ -4747,13 +4727,13 @@ instantiate_type (lhstype, rhs, complain)
/* No exact match found, look for a compatible function. */
field = TREE_OPERAND (rhs, 1);
while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
field = TREE_CHAIN (field);
field = DECL_CHAIN (field);
if (field)
{
TREE_OPERAND (rhs, 1) = field;
field = TREE_CHAIN (field);
field = DECL_CHAIN (field);
while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
field = TREE_CHAIN (field);
field = DECL_CHAIN (field);
if (field)
{
if (complain)
@ -4821,7 +4801,7 @@ instantiate_type (lhstype, rhs, complain)
{
int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
tree *t = (tree *) alloca (sizeof (tree) * n);
int i, d;
int i, d = 0;
i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), &d, 0);
@ -4845,14 +4825,15 @@ instantiate_type (lhstype, rhs, complain)
/* No match found, look for a compatible function. */
elem = get_first_fn (rhs);
while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 1) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
tree save_elem = elem;
elem = DECL_CHAIN (elem);
while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem),
0))
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 0) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
@ -4900,7 +4881,7 @@ instantiate_type (lhstype, rhs, complain)
if (comptypes (lhstype, TREE_TYPE (elem), 1))
return elem;
else
elem = TREE_CHAIN (elem);
elem = DECL_CHAIN (elem);
}
/* No exact match found, look for a compatible method. */
@ -4908,14 +4889,16 @@ instantiate_type (lhstype, rhs, complain)
baselink = next_baselink (baselink))
{
elem = TREE_VALUE (baselink);
while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
elem = TREE_CHAIN (elem);
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 1) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
tree save_elem = elem;
elem = TREE_CHAIN (elem);
while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 0))
elem = TREE_CHAIN (elem);
elem = DECL_CHAIN (elem);
while (elem && comp_target_types (lhstype,
TREE_TYPE (elem), 0) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
if (complain)
@ -4940,7 +4923,7 @@ instantiate_type (lhstype, rhs, complain)
#endif
}
if (complain)
error ("no static member functions named `%s'",
error ("no compatible member functions named `%s'",
IDENTIFIER_POINTER (name));
return error_mark_node;
}

View File

@ -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));

View File

@ -518,6 +518,18 @@ build_up_reference (type, arg, flags, checkconst)
build_up_reference (type, TREE_OPERAND (targ, 2),
LOOKUP_PROTECT, checkconst));
/* Undo the folding... */
case MIN_EXPR:
case MAX_EXPR:
return build (COND_EXPR, type,
build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR,
boolean_type_node, TREE_OPERAND (targ, 0),
TREE_OPERAND (targ, 1)),
build_up_reference (type, TREE_OPERAND (targ, 0),
LOOKUP_PROTECT, checkconst),
build_up_reference (type, TREE_OPERAND (targ, 1),
LOOKUP_PROTECT, checkconst));
case WITH_CLEANUP_EXPR:
return build (WITH_CLEANUP_EXPR, type,
build_up_reference (type, TREE_OPERAND (targ, 0),
@ -666,11 +678,10 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (form == REFERENCE_TYPE)
{
tree type = TREE_TYPE (expr);
tree tmp = copy_node (expr);
TREE_TYPE (tmp) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), tmp,
TREE_TYPE (expr) = build_pointer_type (TREE_TYPE (type));
rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), expr,
convtype, flags);
TREE_TYPE (tmp) = type;
TREE_TYPE (expr) = type;
TREE_TYPE (rval) = reftype;
return rval;
}
@ -1487,14 +1498,8 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
If (FOR_SURE & 1) is non-zero, then we allow this type conversion
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. */
If FOR_SURE >= 2, then we only look for exact conversions.
TYPE may be a reference type, in which case we first look
for something that will convert to a reference type. If
that fails, we will try to look for something of the
reference's target type, and then return a reference to that. */
tree
build_type_conversion (code, xtype, expr, for_sure)
enum tree_code code;
@ -1502,14 +1507,10 @@ build_type_conversion (code, xtype, expr, for_sure)
int for_sure;
{
/* C++: check to see if we can convert this aggregate type
into the required scalar type. */
tree type, type_default;
tree typename = build_typename_overload (xtype), *typenames;
int n_variants = 0;
tree basetype, save_basetype;
tree rval;
int exact_conversion = for_sure >= 2;
for_sure &= 1;
into the required type. */
tree basetype;
tree conv;
tree winner = NULL_TREE;
if (expr == error_mark_node)
return error_mark_node;
@ -1518,313 +1519,42 @@ build_type_conversion (code, xtype, expr, for_sure)
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
if (TYPE_PTRMEMFUNC_P (basetype) && TREE_CODE (xtype) == BOOLEAN_TYPE)
{
/* We convert a pointer to member function into a boolean,
by just checking the index value, for == 0, we want false, for
!= 0, we want true. */
return convert (xtype, build_component_ref (expr, index_identifier, 0, 0));
}
basetype = TYPE_MAIN_VARIANT (basetype);
if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
return NULL_TREE;
if (TREE_CODE (xtype) == POINTER_TYPE
|| TREE_CODE (xtype) == REFERENCE_TYPE)
/* Do we have an exact match? */
{
tree typename = build_typename_overload (xtype);
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
return build_type_conversion_1 (xtype, basetype, expr, typename,
for_sure);
}
/* Nope; try looking for others. */
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
/* Prepare to match a variant of this type. */
type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type))
n_variants++;
typenames = (tree *)alloca (n_variants * sizeof (tree));
for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
type; n_variants++, type = TYPE_NEXT_VARIANT (type))
if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
continue;
if (can_convert (xtype, TREE_VALUE (conv)))
{
if (type == TREE_TYPE (xtype))
typenames[n_variants] = typename;
else if (TREE_CODE (xtype) == POINTER_TYPE)
typenames[n_variants] = build_typename_overload (build_pointer_type (type));
else
typenames[n_variants] = build_typename_overload (build_reference_type (type));
}
}
save_basetype = basetype;
type = xtype;
while (TYPE_HAS_CONVERSION (basetype))
{
int i;
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
for (i = 0; i < n_variants; i++)
if (typenames[i] != typename
&& lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0))
return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure);
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
#if 0
/* Only reference variable initializations can use a temporary; this
must be handled elsewhere (like convert_to_reference and
compute_conversion_costs). */
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
typename = build_typename_overload (type);
basetype = save_basetype;
/* May need to build a temporary for this. */
while (TYPE_HAS_CONVERSION (basetype))
{
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
if (winner)
{
int flags;
if (for_sure == 0)
flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING;
else
flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
rval = build_method_call (expr,
constructor_name_full (typename),
NULL_TREE, NULL_TREE, flags);
if (rval == error_mark_node)
{
if (for_sure == 0)
return NULL_TREE;
return error_mark_node;
}
return convert (xtype, rval);
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
#endif
/* No free conversions for reference types, right?. */
return NULL_TREE;
}
if (exact_conversion)
return NULL_TREE;
if (TREE_CODE (type) == BOOLEAN_TYPE)
{
tree as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, 0);
tree as_ptr = build_type_conversion (code, ptr_type_node, expr, 0);
/* We are missing the conversion to pointer to member type. */
/* We are missing the conversion to floating type. */
if (as_int && as_ptr && for_sure)
{
cp_error ("ambiguous conversion from `%T' to `bool', can convert to integral type or pointer", TREE_TYPE (expr));
return error_mark_node;
}
if (as_int)
{
as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, for_sure+exact_conversion*2);
return convert (xtype, as_int);
}
if (as_ptr)
{
as_ptr = build_type_conversion (code, ptr_type_node, expr, for_sure+exact_conversion*2);
return convert (xtype, as_ptr);
}
return NULL_TREE;
}
/* No perfect match found, try default. */
#if 0 /* This is wrong; there is no standard conversion from void* to
anything. -jason */
if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE)
type_default = ptr_type_node;
else
#endif
if (type == void_type_node)
return NULL_TREE;
else
{
tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node));
if (tmp == error_mark_node)
return NULL_TREE;
type_default = TREE_TYPE (tmp);
}
basetype = save_basetype;
if (type_default != type)
{
type = type_default;
typename = build_typename_overload (type);
while (TYPE_HAS_CONVERSION (basetype))
{
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
}
if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type)))
{
/* Try converting to some other const pointer type and then using
standard conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
{
if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
return error_mark_node;
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
}
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Try converting to some other pointer type and then using standard
conversions. */
while (TYPE_HAS_CONVERSION (basetype))
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
{
if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
return error_mark_node;
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
}
/* Use the longer or shorter conversion that is appropriate. Have
to check against 0 because the conversion may come from a baseclass. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_HAS_INT_CONVERSION (basetype)
&& CLASSTYPE_CONVERSION (basetype, int_conv) != 0
&& CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node)
{
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
if (TREE_CODE (type) == REAL_TYPE
&& TYPE_HAS_REAL_CONVERSION (basetype)
&& CLASSTYPE_CONVERSION (basetype, real_conv) != 0
&& CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node)
{
/* Only accept using an operator double() if there isn't a conflicting
operator int(). */
if (TYPE_HAS_INT_CONVERSION (basetype))
{
if (for_sure)
{
cp_error ("two possible conversions for type `%T'", type);
return error_mark_node;
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
cp_error (" candidate conversion functions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
return NULL_TREE;
}
else
return NULL_TREE;
}
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv));
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
}
/* THESE ARE TOTAL KLUDGES. */
/* Default promotion yields no new alternatives, try
conversions which are anti-default, such as
double -> float or int -> unsigned or unsigned -> long
*/
if (type_default == type
&& (INTEGRAL_TYPE_P (type) || TREE_CODE (type) == REAL_TYPE))
{
int not_again = 0;
if (type == double_type_node)
typename = build_typename_overload (float_type_node);
else if (type == integer_type_node)
typename = build_typename_overload (unsigned_type_node);
else if (type == unsigned_type_node)
typename = build_typename_overload (long_integer_type_node);
again:
basetype = save_basetype;
while (TYPE_HAS_CONVERSION (basetype))
{
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
if (! not_again)
{
if (type == integer_type_node)
{
typename = build_typename_overload (long_integer_type_node);
not_again = 1;
goto again;
}
else
{
typename = build_typename_overload (integer_type_node);
not_again = 1;
goto again;
}
winner = conv;
}
}
/* Now, try C promotions...
float -> int
int -> float */
basetype = save_basetype;
if (TREE_CODE (type) == REAL_TYPE)
type = integer_type_node;
else if (TREE_CODE (type) == INTEGER_TYPE)
if (TYPE_HAS_REAL_CONVERSION (basetype))
type = double_type_node;
else
return NULL_TREE;
else
return NULL_TREE;
typename = build_typename_overload (type);
while (TYPE_HAS_CONVERSION (basetype))
{
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
{
rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
return rval;
}
if (TYPE_BINFO_BASETYPES (basetype))
basetype = TYPE_BINFO_BASETYPE (basetype, 0);
else
break;
}
if (winner)
return build_type_conversion_1 (xtype, basetype, expr,
TREE_PURPOSE (winner), for_sure);
return NULL_TREE;
}

View File

@ -49,6 +49,8 @@ extern int current_class_depth;
extern tree cleanups_this_call;
extern tree static_ctors, static_dtors;
/* Stack of places to restore the search obstack back to. */
/* Obstack used for remembering local class declarations (like
@ -94,7 +96,11 @@ static struct stack_level *decl_stack;
#endif
#ifndef BOOL_TYPE_SIZE
#ifdef SLOW_BYTE_ACCESS
#define BOOL_TYPE_SIZE BITS_PER_WORD
#else
#define BOOL_TYPE_SIZE BITS_PER_UNIT
#endif
#endif
/* We let tm.h override the types used here, to handle trivial differences
@ -428,7 +434,8 @@ extern int flag_no_builtin;
extern int flag_no_nonansi_builtin;
/* Nonzero means disable GNU extensions. */
/* Nonzero means enable obscure ANSI features and disable GNU extensions
that might cause ANSI-compliant code to be miscompiled. */
extern int flag_ansi;
@ -1638,27 +1645,25 @@ static void
set_nested_typename (decl, classname, name, type)
tree decl, classname, name, type;
{
char *buf;
my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
if (classname != NULL_TREE)
{
char *buf;
my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
+ IDENTIFIER_LENGTH (name));
sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
IDENTIFIER_POINTER (name));
DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
if (classname == NULL_TREE)
classname = get_identifier ("");
/* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
correspondence in any binding_level. This is ok since the
DECL_NESTED_TYPENAME is just a convenience identifier whose
IDENTIFIER_TYPE_VALUE will remain constant from now on. */
SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
}
else
DECL_NESTED_TYPENAME (decl) = name;
my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
+ IDENTIFIER_LENGTH (name));
sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
IDENTIFIER_POINTER (name));
DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
/* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
correspondence in any binding_level. This is ok since the
DECL_NESTED_TYPENAME is just a convenience identifier whose
IDENTIFIER_TYPE_VALUE will remain constant from now on. */
SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
}
/* Pop off extraneous binding levels left over due to syntax errors. */
@ -1743,11 +1748,13 @@ pushtag (name, type, globalize)
context = current_scope ();
if (context)
c_decl = TREE_CODE (context) == FUNCTION_DECL
? context : TYPE_NAME (context);
? context : TYPE_MAIN_DECL (context);
#if 0
/* Record the identifier as the type's name if it has none. */
if (TYPE_NAME (type) == NULL_TREE)
TYPE_NAME (type) = name;
#endif
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
@ -1784,14 +1791,11 @@ pushtag (name, type, globalize)
else
d = TYPE_NAME (d);
TYPE_NAME (type) = d;
/* If it is anonymous, then we are called from pushdecl,
and we don't want to infinitely recurse. Also, if the
name is already in scope, we don't want to push it
again--pushdecl is only for pushing new decls. */
if (! ANON_AGGRNAME_P (name)
&& TYPE_NAME (type)
&& (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
|| lookup_name (name, 1) != TYPE_NAME (type)))
and we don't want to infinitely recurse. */
if (! ANON_AGGRNAME_P (name))
{
if (b->parm_flag == 2)
d = pushdecl_class_level (d);
@ -1815,6 +1819,9 @@ pushtag (name, type, globalize)
DECL_IGNORED_P (d) = 1;
}
#endif /* DWARF_DEBUGGING_INFO */
TYPE_NAME (type) = d;
/* Make sure we're in this type's scope when we push the
decl for a template, otherwise class_binding_level will
be NULL and we'll end up dying inside of
@ -1830,11 +1837,10 @@ pushtag (name, type, globalize)
if (ANON_AGGRNAME_P (name))
DECL_IGNORED_P (d) = 1;
}
TYPE_NAME (type) = d;
if (context == NULL_TREE)
/* Non-nested class. */
DECL_NESTED_TYPENAME (d) = name;
set_nested_typename (d, NULL_TREE, name, type);
else if (context && TREE_CODE (context) == FUNCTION_DECL)
{
/* Function-nested class. */
@ -2036,7 +2042,9 @@ decls_match (newdecl, olddecl)
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
types_match = (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1)
&& TREE_READONLY (newdecl) == TREE_READONLY (olddecl)
&& TREE_THIS_VOLATILE (newdecl) == TREE_THIS_VOLATILE (olddecl));
}
return types_match;
@ -2226,16 +2234,6 @@ duplicate_decls (newdecl, olddecl)
return 0;
}
if (olddecl == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (newdecl))
cp_pedwarn ("redeclaration of wchar_t as `%T'",
TREE_TYPE (newdecl));
/* Throw away the redeclaration. */
return 1;
}
/* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
@ -2281,6 +2279,39 @@ duplicate_decls (newdecl, olddecl)
DECL_LANGUAGE (newdecl));
}
}
if (TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
int i = 1;
if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
for (; t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
{
if (simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
{
if (pedantic)
{
cp_pedwarn ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_pedwarn_at ("after previous specification in `%#D'",
olddecl);
}
}
else
{
cp_error ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_error_at ("conflicts with previous specification in `%#D'",
olddecl);
}
}
}
}
/* If new decl is `static' and an `extern' was seen previously,
@ -2306,6 +2337,8 @@ duplicate_decls (newdecl, olddecl)
DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
}
/* Deal with C++: must preserve virtual function table size. */
@ -2358,13 +2391,10 @@ duplicate_decls (newdecl, olddecl)
{
/* Automatically handles default parameters. */
tree oldtype = TREE_TYPE (olddecl);
/* Merge the data types specified in the two decls. */
tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
tree newtype;
/* Make sure we put the new type in the same obstack as the old ones.
If the old types are not both in the same obstack, use the permanent
one. */
if (oldtype && TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
/* Make sure we put the new type in the same obstack as the old one. */
if (oldtype)
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
{
@ -2372,6 +2402,9 @@ duplicate_decls (newdecl, olddecl)
end_temporary_allocation ();
}
/* Merge the data types specified in the two decls. */
newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
/* Do this after calling `common_type' so that default
@ -2703,6 +2736,14 @@ pushdecl (x)
&& ! DECL_TEMPLATE_IS_CLASS (x)))
&& is_overloaded_fn (t))
/* don't do anything just yet */;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x));
/* Throw away the redeclaration. */
return t;
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
@ -2796,9 +2837,8 @@ pushdecl (x)
}
my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
if (DECL_NAME (name) && !DECL_NESTED_TYPENAME (name))
set_nested_typename (x, current_class_name,
DECL_NAME (name), type);
if (! DECL_NESTED_TYPENAME (x))
set_nested_typename (x, current_class_name, DECL_NAME (x), type);
if (type != error_mark_node
&& TYPE_NAME (type)
@ -2856,11 +2896,11 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x))
TREE_PUBLIC (name) = 1;
/* Don't install a TYPE_DECL if we already have another
sort of _DECL with that name. */
/* Don't install an artificial TYPE_DECL if we already have
another _DECL with that name. */
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| TREE_CODE (t) == TYPE_DECL)
|| ! DECL_ARTIFICIAL (x))
IDENTIFIER_GLOBAL_VALUE (name) = x;
/* Don't forget if the function was used via an implicit decl. */
@ -2892,8 +2932,15 @@ pushdecl (x)
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
IDENTIFIER_LOCAL_VALUE (name) = x;
/* Don't install an artificial TYPE_DECL if we already have
another _DECL with that name. */
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
{
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
IDENTIFIER_LOCAL_VALUE (name) = x;
}
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
@ -2968,11 +3015,25 @@ pushdecl (x)
if (warnstring)
warning (warnstring, IDENTIFIER_POINTER (name));
}
}
/* If storing a local value, there may already be one (inherited).
If so, record it for restoration when this binding level ends. */
if (oldlocal != NULL_TREE)
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
if (TREE_CODE (x) == FUNCTION_DECL)
{
/* 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. */
@ -3168,6 +3229,10 @@ push_class_level_binding (name, x)
tree name;
tree x;
{
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
maybe_push_cache_obstack ();
class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
@ -3251,13 +3316,7 @@ push_overloaded_decl (decl, forgettable)
old = TREE_OPERAND (old, 0);
else
#endif
if (TREE_CODE (old) == VAR_DECL)
{
cp_error_at ("previous non-function declaration `%#D'", old);
cp_error ("conflicts with function declaration `%#D'", decl);
return error_mark_node;
}
else if (TREE_CODE (old) == TYPE_DECL)
if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
{
tree t = TREE_TYPE (old);
if (IS_AGGR_TYPE (t) && warn_shadow)
@ -3272,6 +3331,12 @@ push_overloaded_decl (decl, forgettable)
if (decl == tmp || duplicate_decls (decl, tmp))
return tmp;
}
else
{
cp_error_at ("previous non-function declaration `%#D'", old);
cp_error ("conflicts with function declaration `%#D'", decl);
return error_mark_node;
}
}
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
@ -3386,18 +3451,6 @@ redeclaration_error_message (newdecl, olddecl)
else
return "redefinition of `%#D'";
}
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
for (; t1; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
return "duplicate default arguments given for `%#D'";
}
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@ -3535,6 +3588,9 @@ define_label (filename, line, name)
decl = lookup_label (name);
}
if (name == get_identifier ("wchar_t"))
cp_pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
{
cp_error ("duplicate label `%D'", decl);
@ -3866,9 +3922,9 @@ lookup_nested_type (type, context)
}
break;
case FUNCTION_DECL:
return TYPE_IDENTIFIER (type) ?
lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
break;
if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
return lookup_name (TYPE_IDENTIFIER (type), 1);
return NULL_TREE;
default:
my_friendly_abort (12);
}
@ -3893,43 +3949,50 @@ lookup_name_real (name, prefer_type, nonclass)
{
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
if (prefer_type == -2)
{
extern int looking_for_typename;
tree type;
yylex = 1;
prefer_type = looking_for_typename;
if (got_scope)
type = got_scope;
else
type = got_object;
if (got_scope != NULL_TREE)
if (type)
{
if (got_scope == error_mark_node)
if (type == error_mark_node)
return error_mark_node;
else if (got_scope == void_type_node)
else if (type == void_type_node)
val = IDENTIFIER_GLOBAL_VALUE (name);
else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM
else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
/* TFIXME -- don't do this for UPTs in new model. */
|| TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE)
|| TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
{
if (prefer_type > 0)
val = create_nested_upt (got_scope, name);
val = create_nested_upt (type, name);
else
val = NULL_TREE;
}
else if (! IS_AGGR_TYPE (got_scope))
else if (! IS_AGGR_TYPE (type))
/* Someone else will give an error about this if needed. */
val = NULL_TREE;
else if (TYPE_BEING_DEFINED (got_scope))
else if (TYPE_BEING_DEFINED (type))
{
val = IDENTIFIER_CLASS_VALUE (name);
if (val && DECL_CONTEXT (val) != got_scope)
if (val && DECL_CONTEXT (val) != type)
{
struct binding_level *b = class_binding_level;
for (val = NULL_TREE; b; b = b->level_chain)
{
tree t = purpose_member (name, b->class_shadowed);
if (t && TREE_VALUE (t)
&& DECL_CONTEXT (TREE_VALUE (t)) == got_scope)
&& DECL_CONTEXT (TREE_VALUE (t)) == type)
{
val = TREE_VALUE (t);
break;
@ -3937,16 +4000,23 @@ lookup_name_real (name, prefer_type, nonclass)
}
}
if (val == NULL_TREE
&& CLASSTYPE_LOCAL_TYPEDECLS (got_scope))
val = lookup_field (got_scope, name, 0, 1);
&& CLASSTYPE_LOCAL_TYPEDECLS (type))
val = lookup_field (type, name, 0, 1);
}
else if (got_scope == current_class_type)
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
val = lookup_field (got_scope, name, 0, 0);
goto done;
val = lookup_field (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
if (got_scope)
goto done;
/* This special lookup only applies to types. */
else if (got_object && val && TREE_CODE (val) == TYPE_DECL)
from_obj = val;
}
if (current_binding_level != global_binding_level
@ -3980,16 +4050,20 @@ lookup_name_real (name, prefer_type, nonclass)
done:
if (val)
{
if (from_obj && from_obj != val)
cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope",
got_object);
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
return val;
if (IDENTIFIER_HAS_TYPE_VALUE (name))
return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
if (TREE_TYPE (val) == error_mark_node)
return error_mark_node;
;
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
val = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
else if (TREE_TYPE (val) == error_mark_node)
val = error_mark_node;
}
else if (from_obj)
val = from_obj;
return val;
}
@ -4031,7 +4105,7 @@ lookup_name_current_level (name)
while (1)
{
for (t = b->names; t; t = TREE_CHAIN (t))
if (DECL_NAME (t) == name)
if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
goto out;
if (b->keep == 2)
b = b->level_chain;
@ -4207,13 +4281,19 @@ init_decl_processing ()
int wchar_type_size;
tree temp;
tree array_domain_type;
extern int flag_strict_prototype;
/* Have to make these distinct before we try using them. */
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
if (flag_ansi || pedantic)
strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
if (flag_strict_prototype == 2)
{
if (pedantic)
strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
}
else
strict_prototypes_lang_c = flag_strict_prototype;
/* Initially, C. */
current_lang_name = lang_name_c;
@ -5629,8 +5709,9 @@ grok_reference_init (decl, type, init, cleanupp)
if (init == NULL_TREE)
{
if (DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
{
cp_error ("`%D' declared as reference but not initialized", decl);
if (TREE_CODE (decl) == VAR_DECL)
@ -6530,12 +6611,24 @@ complete_array_type (type, initial_value, do_default)
/* Note MAXINDEX is really the maximum index,
one less than the size. */
if (TREE_CODE (initial_value) == STRING_CST)
maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) - 1, 0);
{
int eltsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
/ eltsize) - 1, 0);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
register int nelts
= list_length (CONSTRUCTOR_ELTS (initial_value));
maxindex = build_int_2 (nelts - 1, - (nelts == 0));
tree elts = CONSTRUCTOR_ELTS (initial_value);
maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
}
maxindex = copy_node (maxindex);
}
else
{
@ -7281,6 +7374,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != CALL_EXPR
&& ! (ctype && declspecs == NULL_TREE))
{
cp_error ("declaration of `%D' as non-function", dname);
return void_type_node;
}
/* Anything declared one level down from the top level
must be one of the parameters of a function
(because the body is at least two levels down). */
@ -7361,8 +7462,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
if (pedantic && flag_ansi)
pedwarn ("duplicate `long'");
if (pedantic && ! in_system_header)
pedwarn ("ANSI C++ does not support `long long'");
else if (longlong)
error ("`long long long' is too long for GCC");
else
@ -7468,7 +7569,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
else if (return_type == return_conversion)
{
if (comp_target_types (type, ctor_return_type, 1) == 0)
if (comptypes (type, ctor_return_type, 1) == 0)
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
@ -8022,7 +8123,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
if (TREE_READONLY_DECL_P (size))
size = decl_constant_value (size);
if (flag_ansi && integer_zerop (size))
if (pedantic && integer_zerop (size))
cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
if (TREE_CONSTANT (size))
{
@ -8037,7 +8138,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
}
else
{
if (flag_ansi)
if (pedantic)
{
if (dname)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
@ -8384,9 +8485,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
&& (constp || volatilep))
{
if (constp)
warning ("discarding `const' applied to a reference");
pedwarn ("discarding `const' applied to a reference");
if (volatilep)
warning ("discarding `volatile' applied to a reference");
pedwarn ("discarding `volatile' applied to a reference");
constp = volatilep = 0;
}
}
@ -8956,7 +9057,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
initialize the named nonstatic member.... This (or an
initializer list) is the only way to initialize
nonstatic const and reference members. */
else if (flag_ansi || ! constp)
else if (pedantic || ! constp)
cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
constp ? "const member" : "member", declarator);
}
@ -9103,7 +9204,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
current_extern_inline = 1;
if (flag_ansi)
if (pedantic)
pedwarn ("ANSI C++ does not permit `extern inline'");
}
}
@ -9450,12 +9551,19 @@ grokparms (first_parm, funcdef_flag)
}
else
init = require_instantiated_type (type, init, integer_zero_node);
init = convert_for_initialization
(NULL_TREE, type, init, LOOKUP_NORMAL,
"argument passing", 0, 0);
}
#if 0 /* This is too early to check; trailing parms might be merged in by
duplicate_decls. */
else if (any_init)
{
error ("all trailing parameters must have default arguments");
any_error = 1;
}
#endif
}
else
init = NULL_TREE;
@ -11042,7 +11150,7 @@ store_return_init (return_id, init)
{
tree decl = DECL_RESULT (current_function_decl);
if (flag_ansi)
if (pedantic)
/* Give this error as many times as there are occurrences,
so that users can use Emacs compilation buffers to find
and fix all such places. */
@ -11539,45 +11647,11 @@ finish_function (lineno, call_poplevel, nested)
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
if (DECL_EXTERNAL (fndecl)
/* This function is just along for the ride. If we can make
it inline, that's great. Otherwise, just punt it. */
&& (DECL_INLINE (fndecl) == 0
|| flag_no_inline
|| function_cannot_inline_p (fndecl)
/* ??? Compensate for Sun brain damage in dealing with
data segments of PIC code. */
|| (flag_pic
&& (DECL_CONSTRUCTOR_P (fndecl)
|| DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
&& CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))))
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
{
extern int rtl_dump_and_exit;
int old_rtl_dump_and_exit = rtl_dump_and_exit;
int inline_spec = DECL_INLINE (fndecl);
/* This throws away the code for FNDECL. */
rtl_dump_and_exit = 1;
/* This throws away the memory of the code for FNDECL. */
if (flag_no_inline)
DECL_INLINE (fndecl) = 0;
rest_of_compilation (fndecl);
rtl_dump_and_exit = old_rtl_dump_and_exit;
DECL_INLINE (fndecl) = inline_spec;
}
else
{
/* Run the optimizers and output the assembler code for this
function. */
rest_of_compilation (fndecl);
}
if (DECL_INLINE (fndecl) && !TREE_ASM_WRITTEN (fndecl)
&& DECL_DEFER_OUTPUT (fndecl))
{
mark_inline_for_output (fndecl);
}
if (DECL_DEFER_OUTPUT (fndecl))
mark_inline_for_output (fndecl);
if (ctype && TREE_ASM_WRITTEN (fndecl))
note_debug_info_needed (ctype);
@ -11628,6 +11702,11 @@ finish_function (lineno, call_poplevel, nested)
DECL_ARGUMENTS (fndecl) = NULL_TREE;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
if (DECL_STATIC_DESTRUCTOR (fndecl))
static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
/* Let the error reporting routines know that we're outside a function. */
current_function_decl = NULL_TREE;
named_label_uses = NULL_TREE;

View File

@ -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 ();

View File

@ -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
text_section ();
if (flag_pic)
data_section ();
else
#if defined(__rs6000)
data_section ();
#else
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);
@ -812,6 +838,11 @@ init_exception_processing ()
saved_pc = gen_rtx (REG, Pmode, 16);
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);
@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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. */

View File

@ -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");

View File

@ -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)

View File

@ -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;
}

View File

@ -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--;

View File

@ -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;

View File

@ -202,9 +202,6 @@ commonparms (p1, p2)
{
if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2))
{
/* We used to give a warning here that advised about a default
argument being given in the prototype but not in the function's
declaration. It's best not to bother. */
TREE_PURPOSE (n) = TREE_PURPOSE (p1);
any_change = 1;
}
@ -352,6 +349,11 @@ common_type (t1, t2)
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
return build_type_attribute_variant (long_double_type_node,
attributes);
/* Otherwise prefer the unsigned one. */
if (TREE_UNSIGNED (t1))
@ -445,9 +447,12 @@ common_type (t1, t2)
my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1
&& TYPE_MAIN_VARIANT (t2) == t2, 306);
if (! binfo_or_else (t1, t2))
compiler_error ("common_type called with uncommon aggregate types");
return build_type_attribute_variant (t1, attributes);
if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))
return build_type_attribute_variant (t1, attributes);
else if (binfo_or_else (t2, t1))
return build_type_attribute_variant (t2, attributes);
else
compiler_error ("common_type called with uncommon aggregate types");
case METHOD_TYPE:
if (comptypes (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), 1)
@ -761,9 +766,7 @@ comp_target_types (ttl, ttr, nptrs)
case 1:
return 1;
case 2:
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl);
return 1;
return -1;
default:
my_friendly_abort (112);
}
@ -780,17 +783,17 @@ comp_target_types (ttl, ttr, nptrs)
return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0)
&& comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
{
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl);
return 1;
}
return -1;
}
else if (IS_AGGR_TYPE (ttl))
{
if (nptrs < 0)
return 0;
return comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0);
if (comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0))
return 1;
if (comptypes (TYPE_POINTER_TO (ttr), TYPE_POINTER_TO (ttl), 0))
return -1;
return 0;
}
return 0;
@ -1223,7 +1226,7 @@ c_sizeof_nowarn (type)
/* Convert in case a char is more than one unit. */
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
size_int (TYPE_PRECISION (char_type_node)));
size_int (TYPE_PRECISION (char_type_node)));
force_fit_type (t, 0);
return t;
}
@ -1665,7 +1668,14 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
}
else
return build (COMPONENT_REF, unknown_type_node, datum, fndecls);
{
/* Just act like build_offset_ref, since the object does
not matter unless we're actually calling the function. */
tree t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype,
unknown_type_node);
return t;
}
}
#if 0
@ -2187,12 +2197,13 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree index = save_expr (convert (integer_type_node,
build_component_ref (function,
index_identifier,
0, 0)));
tree e1 = build (GT_EXPR, integer_type_node, index, integer_zero_node);
tree delta = build_component_ref (function, delta_identifier, 0, 0);
tree index = save_expr (build_component_ref (function,
index_identifier,
0, 0));
tree e1 = build (GT_EXPR, delta_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;
@ -2208,11 +2219,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
vtbl
= build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
vtbl, convert (sizetype, delta2));
vtbl, convert (ptrdiff_type_node, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, size_binop (MINUS_EXPR,
index,
integer_one_node));
aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
index,
integer_one_node, 1));
if (! flag_vtable_thunks)
{
aref = save_expr (aref);
@ -2222,14 +2233,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF)
TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
delta = build (PLUS_EXPR, integer_type_node,
build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
delta);
delta = build_binary_op (PLUS_EXPR,
build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
delta, 1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr),
*instance_ptrptr,
convert (integer_type_node, delta));
delta);
if (flag_vtable_thunks)
e2 = aref;
else
@ -3162,7 +3173,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree delta21 = DELTA2_FROM_PTRMEMFUNC (op1);
tree e1, e2, e3;
tree integer_neg_one_node
= size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
= build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
@ -3183,7 +3194,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree delta21 = integer_zero_node;
tree e1, e2, e3;
tree integer_neg_one_node
= size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
= build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (op1, 0)))
{
@ -3828,9 +3839,17 @@ build_unary_op (code, xarg, noconvert)
errstring = "wrong type argument to unary plus";
else if (!noconvert)
arg = default_conversion (arg);
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
break;
case NEGATE_EXPR:
if (typecode == OFFSET_TYPE)
{
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
if (!noconvert)
@ -3852,6 +3871,13 @@ build_unary_op (code, xarg, noconvert)
break;
case BIT_NOT_EXPR:
if (typecode == OFFSET_TYPE)
{
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
if (!noconvert)
@ -3873,6 +3899,13 @@ build_unary_op (code, xarg, noconvert)
break;
case ABS_EXPR:
if (typecode == OFFSET_TYPE)
{
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
if (!noconvert)
@ -3917,6 +3950,13 @@ build_unary_op (code, xarg, noconvert)
/* Report invalid types. */
if (typecode == OFFSET_TYPE)
{
arg = resolve_offset_ref (arg);
typecode = TREE_CODE (TREE_TYPE (arg));
isaggrtype = IS_AGGR_TYPE_CODE (typecode);
}
if (isaggrtype)
{
arg = default_conversion (arg);
@ -4012,9 +4052,6 @@ build_unary_op (code, xarg, noconvert)
}
}
if (TREE_CODE (arg) == OFFSET_REF)
arg = resolve_offset_ref (arg);
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@ -4244,7 +4281,9 @@ unary_complex_lvalue (code, arg)
if (TREE_CODE (arg) == COND_EXPR)
return rationalize_conditional_expr (code, arg);
if (TREE_CODE (arg) == MODIFY_EXPR)
if (TREE_CODE (arg) == MODIFY_EXPR
|| TREE_CODE (arg) == PREINCREMENT_EXPR
|| TREE_CODE (arg) == PREDECREMENT_EXPR)
return unary_complex_lvalue
(code, build (COMPOUND_EXPR, TREE_TYPE (TREE_OPERAND (arg, 0)),
arg, TREE_OPERAND (arg, 0)));
@ -4499,7 +4538,7 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
ifexp = bool_truthvalue_conversion (default_conversion (ifexp));
ifexp = bool_truthvalue_conversion (ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
@ -5780,8 +5819,7 @@ build_modify_expr (lhs, modifycode, rhs)
int from_array;
/* Allow array assignment in compiler-generated code. */
if ((pedantic || flag_ansi)
&& ! DECL_ARTIFICIAL (current_function_decl))
if (pedantic && ! DECL_ARTIFICIAL (current_function_decl))
pedwarn ("ANSI C++ forbids assignment of arrays");
/* Have to wrap this in RTL_EXPR for two cases:
@ -6010,9 +6048,9 @@ get_delta_difference (from, to, force)
{
warning ("pointer to member conversion to virtual base class will only work if your very careful");
}
return fold (size_binop (MINUS_EXPR,
integer_zero_node,
BINFO_OFFSET (binfo)));
return build_binary_op (MINUS_EXPR,
integer_zero_node,
BINFO_OFFSET (binfo), 1);
}
if (TREE_VIA_VIRTUAL (binfo))
{
@ -6069,14 +6107,14 @@ build_ptrmemfunc (type, pfn, force)
if (TREE_CODE (pfn) != CONSTRUCTOR)
{
tree e1, e2, e3;
ndelta = convert (sizetype, build_component_ref (pfn, delta_identifier, 0, 0));
ndelta2 = convert (sizetype, DELTA2_FROM_PTRMEMFUNC (pfn));
ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, 0, 0));
ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
index = build_component_ref (pfn, index_identifier, 0, 0);
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta = fold (size_binop (PLUS_EXPR, delta, ndelta));
delta2 = fold (size_binop (PLUS_EXPR, ndelta2, delta2));
delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
e1 = fold (build (GT_EXPR, integer_type_node, index, integer_zero_node));
u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
@ -6136,7 +6174,7 @@ build_ptrmemfunc (type, pfn, force)
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta2 = fold (size_binop (PLUS_EXPR, delta2, delta));
delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
warning ("assuming pointer to member function is non-virtual");
@ -6159,7 +6197,7 @@ build_ptrmemfunc (type, pfn, force)
}
else
{
index = fold (size_binop (MINUS_EXPR, integer_zero_node, integer_one_node));
index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
npfn = build1 (NOP_EXPR, type, pfn);
TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
@ -6306,6 +6344,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
{
register tree ttl = TREE_TYPE (type);
register tree ttr;
int ctt = 0;
if (coder == RECORD_TYPE)
{
@ -6358,7 +6397,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| comp_target_types (type, rhstype, 1)
|| (ctt = comp_target_types (type, rhstype, 1))
|| (unsigned_type (TYPE_MAIN_VARIANT (ttl))
== unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
@ -6366,17 +6405,21 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
&& TREE_CODE (ttr) == OFFSET_TYPE)
{
error ("no standard conversion from pointer to member to `void *'");
cp_error ("no standard conversion from `%T' to `void *'", ttr);
return error_mark_node;
}
if (ctt < 0)
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node
&& rhs != null_pointer_node)
{
if (coder == RECORD_TYPE)
pedwarn ("implicit conversion of signature pointer to type `%s'",
type_as_string (type, 0));
cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
type);
else
pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
errtype);
@ -6481,7 +6524,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
ttl = unsigned_type (ttl);
}
if (comp_target_types (ttl, ttr, nptrs))
if (comp_target_types (ttl, ttr, nptrs) > 0)
{
if (add_quals)
{
@ -6585,7 +6628,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
return null_pointer_node;
}
else if ((codel == INTEGER_TYPE || codel == BOOLEAN_TYPE)
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
|| (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
@ -6600,6 +6643,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
errtype, type, rhstype);
return convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE
&& (coder == POINTER_TYPE
|| (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
return convert (type, rhs);
/* C++ */
else if (((coder == POINTER_TYPE && TREE_CODE (rhs) == ADDR_EXPR