parent
43238b97ad
commit
e1cd6e56ad
375
gcc/cp/ChangeLog
375
gcc/cp/ChangeLog
|
@ -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>
|
||||
|
||||
|
|
171
gcc/cp/call.c
171
gcc/cp/call.c
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
261
gcc/cp/class.c
261
gcc/cp/class.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
358
gcc/cp/cvt.c
358
gcc/cp/cvt.c
|
@ -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;
|
||||
}
|
||||
|
|
401
gcc/cp/decl.c
401
gcc/cp/decl.c
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
102
gcc/cp/except.c
102
gcc/cp/except.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ __headof__, HEADOF, NORID
|
|||
__inline, SCSPEC, RID_INLINE
|
||||
__inline__, SCSPEC, RID_INLINE
|
||||
__label__, LABEL, NORID
|
||||
__signature__, AGGR, RID_SIGNATURE /* Extension */,
|
||||
__signed, TYPESPEC, RID_SIGNED
|
||||
__signed__, TYPESPEC, RID_SIGNED
|
||||
__sigof__, SIGOF, NORID /* Extension */,
|
||||
__typeof, TYPEOF, NORID
|
||||
__typeof__, TYPEOF, NORID
|
||||
__volatile, TYPE_QUAL, RID_VOLATILE
|
||||
|
|
|
@ -2376,9 +2376,9 @@ add_friend (type, decl)
|
|||
{
|
||||
if (decl == TREE_VALUE (friends))
|
||||
{
|
||||
cp_pedwarn ("`%D' is already a friend of class `%T'",
|
||||
cp_warning ("`%D' is already a friend of class `%T'",
|
||||
decl, type);
|
||||
cp_pedwarn_at ("previous friend declaration of `%D'",
|
||||
cp_warning_at ("previous friend declaration of `%D'",
|
||||
TREE_VALUE (friends));
|
||||
return;
|
||||
}
|
||||
|
@ -2948,12 +2948,15 @@ build_new (placement, decl, init, use_global_new)
|
|||
else
|
||||
size = size_in_bytes (type);
|
||||
|
||||
if (true_type == void_type_node)
|
||||
{
|
||||
error ("invalid type for new: `void'");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (TYPE_SIZE (true_type) == 0)
|
||||
{
|
||||
if (true_type == void_type_node)
|
||||
error ("invalid type for new: `void'");
|
||||
else
|
||||
incomplete_type_error (0, true_type);
|
||||
incomplete_type_error (0, true_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
|
|
33
gcc/cp/lex.c
33
gcc/cp/lex.c
|
@ -403,6 +403,8 @@ void
|
|||
init_lex ()
|
||||
{
|
||||
extern char *(*decl_printable_name) ();
|
||||
extern int flag_no_gnu_keywords;
|
||||
extern int flag_operator_names;
|
||||
|
||||
int i;
|
||||
|
||||
|
@ -788,23 +790,21 @@ init_lex ()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (! (flag_gc || flag_rtti))
|
||||
if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
|
||||
{
|
||||
UNSET_RESERVED_WORD ("classof");
|
||||
UNSET_RESERVED_WORD ("headof");
|
||||
}
|
||||
if (! flag_handle_signatures)
|
||||
if (! flag_handle_signatures || flag_no_gnu_keywords)
|
||||
{
|
||||
/* Easiest way to not recognize signature
|
||||
handling extensions... */
|
||||
UNSET_RESERVED_WORD ("signature");
|
||||
UNSET_RESERVED_WORD ("sigof");
|
||||
}
|
||||
if (flag_no_asm)
|
||||
UNSET_RESERVED_WORD ("asm");
|
||||
if (flag_no_asm || flag_traditional)
|
||||
if (flag_no_asm || flag_no_gnu_keywords)
|
||||
UNSET_RESERVED_WORD ("typeof");
|
||||
if (!flag_ansi)
|
||||
if (! flag_operator_names)
|
||||
{
|
||||
/* These are new ANSI keywords that may break code. */
|
||||
UNSET_RESERVED_WORD ("and");
|
||||
|
@ -815,6 +815,8 @@ init_lex ()
|
|||
UNSET_RESERVED_WORD ("or");
|
||||
UNSET_RESERVED_WORD ("xor");
|
||||
}
|
||||
if (! flag_traditional)
|
||||
UNSET_RESERVED_WORD ("overload");
|
||||
|
||||
token_count = init_parse ();
|
||||
interface_unknown = 1;
|
||||
|
@ -4211,7 +4213,7 @@ real_yylex ()
|
|||
goto tryagain;
|
||||
if (width < HOST_BITS_PER_INT
|
||||
&& (unsigned) c >= (1 << width))
|
||||
pedwarn ("escape sequence out of range for character");
|
||||
warning ("escape sequence out of range for character");
|
||||
#ifdef MAP_CHARACTER
|
||||
if (isprint (c))
|
||||
c = MAP_CHARACTER (c);
|
||||
|
@ -4328,7 +4330,7 @@ real_yylex ()
|
|||
if (!wide_flag
|
||||
&& TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
|
||||
&& c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
|
||||
pedwarn ("escape sequence out of range for character");
|
||||
warning ("escape sequence out of range for character");
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
|
@ -4483,7 +4485,7 @@ real_yylex ()
|
|||
}
|
||||
else if ((c == '-') && (c1 == '>'))
|
||||
{
|
||||
nextchar = skip_white_space (getch ());
|
||||
nextchar = getch ();
|
||||
if (nextchar == '*')
|
||||
{
|
||||
nextchar = -1;
|
||||
|
@ -4510,11 +4512,22 @@ real_yylex ()
|
|||
value = MIN_MAX;
|
||||
nextchar = c1;
|
||||
}
|
||||
if (flag_ansi)
|
||||
if (pedantic)
|
||||
pedwarn ("use of `operator %s' is not standard C++",
|
||||
token_buffer);
|
||||
goto done;
|
||||
}
|
||||
/* digraphs */
|
||||
else if (c == '<' && c1 == '%')
|
||||
{ value = '{'; goto done; }
|
||||
else if (c == '<' && c1 == ':')
|
||||
{ value = '['; goto done; }
|
||||
else if (c == '%' && c1 == '>')
|
||||
{ value = '}'; goto done; }
|
||||
else if (c == '%' && c1 == ':')
|
||||
{ value = '#'; goto done; }
|
||||
else if (c == ':' && c1 == '>')
|
||||
{ value = ']'; goto done; }
|
||||
|
||||
nextchar = c1;
|
||||
token_buffer[1] = 0;
|
||||
|
|
|
@ -123,6 +123,7 @@ extern int looking_for_template;
|
|||
|
||||
/* Tell the lexer where to look for names. */
|
||||
extern tree got_scope;
|
||||
extern tree got_object;
|
||||
|
||||
/* Pending language change.
|
||||
Positive is push count, negative is pop count. */
|
||||
|
|
|
@ -1246,7 +1246,8 @@ expr_no_commas:
|
|||
| expr_no_commas '?' xexpr ':' expr_no_commas
|
||||
{ $$ = build_x_conditional_expr ($$, $3, $5); }
|
||||
| expr_no_commas '=' expr_no_commas
|
||||
{ $$ = build_modify_expr ($$, NOP_EXPR, $3); }
|
||||
{ $$ = build_modify_expr ($$, NOP_EXPR, $3);
|
||||
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
|
||||
| expr_no_commas ASSIGN expr_no_commas
|
||||
{ register tree rval;
|
||||
if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
|
||||
|
@ -1333,7 +1334,12 @@ primary:
|
|||
| string
|
||||
{ $$ = combine_strings ($$); }
|
||||
| '(' expr ')'
|
||||
{ $$ = $2; }
|
||||
{ char class = TREE_CODE_CLASS (TREE_CODE ($2));
|
||||
if (class == 'e' || class == '1'
|
||||
|| class == '2' || class == '<')
|
||||
/* This inhibits warnings in truthvalue_conversion. */
|
||||
C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
|
||||
$$ = $2; }
|
||||
| '(' error ')'
|
||||
{ $$ = error_mark_node; }
|
||||
| '('
|
||||
|
@ -1538,11 +1544,14 @@ primary:
|
|||
| overqualified_id LEFT_RIGHT
|
||||
{ $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
|
||||
| object unqualified_id %prec UNARY
|
||||
{ $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
|
||||
{ got_object = NULL_TREE;
|
||||
$$ = build_component_ref ($$, $2, NULL_TREE, 1); }
|
||||
| object qualified_id %prec UNARY
|
||||
{ $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
|
||||
{ got_object = NULL_TREE;
|
||||
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
|
||||
| object unqualified_id '(' nonnull_exprlist ')'
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
#if 0
|
||||
/* This is a future direction of this code, but because
|
||||
build_x_function_call cannot always undo what is done
|
||||
|
@ -1558,6 +1567,7 @@ primary:
|
|||
}
|
||||
| object unqualified_id LEFT_RIGHT
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
#if 0
|
||||
/* This is a future direction of this code, but because
|
||||
build_x_function_call cannot always undo what is done
|
||||
|
@ -1573,6 +1583,7 @@ primary:
|
|||
}
|
||||
| object qualified_id '(' nonnull_exprlist ')'
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
|
||||
{
|
||||
warning ("signature name in scope resolution ignored");
|
||||
|
@ -1584,6 +1595,7 @@ primary:
|
|||
}
|
||||
| object qualified_id LEFT_RIGHT
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
|
||||
{
|
||||
warning ("signature name in scope resolution ignored");
|
||||
|
@ -1595,14 +1607,16 @@ primary:
|
|||
}
|
||||
/* p->int::~int() is valid -- 12.4 */
|
||||
| object '~' TYPESPEC LEFT_RIGHT
|
||||
{
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
if (TREE_CODE (TREE_TYPE ($1))
|
||||
!= TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
|
||||
cp_error ("`%E' is not of type `%T'", $1, $3);
|
||||
$$ = convert (void_type_node, $1);
|
||||
}
|
||||
| object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
|
||||
{
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
if ($2 != $5)
|
||||
cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
|
||||
if (TREE_CODE (TREE_TYPE ($1))
|
||||
|
@ -1610,6 +1624,11 @@ primary:
|
|||
cp_error ("`%E' is not of type `%T'", $1, $2);
|
||||
$$ = convert (void_type_node, $1);
|
||||
}
|
||||
| object error
|
||||
{
|
||||
got_object = NULL_TREE;
|
||||
$$ = error_mark_node;
|
||||
}
|
||||
;
|
||||
|
||||
/* Not needed for now.
|
||||
|
@ -1690,9 +1709,11 @@ nodecls:
|
|||
;
|
||||
|
||||
object: primary '.'
|
||||
{ got_object = TREE_TYPE ($$); }
|
||||
| primary POINTSAT
|
||||
{
|
||||
$$ = build_x_arrow ($$);
|
||||
$$ = build_x_arrow ($$);
|
||||
got_object = TREE_TYPE ($$);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -3288,7 +3309,7 @@ simple_stmt:
|
|||
else if (success == 2)
|
||||
{
|
||||
cp_error ("duplicate case value `%E'", $2);
|
||||
cp_error_at ("`%E' previously used here", duplicate);
|
||||
cp_error_at ("previously used here", duplicate);
|
||||
}
|
||||
else if (success == 3)
|
||||
warning ("case value out of range");
|
||||
|
|
|
@ -1257,6 +1257,8 @@ tsubst (t, args, nargs, in_decl)
|
|||
type = newtype;
|
||||
|
||||
fnargs = copy_node (DECL_ARGUMENTS (t));
|
||||
TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
|
||||
|
||||
/* In this case we need "in-charge" flag saying whether
|
||||
this constructor is responsible for initialization
|
||||
of virtual baseclasses or not. */
|
||||
|
@ -1419,7 +1421,7 @@ tsubst (t, args, nargs, in_decl)
|
|||
r = build_lang_decl (FUNCTION_DECL, r, type);
|
||||
DECL_ASSEMBLER_NAME (r) = a;
|
||||
}
|
||||
else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r))
|
||||
else if (TREE_STATIC (r))
|
||||
{
|
||||
/* This overrides the template version, use it. */
|
||||
return r;
|
||||
|
@ -1718,7 +1720,7 @@ instantiate_template (tmpl, targ_ptr)
|
|||
|
||||
/* If we have a preexisting version of this function, don't expand
|
||||
the template version, use the other instead. */
|
||||
if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))
|
||||
if (TREE_STATIC (fndecl))
|
||||
{
|
||||
SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
|
||||
p = (struct pending_inline *)0;
|
||||
|
@ -2448,7 +2450,7 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
{
|
||||
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
|
||||
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
|
||||
int i, dummy;
|
||||
int i, dummy = 0;
|
||||
i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
|
||||
TYPE_ARG_TYPES (TREE_TYPE (fn)),
|
||||
TYPE_ARG_TYPES (TREE_TYPE (decl)),
|
||||
|
@ -2460,6 +2462,7 @@ do_function_instantiation (declspecs, declarator, storage)
|
|||
else
|
||||
result = instantiate_template (fn, targs);
|
||||
}
|
||||
free (targs);
|
||||
}
|
||||
}
|
||||
if (! result)
|
||||
|
|
137
gcc/cp/search.c
137
gcc/cp/search.c
|
@ -1089,18 +1089,29 @@ lookup_field (xbasetype, name, protect, want_type)
|
|||
entry = 0;
|
||||
|
||||
rval = lookup_field_1 (type, name);
|
||||
if (rval || lookup_fnfields_here (type, name)>=0)
|
||||
{
|
||||
rval_binfo = basetype_path;
|
||||
rval_binfo_h = rval_binfo;
|
||||
}
|
||||
|
||||
if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
|
||||
rval = NULL_TREE;
|
||||
|
||||
if (rval)
|
||||
if (rval || lookup_fnfields_here (type, name) >= 0)
|
||||
{
|
||||
if (protect)
|
||||
if (rval)
|
||||
{
|
||||
if (want_type)
|
||||
{
|
||||
if (TREE_CODE (rval) != TYPE_DECL)
|
||||
{
|
||||
rval = purpose_member (name, CLASSTYPE_TAGS (type));
|
||||
if (rval)
|
||||
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TREE_CODE (rval) == TYPE_DECL
|
||||
&& lookup_fnfields_here (type, name) >= 0)
|
||||
rval = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
if (protect && rval)
|
||||
{
|
||||
if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
|
||||
this_v = compute_access (basetype_path, rval);
|
||||
|
@ -1259,12 +1270,33 @@ lookup_field (xbasetype, name, protect, want_type)
|
|||
if (entry)
|
||||
TREE_VALUE (entry) = rval;
|
||||
|
||||
if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL))
|
||||
if (rval_binfo)
|
||||
{
|
||||
rval = NULL_TREE;
|
||||
errstr = 0;
|
||||
type = BINFO_TYPE (rval_binfo);
|
||||
|
||||
if (rval)
|
||||
{
|
||||
if (want_type)
|
||||
{
|
||||
if (TREE_CODE (rval) != TYPE_DECL)
|
||||
{
|
||||
rval = purpose_member (name, CLASSTYPE_TAGS (type));
|
||||
if (rval)
|
||||
rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TREE_CODE (rval) == TYPE_DECL
|
||||
&& lookup_fnfields_here (type, name) >= 0)
|
||||
rval = NULL_TREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rval == NULL_TREE)
|
||||
errstr = 0;
|
||||
|
||||
/* If this FIELD_DECL defines its own access level, deal with that. */
|
||||
if (rval && errstr == 0
|
||||
&& ((protect&1) || entry)
|
||||
|
@ -1948,11 +1980,51 @@ get_matching_virtual (binfo, fndecl, dtorp)
|
|||
== TYPE_READONLY (instptr_type))
|
||||
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
|
||||
{
|
||||
if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
|
||||
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
|
||||
tree brettype = TREE_TYPE (TREE_TYPE (tmp));
|
||||
if (comptypes (brettype, drettype, 1))
|
||||
/* OK */;
|
||||
else if
|
||||
(TREE_CODE (brettype) == TREE_CODE (drettype)
|
||||
&& (TREE_CODE (brettype) == POINTER_TYPE
|
||||
|| TREE_CODE (brettype) == REFERENCE_TYPE)
|
||||
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)),
|
||||
TYPE_MAIN_VARIANT (TREE_TYPE (drettype)),
|
||||
0))
|
||||
/* covariant return type */
|
||||
{
|
||||
tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype);
|
||||
if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d))
|
||||
{
|
||||
tree binfo = get_binfo (b, d, 1);
|
||||
if (binfo != error_mark_node
|
||||
&& ! BINFO_OFFSET_ZEROP (binfo))
|
||||
sorry ("adjusting pointers for covariant returns");
|
||||
}
|
||||
if (TYPE_READONLY (d) > TYPE_READONLY (b))
|
||||
{
|
||||
cp_error ("return type of `%#D' adds const", fndecl);
|
||||
cp_error_at (" overriding definition as `%#D'",
|
||||
tmp);
|
||||
}
|
||||
else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
|
||||
{
|
||||
cp_error ("return type of `%#D' adds volatile",
|
||||
fndecl);
|
||||
cp_error_at (" overriding definition as `%#D'",
|
||||
tmp);
|
||||
}
|
||||
}
|
||||
else if (IS_AGGR_TYPE_2 (brettype, drettype)
|
||||
&& comptypes (brettype, drettype, 0))
|
||||
{
|
||||
error ("invalid covariant return type (must use pointer or reference)");
|
||||
cp_error_at (" overriding `%#D'", tmp);
|
||||
cp_error (" with `%#D'", fndecl);
|
||||
}
|
||||
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
|
||||
{
|
||||
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
|
||||
cp_error_at ("overriding definition as `%#D'", tmp);
|
||||
cp_error_at (" overriding definition as `%#D'", tmp);
|
||||
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
|
||||
}
|
||||
break;
|
||||
|
@ -2192,7 +2264,7 @@ dfs_walk (binfo, fn, qfn)
|
|||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
|
||||
if ((*qfn)(base_binfo))
|
||||
if (qfn == 0 || (*qfn)(base_binfo))
|
||||
{
|
||||
if (fn == dfs_init_vbase_pointers)
|
||||
{
|
||||
|
@ -2800,8 +2872,14 @@ dfs_pushdecls (binfo)
|
|||
? DECL_CLASS_CONTEXT (value)
|
||||
: DECL_CONTEXT (value);
|
||||
|
||||
if (context && (context == type
|
||||
|| TYPE_DERIVES_FROM (context, type)))
|
||||
if (context == type)
|
||||
{
|
||||
if (TREE_CODE (value) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (value))
|
||||
value = fields;
|
||||
/* else the old value wins */
|
||||
}
|
||||
else if (context && TYPE_DERIVES_FROM (context, type))
|
||||
value = fields;
|
||||
else
|
||||
value = tree_cons (NULL_TREE, fields,
|
||||
|
@ -3210,3 +3288,24 @@ reinit_search_statistics ()
|
|||
n_outer_fields_searched = 0;
|
||||
n_contexts_saved = 0;
|
||||
}
|
||||
|
||||
static tree conversions;
|
||||
static void
|
||||
add_conversions (binfo)
|
||||
tree binfo;
|
||||
{
|
||||
tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
|
||||
for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
|
||||
tmp = TREE_CHAIN (tmp))
|
||||
conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
|
||||
conversions);
|
||||
}
|
||||
|
||||
tree
|
||||
lookup_conversions (type)
|
||||
tree type;
|
||||
{
|
||||
conversions = NULL_TREE;
|
||||
dfs_walk (TYPE_BINFO (type), add_conversions, 0);
|
||||
return conversions;
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@ int looking_for_template;
|
|||
|
||||
extern struct obstack *current_obstack, *saveable_obstack;
|
||||
tree got_scope;
|
||||
tree got_object;
|
||||
|
||||
int
|
||||
yylex()
|
||||
|
@ -316,7 +317,7 @@ yylex()
|
|||
if (lastiddecl != trrr)
|
||||
{
|
||||
lastiddecl = trrr;
|
||||
if (got_scope)
|
||||
if (got_scope || got_object)
|
||||
tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
|
||||
}
|
||||
break;
|
||||
|
@ -334,8 +335,11 @@ yylex()
|
|||
lastiddecl = trrr;
|
||||
got_scope = NULL_TREE;
|
||||
/* and fall through to... */
|
||||
case IDENTIFIER_DEFN:
|
||||
case TYPENAME:
|
||||
case TYPENAME_DEFN:
|
||||
case PTYPENAME:
|
||||
case PTYPENAME_DEFN:
|
||||
consume_token ();
|
||||
if (looking_for_typename > 0)
|
||||
looking_for_typename--;
|
||||
|
|
|
@ -102,6 +102,11 @@ lvalue_p (ref)
|
|||
|
||||
case COMPOUND_EXPR:
|
||||
return lvalue_p (TREE_OPERAND (ref, 1));
|
||||
|
||||
case MAX_EXPR:
|
||||
case MIN_EXPR:
|
||||
return (lvalue_p (TREE_OPERAND (ref, 0))
|
||||
&& lvalue_p (TREE_OPERAND (ref, 1)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -570,9 +575,13 @@ layout_vbasetypes (rec, max)
|
|||
BINFO_OFFSET (vbase_types) = offset;
|
||||
|
||||
if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
|
||||
const_size += MAX (BITS_PER_UNIT,
|
||||
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
|
||||
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
|
||||
{
|
||||
/* Every virtual baseclass takes a least a UNIT, so that we can
|
||||
take it's address and get something different for each base. */
|
||||
const_size += MAX (BITS_PER_UNIT,
|
||||
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
|
||||
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
|
||||
}
|
||||
else if (var_size == 0)
|
||||
var_size = TYPE_SIZE (basetype);
|
||||
else
|
||||
|
@ -581,6 +590,15 @@ layout_vbasetypes (rec, max)
|
|||
vbase_types = TREE_CHAIN (vbase_types);
|
||||
}
|
||||
|
||||
if (const_size)
|
||||
{
|
||||
/* Because a virtual base might take a single byte above,
|
||||
we have to re-adjust the total size to make sure it it
|
||||
a multiple of the alignment. */
|
||||
/* Give the whole object the alignment it wants. */
|
||||
const_size = CEIL (const_size, record_align) * record_align;
|
||||
}
|
||||
|
||||
/* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN
|
||||
here, as that is for this class, without any virtual base classes. */
|
||||
TYPE_ALIGN (rec) = record_align;
|
||||
|
|
160
gcc/cp/typeck.c
160
gcc/cp/typeck.c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue