diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1994-05-19 20:19:03 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1994-05-19 20:19:03 +0000 |
commit | bb0726a148f7adef1517311f8a5037cb525e0f39 (patch) | |
tree | 6821be58065899a0af95c7612b289e6fe83ca054 | |
parent | dd0637857dcaec160c42e0bf1ba437961d7d2e0d (diff) | |
download | ppe42-gcc-bb0726a148f7adef1517311f8a5037cb525e0f39.tar.gz ppe42-gcc-bb0726a148f7adef1517311f8a5037cb525e0f39.zip |
38th Cygnus<->FSF merge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7337 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 204 | ||||
-rw-r--r-- | gcc/cp/call.c | 1480 | ||||
-rw-r--r-- | gcc/cp/class.c | 47 | ||||
-rw-r--r-- | gcc/cp/class.h | 55 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 15 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 167 | ||||
-rw-r--r-- | gcc/cp/decl.c | 99 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 69 | ||||
-rw-r--r-- | gcc/cp/errfn.c | 2 | ||||
-rw-r--r-- | gcc/cp/error.c | 7 | ||||
-rw-r--r-- | gcc/cp/gxx.gperf | 3 | ||||
-rw-r--r-- | gcc/cp/hash.h | 194 | ||||
-rw-r--r-- | gcc/cp/init.c | 5 | ||||
-rw-r--r-- | gcc/cp/lex.c | 9 | ||||
-rw-r--r-- | gcc/cp/lex.h | 1 | ||||
-rw-r--r-- | gcc/cp/method.c | 16 | ||||
-rw-r--r-- | gcc/cp/parse.y | 249 | ||||
-rw-r--r-- | gcc/cp/pt.c | 11 | ||||
-rw-r--r-- | gcc/cp/search.c | 37 | ||||
-rw-r--r-- | gcc/cp/tree.c | 13 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 376 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 29 |
22 files changed, 1067 insertions, 2021 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bd2be26f9ca..f4b142407d3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,207 @@ +Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com) + + * cvt.c (type_promotes_to): Make sure bool promotes to int rather + than unsigned on platforms where sizeof(char)==sizeof(int). + +Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (build_c_cast): Tack on a NOP_EXPR when casting to + another variant. + (build_modify_expr): Don't strip NOP_EXPRs, and don't get tricky + and treat them as lvalues. + + * decl.c (shadow_tag): Do complain about forward declarations of + enums and empty declarations. + * parse.y: Don't complain about forward declarations of enums and + empty declarations. + + * typeck.c (convert_for_assignment): Complain about changing + the signedness of a pointer's target type. + + * parse.y (stmt): Move duplicated code for checking case values from + here. + * decl2.c (check_cp_case_value): To here. And add a call to + constant_expression_warning. + + * typeck.c (convert_for_assignment): Don't complain about assigning + a negative value to bool. + + * decl.c (init_decl_processing): Make bool unsigned. + + * class.c (finish_struct): Allow bool bitfields. + +Wed May 18 14:41:59 1994 Mike Stump (mrs@cygnus.com) + + * class.c (finish_base_struct): Make sure we set BINFO_VTABLE and + BINFO_VIRTUALS when we choose a new base class to inherit from. + * class.c (modify_one_vtable): Use get_vfield_offset to get the + offset to the most base class subobject that we derived this binfo + from. + * class.c (finish_struct): Move code to calculate the + DECL_FIELD_BITPOS of the vfield up, as we need might need it for + new calls to get_vfield_offset in modify_one_vtable. + +Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp. + +Wed May 18 03:28:35 1994 Jason Merrill (jason@deneb.cygnus.com) + + * cvt.c (build_type_conversion): Lose special handling of + truthvalues. + + * search.c (dfs_pushdecls): Improve shadowing warning. + +Tue May 17 13:34:46 1994 Jason Merrill (jason@deneb.cygnus.com) + + * init.c (build_delete): Throw away const and volatile on `this'. + + * decl.c (finish_enum): Put the constants in TYPE_VALUES again, + rather than the enumerators. + (pushtag): s/cdecl/c_decl/g + +Mon May 16 23:04:01 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de) + + * cp/typeck.c (common_type): Attribute merging. + (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro. + + * cp/parse.y: Revamp attribute parsing. + +Mon May 16 01:40:34 1994 Jason Merrill (jason@deneb.cygnus.com) + + * decl.c (shadow_tag): Also check for inappropriate use of auto and + register. + + * method.c (build_overload_name): Clarify that the illegal case is a + pointer or reference to array of unknown bound. + + * error.c (dump_type_prefix): Print references to arrays properly. + + * typeck.c (various): Be more helpful in pointer + comparison diagnostics. + + * tree.c (lvalue_p): MODIFY_EXPRs are lvalues again. Isn't this + fun? + + * parse.y: Also catch an error after valid stmts. + + * search.c (dfs_init_vbase_pointers): Don't abort because `this' is + const. + + * typeck.c (convert_for_initialization): If call to + convert_to_reference generated a diagnostic, print out the parm + number and function decl if any. + + * errfn.c (cp_thing): Check atarg1 to determine whether or not we're + specifying a line, not atarg. + + * tree.c (build_cplus_method_type): Always make `this' const. + + * decl2.c (grokclassfn): If -fthis-is-variable and this function is + a constructor or destructor, make `this' non-const. + + * typeck.c (build_modify_expr): Don't warn specially about + assignment to `this' here anymore, since it will be caught by the + usual machinery. + + * various: Disallow specific GNU extensions (variable-size arrays, + etc.) when flag_ansi is set, not necessarily when pedantic is set, + so that people can compile with -pedantic-errors for tighter const + checking and such without losing desirable extensions. + + * typeck2.c (build_functional_cast): Call build_method_call with + LOOKUP_PROTECT. + (process_init_constructor): Only process FIELD_DECLs. + + * decl.c (finish_decl): Also force static consts with no explicit + initializer that need constructing into the data segment. + + * init.c (build_delete): Undo last patch, as it interferes with + automatic cleanups. + +Sat May 14 01:59:31 1994 Jason Merrill (jason@deneb.cygnus.com) + + * call.c, class.h, cp-tree.h, cvt.c, decl2.c: Lose old overloading + code. + + * init.c (build_delete): pedwarn about using plain delete to delete + an array. + +Fri May 13 16:45:07 1994 Jason Merrill (jason@deneb.cygnus.com) + + * typeck.c (comp_target_types): Be more helpful in contravariance + warnings, and make them pedwarns. + + * decl.c (grokdeclarator): Use decl_context to decide whether or not + this is an access declaration. + + * class.c (finish_struct_bits): Set TYPE_HAS_INT_CONVERSION if it + has a conversion to enum or bool, too. + +Fri May 13 16:31:27 1994 Mike Stump (mrs@cygnus.com) + + * method.c (emit_thunk): Make declaration for + current_call_is_indirect local (needed for hppa). + +Fri May 13 16:16:37 1994 Jason Merrill (jason@deneb.cygnus.com) + + * pt.c (uses_template_parms): Grok BOOLEAN_TYPE. + (tsubst): Ditto. + +Fri May 13 16:23:32 1994 Mike Stump (mrs@cygnus.com) + + * pt.c (tsubst): If there is already a function for this expansion, + use it. + * pt.c (instantiate_template): Ditto. + +Fri May 13 10:30:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com) + + * parse.y (implicitly_scoped_stmt, simple_stmt case): Use + kept_level_p for MARK_ENDS argument to expand_end_bindings, to avoid + generating debug info for unemitted symbols on some systems. + + * cp-tree.h (build_static_cast, build_reinterpret_cast, + build_const_cast): Add declarations. + +Fri May 13 09:50:31 1994 Mike Stump (mrs@cygnus.com) + + * search.c (expand_indirect_vtbls_init): Fix breakage from Apr 27 + fix. We now try get_binfo, and if that doesn't find what we want, + we go back to the old method, which still sometimes fails. + +Fri May 13 01:43:18 1994 Jason Merrill (jason@deneb.cygnus.com) + + * parse.y (initdcl): Call cplus_decl_attributes on the right + variable. + * decl2.c (cplus_decl_attributes): Don't call decl_attributes for + void_type_node. + + * typeck.c (build_binary_op_nodefault): Change result_type for + comparison ops to bool. + (build_binary_op): Convert args of && and || to bool. + * cvt.c (build_default_binary_type_conversion): Convert args of && + and || to bool. + (build_default_unary_type_conversion): Convert arg of ! to bool. + (type_promotes_to): bool promotes to int. + +Fri May 13 01:43:18 1994 Mike Stump (mrs@cygnus.com) + + Implement the new builtin `bool' type. + * typeck.c (build_binary_op_nodefault): Convert args of && and || to + bool. + (build_unary_op): Convert arg of ! to bool. + * parse.y: Know true and false. Use bool_truthvalue_conversion. + * method.c (build_overload_value): Know bool. + (build_overload_name): Ditto. + * lex.c (init_lex): Set up RID_BOOL. + * gxx.gperf: Add bool, true, false. + * error.c (*): Know bool. + * decl.c (init_decl_processing): Set up bool, true, false. + * cvt.c (cp_convert): Handle conversion to bool. + (build_type_conversion): Ditto. + * *.c: Accept bool where integers and enums are accepted (use + INTEGRAL_CODE_P macro). + Thu May 12 19:13:54 1994 Richard Earnshaw (rwe11@cl.cam.ac.uk) * g++.c: Use #ifdef for __MSDOS__, not #if. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 6700f87e87e..e957776711d 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -44,38 +44,17 @@ extern tree unary_complex_lvalue (); /* Compute the ease with which a conversion can be performed between an expected and the given type. */ -static int convert_harshness_old (); -static struct harshness_code convert_harshness_ansi (); - -/* OLD METHOD */ -/* Note the old method also uses USER_HARSHNESS, BASE_DERIVED_HARSHNESS, - CONST_HARSHNESS. */ -#define EVIL 1 -#define TRIVIAL 0 -#define EVIL_HARSHNESS(ARG) ((ARG) & 1) -#define ELLIPSIS_HARSHNESS(ARG) ((ARG) & 2) -#define CONTRAVARIANT_HARSHNESS(ARG) ((ARG) & 8) -#define INT_TO_BD_HARSHNESS(ARG) (((ARG) << 5) | 16) -#define INT_FROM_BD_HARSHNESS(ARG) ((ARG) >> 5) -#define INT_TO_EASY_HARSHNESS(ARG) ((ARG) << 5) -#define INT_FROM_EASY_HARSHNESS(ARG) ((ARG) >> 5) -#define ONLY_EASY_HARSHNESS(ARG) (((ARG) & 31) == 0) - - -/* NEW METHOD */ +static struct harshness_code convert_harshness (); + #define EVIL_RETURN(ARG) ((ARG).code = EVIL_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)) -#define USER_HARSHNESS(ARG) ((ARG) & 4) -#define BASE_DERIVED_HARSHNESS(ARG) ((ARG) & 16) -#define CONST_HARSHNESS(ARG) ((ARG) & 2048) - /* Ordering function for overload resolution. Compare two candidates by gross quality. */ int -rank_for_overload_ansi (x, y) +rank_for_overload (x, y) struct candidate *x, *y; { if (y->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE)) @@ -85,8 +64,8 @@ rank_for_overload_ansi (x, y) /* This is set by compute_conversion_costs, for calling a non-const member function from a const member function. */ - if ((y->v.ansi_harshness[0].code & CONST_CODE) ^ (x->v.ansi_harshness[0].code & CONST_CODE)) - return y->v.ansi_harshness[0].code - x->v.ansi_harshness[0].code; + if ((y->harshness[0].code & CONST_CODE) ^ (x->harshness[0].code & CONST_CODE)) + return y->harshness[0].code - x->harshness[0].code; if (y->h.code & STD_CODE) { @@ -100,33 +79,6 @@ rank_for_overload_ansi (x, y) return y->h.code - x->h.code; } -int -rank_for_overload_old (x, y) - struct candidate *x, *y; -{ - if (y->evil - x->evil) - return y->evil - x->evil; - if (CONST_HARSHNESS (y->v.old_harshness[0]) ^ CONST_HARSHNESS (x->v.old_harshness[0])) - return y->v.old_harshness[0] - x->v.old_harshness[0]; - if (y->ellipsis - x->ellipsis) - return y->ellipsis - x->ellipsis; - if (y->user - x->user) - return y->user - x->user; - if (y->b_or_d - x->b_or_d) - return y->b_or_d - x->b_or_d; - return y->easy - x->easy; -} - -int -rank_for_overload (x, y) - struct candidate *x, *y; -{ - if (flag_ansi_overloading) - return rank_for_overload_ansi (x, y); - else - return rank_for_overload_old (x, y); -} - /* Compare two candidates, argument by argument. */ int rank_for_ideal (x, y) @@ -139,17 +91,17 @@ rank_for_ideal (x, y) for (i = 0; i < x->h_len; i++) { - if (y->v.ansi_harshness[i].code - x->v.ansi_harshness[i].code) - return y->v.ansi_harshness[i].code - x->v.ansi_harshness[i].code; - if ((y->v.ansi_harshness[i].code & STD_CODE) - && (y->v.ansi_harshness[i].distance - x->v.ansi_harshness[i].distance)) - return y->v.ansi_harshness[i].distance - x->v.ansi_harshness[i].distance; + if (y->harshness[i].code - x->harshness[i].code) + return y->harshness[i].code - x->harshness[i].code; + if ((y->harshness[i].code & STD_CODE) + && (y->harshness[i].distance - x->harshness[i].distance)) + return y->harshness[i].distance - x->harshness[i].distance; /* They're both the same code. Now see if we're dealing with an integral promotion that needs a finer grain of accuracy. */ - if (y->v.ansi_harshness[0].code & PROMO_CODE - && (y->v.ansi_harshness[i].int_penalty ^ x->v.ansi_harshness[i].int_penalty)) - return y->v.ansi_harshness[i].int_penalty - x->v.ansi_harshness[i].int_penalty; + if (y->harshness[0].code & PROMO_CODE + && (y->harshness[i].int_penalty ^ x->harshness[i].int_penalty)) + return y->harshness[i].int_penalty - x->harshness[i].int_penalty; } return 0; } @@ -158,7 +110,7 @@ rank_for_ideal (x, y) we have to work with. We use a somewhat arbitrary cost function to measure this conversion. */ static struct harshness_code -convert_harshness_ansi (type, parmtype, parm) +convert_harshness (type, parmtype, parm) register tree type, parmtype; tree parm; { @@ -213,7 +165,7 @@ convert_harshness_ansi (type, parmtype, parm) /* Compare return types. */ p1 = TREE_TYPE (type); p2 = TREE_TYPE (parmtype); - h2 = convert_harshness_ansi (p1, p2, NULL_TREE); + h2 = convert_harshness (p1, p2, NULL_TREE); if (h2.code & EVIL_CODE) return h2; @@ -262,7 +214,7 @@ convert_harshness_ansi (type, parmtype, parm) while (p1 && TREE_VALUE (p1) != void_type_node && p2 && TREE_VALUE (p2) != void_type_node) { - h2 = convert_harshness_ansi (TREE_VALUE (p1), TREE_VALUE (p2), + h2 = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2), NULL_TREE); if (h2.code & EVIL_CODE) return h2; @@ -341,7 +293,7 @@ convert_harshness_ansi (type, parmtype, parm) if (coder == VOID_TYPE) return EVIL_RETURN (h); - if (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE) + if (INTEGRAL_CODE_P (codel)) { /* Control equivalence of ints an enums. */ @@ -356,7 +308,7 @@ convert_harshness_ansi (type, parmtype, parm) /* else enums and ints (almost) freely interconvert. */ - if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE) + if (INTEGRAL_CODE_P (coder)) { if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (type_promotes_to (parmtype))) @@ -395,7 +347,7 @@ convert_harshness_ansi (type, parmtype, parm) return h; } - else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE) + else if (INTEGRAL_CODE_P (coder)) { h.code = STD_CODE; h.distance = 0; @@ -625,12 +577,11 @@ convert_harshness_ansi (type, parmtype, parm) matter if we make life easier for the programmer by creating a temporary variable with which to hold the result. */ - if (parm && (coder == INTEGER_TYPE - || coder == ENUMERAL_TYPE + if (parm && (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE) && ! lvalue_p (parm)) { - h = convert_harshness_ansi (ttl, ttr, NULL_TREE); + h = convert_harshness (ttl, ttr, NULL_TREE); if (penalty > 2 || h.code != 0) h.code |= STD_CODE; else @@ -672,7 +623,7 @@ convert_harshness_ansi (type, parmtype, parm) if (parm && codel != REFERENCE_TYPE) { - h = convert_harshness_ansi (ttl, ttr, NULL_TREE); + h = convert_harshness (ttl, ttr, NULL_TREE); if (penalty == 2) h.code |= QUAL_CODE; else if (penalty == 4) @@ -731,468 +682,6 @@ convert_harshness_ansi (type, parmtype, parm) return EVIL_RETURN (h); } -/* TYPE is the type we wish to convert to. PARM is the parameter - we have to work with. We use a somewhat arbitrary cost function - to measure this conversion. */ -static int -convert_harshness_old (type, parmtype, parm) - register tree type, parmtype; - tree parm; -{ - register enum tree_code codel; - register enum tree_code coder; - -#ifdef GATHER_STATISTICS - n_convert_harshness++; -#endif - - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); - if (TYPE_PTRMEMFUNC_P (parmtype)) - parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); - - codel = TREE_CODE (type); - coder = TREE_CODE (parmtype); - - if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type)) - return TRIVIAL; - - if (coder == ERROR_MARK) - return EVIL; - - if (codel == POINTER_TYPE && fntype_p (parmtype)) - { - tree p1, p2; - int harshness, new_harshness; - - /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be. */ - type = TREE_TYPE (type); - - if (coder == POINTER_TYPE) - { - parmtype = TREE_TYPE (parmtype); - coder = TREE_CODE (parmtype); - } - - if (coder != TREE_CODE (type)) - return EVIL; - - harshness = 0; - - /* We allow the default conversion between function type - and pointer-to-function type for free. */ - if (type == parmtype) - return TRIVIAL; - - /* Compare return types. */ - p1 = TREE_TYPE (type); - p2 = TREE_TYPE (parmtype); - new_harshness = convert_harshness_old (p1, p2, NULL_TREE); - if (EVIL_HARSHNESS (new_harshness)) - return EVIL; - - if (BASE_DERIVED_HARSHNESS (new_harshness)) - { - tree binfo; - - /* This only works for pointers. */ - if (TREE_CODE (p1) != POINTER_TYPE - && TREE_CODE (p1) != REFERENCE_TYPE) - return EVIL; - - p1 = TREE_TYPE (p1); - p2 = TREE_TYPE (p2); - /* Don't die if we happen to be dealing with void*. */ - if (!IS_AGGR_TYPE (p1) || !IS_AGGR_TYPE (p2)) - return EVIL; - if (CONTRAVARIANT_HARSHNESS (new_harshness)) - binfo = get_binfo (p2, p1, 0); - else - binfo = get_binfo (p1, p2, 0); - - if (! BINFO_OFFSET_ZEROP (binfo)) - { - static int explained = 0; - if (CONTRAVARIANT_HARSHNESS (new_harshness)) - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1); - else - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2); - - if (! explained++) - sorry ("(because pointer values change during conversion)"); - return EVIL; - } - } - - harshness |= new_harshness; - - p1 = TYPE_ARG_TYPES (type); - p2 = TYPE_ARG_TYPES (parmtype); - while (p1 && TREE_VALUE (p1) != void_type_node - && p2 && TREE_VALUE (p2) != void_type_node) - { - new_harshness = convert_harshness_old (TREE_VALUE (p1), - TREE_VALUE (p2), NULL_TREE); - if (EVIL_HARSHNESS (new_harshness)) - return EVIL; - - if (BASE_DERIVED_HARSHNESS (new_harshness)) - { - /* This only works for pointers and references. */ - if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE - && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE) - return EVIL; - new_harshness ^= CONTRAVARIANT_HARSHNESS (new_harshness); - harshness |= new_harshness; - } - /* This trick allows use to accumulate easy type - conversions without messing up the bits that encode - info about more involved things. */ - else if (ONLY_EASY_HARSHNESS (new_harshness)) - harshness += new_harshness; - else - harshness |= new_harshness; - p1 = TREE_CHAIN (p1); - p2 = TREE_CHAIN (p2); - } - if (p1 == p2) - return harshness; - if (p2) - return p1 ? EVIL : (harshness | ELLIPSIS_HARSHNESS (-1)); - if (p1) - return harshness | (TREE_PURPOSE (p1) == NULL_TREE); - } - else if (codel == POINTER_TYPE && coder == OFFSET_TYPE) - { - /* XXX: Note this is set a few times, but it's never actually - used! (bpk) */ - int harshness; - - /* Get to the OFFSET_TYPE that this might be. */ - type = TREE_TYPE (type); - - if (coder != TREE_CODE (type)) - return EVIL; - - harshness = 0; - - if (TYPE_OFFSET_BASETYPE (type) == TYPE_OFFSET_BASETYPE (parmtype)) - harshness = 0; - else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (type), - TYPE_OFFSET_BASETYPE (parmtype))) - harshness = INT_TO_BD_HARSHNESS (1); - else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (parmtype), - TYPE_OFFSET_BASETYPE (type))) - harshness = CONTRAVARIANT_HARSHNESS (-1); - else - return EVIL; - /* Now test the OFFSET_TYPE's target compatibility. */ - type = TREE_TYPE (type); - parmtype = TREE_TYPE (parmtype); - } - - if (coder == UNKNOWN_TYPE) - { - if (codel == FUNCTION_TYPE - || codel == METHOD_TYPE - || (codel == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))) - return TRIVIAL; - return EVIL; - } - - if (coder == VOID_TYPE) - return EVIL; - - if (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE) - { - /* Control equivalence of ints an enums. */ - - if (codel == ENUMERAL_TYPE - && flag_int_enum_equivalence == 0) - { - /* Enums can be converted to ints, but not vice-versa. */ - if (coder != ENUMERAL_TYPE - || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype)) - return EVIL; - } - - /* else enums and ints (almost) freely interconvert. */ - - if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE) - { - int easy = TREE_UNSIGNED (type) ^ TREE_UNSIGNED (parmtype); - if (codel != coder) - easy += 1; - if (TYPE_MODE (type) != TYPE_MODE (parmtype)) - easy += 2; - return INT_TO_EASY_HARSHNESS (easy); - } - else if (coder == REAL_TYPE) - return INT_TO_EASY_HARSHNESS (4); - } - - if (codel == REAL_TYPE) - if (coder == REAL_TYPE) - /* Shun converting between float and double if a choice exists. */ - { - if (TYPE_MODE (type) != TYPE_MODE (parmtype)) - return INT_TO_EASY_HARSHNESS (2); - return TRIVIAL; - } - else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE) - return INT_TO_EASY_HARSHNESS (4); - - /* convert arrays which have not previously been converted. */ - if (codel == ARRAY_TYPE) - codel = POINTER_TYPE; - if (coder == ARRAY_TYPE) - coder = POINTER_TYPE; - - /* Conversions among pointers */ - if (codel == POINTER_TYPE && coder == POINTER_TYPE) - { - register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - 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 unsinged pointer types. */ - - if ((TREE_CODE (ttl) == METHOD_TYPE - || TREE_CODE (ttl) == FUNCTION_TYPE) - && TREE_CODE (ttl) == TREE_CODE (ttr)) - { - if (comptypes (ttl, ttr, -1)) - return INT_TO_EASY_HARSHNESS (penalty); - return EVIL; - } - - if (!(TREE_CODE (ttl) == VOID_TYPE - || TREE_CODE (ttr) == VOID_TYPE - || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr) - && (ttl = unsigned_type (ttl), - ttr = unsigned_type (ttr), - penalty = 10, 0)) - || (comp_target_types (ttl, ttr, 0)))) - return EVIL; - - if (penalty == 10) - return INT_TO_EASY_HARSHNESS (10); - if (ttr == ttl) - return INT_TO_BD_HARSHNESS (0); - - 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 CONTRAVARIANT_HARSHNESS (-1); - } - return INT_TO_BD_HARSHNESS (b_or_d); - } - /* If converting from a `class*' to a `void*', make it - less favorable than any inheritance relationship. */ - if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr)) - return INT_TO_BD_HARSHNESS (CLASSTYPE_MAX_DEPTH (ttr)+1); - return INT_TO_EASY_HARSHNESS (penalty); - } - - if (codel == POINTER_TYPE && coder == INTEGER_TYPE) - { - /* This is not a bad match, but don't let it beat - integer-enum combinations. */ - if (parm && integer_zerop (parm)) - return INT_TO_EASY_HARSHNESS (4); - } - - /* C++: Since the `this' parameter of a signature member function - is represented as a signature pointer to handle default implementations - correctly, we can have the case that `type' is a signature pointer - while `parmtype' is a pointer to a signature table. We don't really - do any conversions in this case, so just return 0. */ - - if (codel == RECORD_TYPE && coder == POINTER_TYPE - && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype))) - return 0; - - /* C++: one of the types must be a reference type. */ - { - tree ttl, ttr; - register tree intype = TYPE_MAIN_VARIANT (parmtype); - register enum tree_code form = TREE_CODE (intype); - int penalty; - - if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE) - { - ttl = TYPE_MAIN_VARIANT (type); - - if (codel == REFERENCE_TYPE) - { - ttl = TREE_TYPE (ttl); - - /* When passing a non-const argument into a const reference, - dig it a little, so a non-const reference is preferred over - this one. (mrs) */ - if (parm && TREE_READONLY (ttl) && ! TREE_READONLY (parm)) - penalty = 2; - else - penalty = 0; - - ttl = TYPE_MAIN_VARIANT (ttl); - - if (form == OFFSET_TYPE) - { - intype = TREE_TYPE (intype); - form = TREE_CODE (intype); - } - - if (form == REFERENCE_TYPE) - { - intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype)); - - if (ttl == intype) - return TRIVIAL; - penalty = 2; - } - else - { - /* Can reference be built up? */ - if (ttl == intype && penalty == 0) { - /* Because the READONLY bits and VIRTUAL bits are not always - in the type, this extra check is necessary. The problem - should be fixed someplace else, and this extra code - removed. - - Also, if type if a reference, the readonly bits could - either be in the outer type (with reference) or on the - inner type (the thing being referenced). (mrs) */ - if (parm - && ((TREE_READONLY (parm) - && ! (TYPE_READONLY (type) - || (TREE_CODE (type) == REFERENCE_TYPE - && TYPE_READONLY (TREE_TYPE (type))))) - || (TREE_SIDE_EFFECTS (parm) - && ! (TYPE_VOLATILE (type) - || (TREE_CODE (type) == REFERENCE_TYPE - && TYPE_VOLATILE (TREE_TYPE (type))))))) - penalty = 2; - else - return TRIVIAL; - } - else - penalty = 2; - } - } - else if (form == REFERENCE_TYPE) - { - if (parm) - { - tree tmp = convert_from_reference (parm); - intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp)); - } - else - { - intype = parmtype; - do - { - intype = TREE_TYPE (intype); - } - while (TREE_CODE (intype) == REFERENCE_TYPE); - intype = TYPE_MAIN_VARIANT (intype); - } - - if (ttl == intype) - return TRIVIAL; - else - penalty = 2; - } - - if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype)) - { - ttl = unsigned_type (ttl); - intype = unsigned_type (intype); - 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 && (coder == INTEGER_TYPE - || coder == ENUMERAL_TYPE - || coder == REAL_TYPE) - && ! lvalue_p (parm)) - return (convert_harshness_old (ttl, ttr, NULL_TREE) - | INT_TO_EASY_HARSHNESS (penalty)); - - if (ttl == ttr) - { - if (penalty) - return INT_TO_EASY_HARSHNESS (penalty); - return INT_TO_BD_HARSHNESS (0); - } - - /* 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) - return INT_TO_EASY_HARSHNESS (penalty+1); - - if (parm && codel != REFERENCE_TYPE) - return (convert_harshness_old (ttl, ttr, NULL_TREE) - | INT_TO_EASY_HARSHNESS (penalty)); - - /* 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 CONTRAVARIANT_HARSHNESS (-1); - } - /* 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. */ - return INT_TO_BD_HARSHNESS (b_or_d); - } - - if (comp_target_types (ttl, intype, 1)) - return INT_TO_EASY_HARSHNESS (penalty); - } - } - if (codel == RECORD_TYPE && coder == RECORD_TYPE) - { - int b_or_d = get_base_distance (type, parmtype, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (parmtype, type, 0, 0); - if (b_or_d < 0) - return EVIL; - return CONTRAVARIANT_HARSHNESS (-1); - } - return INT_TO_BD_HARSHNESS (b_or_d); - } - return EVIL; -} - #ifdef DEBUG_MATCHING static char * print_harshness (h) @@ -1243,7 +732,7 @@ print_harshness (h) must be unique. */ void -compute_conversion_costs_ansi (function, tta_in, cp, arglen) +compute_conversion_costs (function, tta_in, cp, arglen) tree function; tree tta_in; struct candidate *cp; @@ -1274,7 +763,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) cp->h.code = 0; cp->h.distance = 0; cp->h.int_penalty = 0; - bzero (cp->v.ansi_harshness, + bzero (cp->harshness, (cp->h_len + 1) * sizeof (struct harshness_code)); while (ttf && tta) @@ -1305,7 +794,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) if (TREE_CODE (rhs) == ERROR_MARK) h.code = EVIL_CODE; else - h = convert_harshness_ansi (lhstype, TREE_TYPE (rhs), rhs); + h = convert_harshness (lhstype, TREE_TYPE (rhs), rhs); } else { @@ -1323,7 +812,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) TREE_VALUE (ttf)); #endif - h = convert_harshness_ansi (TREE_VALUE (ttf), + h = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta)); @@ -1332,7 +821,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) #endif } - cp->v.ansi_harshness[strike_index] = h; + cp->harshness[strike_index] = h; if ((h.code & EVIL_CODE) || ((h.code & STD_CODE) && h.distance < 0)) { @@ -1342,7 +831,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) else if (h.code & ELLIPSIS_CODE) ellipsis_strikes += 1; #if 0 - /* This is never set by `convert_harshness_ansi'. */ + /* This is never set by `convert_harshness'. */ else if (h.code & USER_CODE) { user_strikes += 1; @@ -1385,7 +874,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) h.distance = 0; h.int_penalty = 0; for (; l; --l) - cp->v.ansi_harshness[strike_index++] = h; + cp->harshness[strike_index++] = h; } } else if (ttf && ttf != void_list_node) @@ -1398,10 +887,10 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) return; } /* Store index of first default. */ - cp->v.ansi_harshness[arglen].distance = strike_index+1; + cp->harshness[arglen].distance = strike_index+1; } else - cp->v.ansi_harshness[arglen].distance = 0; + cp->harshness[arglen].distance = 0; /* Argument list lengths work out, so don't need to check them again. */ if (evil_strikes) @@ -1431,7 +920,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) if (ttf == void_list_node) break; - lose = cp->v.ansi_harshness[strike_index]; + lose = cp->harshness[strike_index]; if ((lose.code & EVIL_CODE) || ((lose.code & STD_CODE) && lose.distance < 0)) { @@ -1510,7 +999,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) if (win == 1) { user_strikes += 1; - cp->v.ansi_harshness[strike_index].code + cp->harshness[strike_index].code = USER_CODE | (extra_conversions ? STD_CODE : 0); win = 0; } @@ -1543,7 +1032,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm)))) : TYPE_READONLY (TREE_TYPE (this_parm))) { - cp->v.ansi_harshness[0].code |= TRIVIAL_CODE; + cp->harshness[0].code |= TRIVIAL_CODE; ++easy_strikes; } else @@ -1554,7 +1043,7 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) harshness to a maximum value. */ if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in)))))) - cp->v.ansi_harshness[0].code |= CONST_CODE; + cp->harshness[0].code |= CONST_CODE; } } @@ -1569,636 +1058,6 @@ compute_conversion_costs_ansi (function, tta_in, cp, arglen) #endif } -void -compute_conversion_costs_old (function, tta_in, cp, arglen) - tree function; - tree tta_in; - struct candidate *cp; - int arglen; -{ - tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function)); - tree ttf = ttf_in; - tree tta = tta_in; - - /* Start out with no strikes against. */ - int evil_strikes = 0; - int ellipsis_strikes = 0; - int user_strikes = 0; - int b_or_d_strikes = 0; - int easy_strikes = 0; - - int strike_index = 0, win, lose; - -#ifdef GATHER_STATISTICS - n_compute_conversion_costs++; -#endif - - cp->function = function; - cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE; - cp->u.bad_arg = 0; /* optimistic! */ - - bzero (cp->v.old_harshness, (cp->h_len + 1) * sizeof (unsigned short)); - - while (ttf && tta) - { - int harshness; - - if (ttf == void_list_node) - break; - - if (type_unknown_p (TREE_VALUE (tta))) - { - /* Must perform some instantiation here. */ - tree rhs = TREE_VALUE (tta); - tree lhstype = TREE_VALUE (ttf); - - /* Keep quiet about possible contravariance violations. */ - int old_inhibit_warnings = inhibit_warnings; - inhibit_warnings = 1; - - /* @@ This is to undo what `grokdeclarator' does to - parameter types. It really should go through - something more general. */ - - TREE_TYPE (tta) = unknown_type_node; - rhs = instantiate_type (lhstype, rhs, 0); - inhibit_warnings = old_inhibit_warnings; - - if (TREE_CODE (rhs) == ERROR_MARK) - harshness = 1; - else - { - harshness = convert_harshness_old (lhstype, TREE_TYPE (rhs), - rhs); - /* harshness |= 2; */ - } - } - else - harshness = convert_harshness_old (TREE_VALUE (ttf), - TREE_TYPE (TREE_VALUE (tta)), - TREE_VALUE (tta)); - - cp->v.old_harshness[strike_index] = harshness; - if (EVIL_HARSHNESS (harshness) - || CONTRAVARIANT_HARSHNESS (harshness)) - { - cp->u.bad_arg = strike_index; - evil_strikes = 1; - } - else if (ELLIPSIS_HARSHNESS (harshness)) - { - ellipsis_strikes += 1; - } -#if 0 - /* This is never set by `convert_harshness_old'. */ - else if (USER_HARSHNESS (harshness)) - { - user_strikes += 1; - } -#endif - else if (BASE_DERIVED_HARSHNESS (harshness)) - { - b_or_d_strikes += INT_FROM_BD_HARSHNESS (harshness); - } - else - easy_strikes += INT_FROM_EASY_HARSHNESS (harshness); - ttf = TREE_CHAIN (ttf); - tta = TREE_CHAIN (tta); - strike_index += 1; - } - - if (tta) - { - /* ran out of formals, and parmlist is fixed size. */ - if (ttf /* == void_type_node */) - { - cp->evil = 1; - cp->u.bad_arg = -1; - return; - } - else ellipsis_strikes += list_length (tta); - } - else if (ttf && ttf != void_list_node) - { - /* ran out of actuals, and no defaults. */ - if (TREE_PURPOSE (ttf) == NULL_TREE) - { - cp->evil = 1; - cp->u.bad_arg = -2; - return; - } - /* Store index of first default. */ - cp->v.old_harshness[arglen] = strike_index+1; - } - else - cp->v.old_harshness[arglen] = 0; - - /* Argument list lengths work out, so don't need to check them again. */ - if (evil_strikes) - { - /* We do not check for derived->base conversions here, since in - no case would they give evil strike counts, unless such conversions - are somehow ambiguous. */ - - /* See if any user-defined conversions apply. - But make sure that we do not loop. */ - static int dont_convert_types = 0; - - if (dont_convert_types) - { - cp->evil = 1; - return; - } - - win = 0; /* Only get one chance to win. */ - ttf = TYPE_ARG_TYPES (TREE_TYPE (function)); - tta = tta_in; - strike_index = 0; - evil_strikes = 0; - - while (ttf && tta) - { - if (ttf == void_list_node) - break; - - lose = cp->v.old_harshness[strike_index]; - if (EVIL_HARSHNESS (lose) - || CONTRAVARIANT_HARSHNESS (lose)) - { - tree actual_type = TREE_TYPE (TREE_VALUE (tta)); - tree formal_type = TREE_VALUE (ttf); - - dont_convert_types = 1; - - if (TREE_CODE (formal_type) == REFERENCE_TYPE) - formal_type = TREE_TYPE (formal_type); - if (TREE_CODE (actual_type) == REFERENCE_TYPE) - actual_type = TREE_TYPE (actual_type); - - if (formal_type != error_mark_node - && actual_type != error_mark_node) - { - formal_type = TYPE_MAIN_VARIANT (formal_type); - actual_type = TYPE_MAIN_VARIANT (actual_type); - - if (TYPE_HAS_CONSTRUCTOR (formal_type)) - { - /* If it has a constructor for this type, try to use it. */ - if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1) - != error_mark_node) - { - /* @@ There is no way to save this result yet. - @@ So success is NULL_TREE for now. */ - win++; - } - } - if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type)) - { - if (TREE_CODE (formal_type) == INTEGER_TYPE - && TYPE_HAS_INT_CONVERSION (actual_type)) - win++; - else if (TREE_CODE (formal_type) == REAL_TYPE - && TYPE_HAS_REAL_CONVERSION (actual_type)) - win++; - else - { - tree conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0); - if (conv) - { - if (conv == error_mark_node) - win += 2; - else - win++; - } - else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE) - { - conv = build_type_conversion (CALL_EXPR, formal_type, TREE_VALUE (tta), 0); - if (conv) - { - if (conv == error_mark_node) - win += 2; - else - win++; - } - } - } - } - } - dont_convert_types = 0; - - if (win == 1) - { - user_strikes += 1; - cp->v.old_harshness[strike_index] = USER_HARSHNESS (-1); - win = 0; - } - else - { - if (cp->u.bad_arg > strike_index) - cp->u.bad_arg = strike_index; - - evil_strikes = win ? 2 : 1; - break; - } - } - - ttf = TREE_CHAIN (ttf); - tta = TREE_CHAIN (tta); - strike_index += 1; - } - } - - /* Const member functions get a small penalty because defaulting - to const is less useful than defaulting to non-const. */ - /* This is bogus, it does not correspond to anything in the ARM. - This code will be fixed when this entire section is rewritten - to conform to the ARM. (mrs) */ - if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) - { - tree this_parm = TREE_VALUE (ttf_in); - - if (TREE_CODE (this_parm) == RECORD_TYPE /* Is `this' a sig ptr? */ - ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm)))) - : TYPE_READONLY (TREE_TYPE (this_parm))) - { - cp->v.old_harshness[0] += INT_TO_EASY_HARSHNESS (1); - ++easy_strikes; - } - else - { - /* Calling a non-const member function from a const member function - is probably invalid, but for now we let it only draw a warning. - We indicate that such a mismatch has occurred by setting the - harshness to a maximum value. */ - if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE - && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in)))))) - cp->v.old_harshness[0] |= CONST_HARSHNESS (-1); - } - } - - cp->evil = evil_strikes; - cp->ellipsis = ellipsis_strikes; - cp->user = user_strikes; - cp->b_or_d = b_or_d_strikes; - cp->easy = easy_strikes; -} - -void -compute_conversion_costs (function, tta_in, cp, arglen) - tree function; - tree tta_in; - struct candidate *cp; - int arglen; -{ - if (flag_ansi_overloading) - compute_conversion_costs_ansi (function, tta_in, cp, arglen); - else - compute_conversion_costs_old (function, tta_in, cp, arglen); -} - -/* When one of several possible overloaded functions and/or methods - can be called, choose the best candidate for overloading. - - BASETYPE is the context from which we start method resolution - or NULL if we are comparing overloaded functions. - CANDIDATES is the array of candidates we have to choose from. - N_CANDIDATES is the length of CANDIDATES. - PARMS is a TREE_LIST of parameters to the function we'll ultimately - choose. It is modified in place when resolving methods. It is not - modified in place when resolving overloaded functions. - LEN is the length of the parameter list. */ - -static struct candidate * -ideal_candidate_old (basetype, candidates, n_candidates, parms, len) - tree basetype; - struct candidate *candidates; - int n_candidates; - tree parms; - int len; -{ - struct candidate *cp = candidates + n_candidates; - int index, i; - tree ttf; - - qsort (candidates, /* char *base */ - n_candidates, /* int nel */ - sizeof (struct candidate), /* int width */ - rank_for_overload); /* int (*compar)() */ - - /* If the best candidate requires user-defined conversions, - and its user-defined conversions are a strict subset - of all other candidates requiring user-defined conversions, - then it is, in fact, the best. */ - for (i = -1; cp + i != candidates; i--) - if (cp[i].user == 0) - break; - - if (i < -1) - { - tree ttf0; - - /* Check that every other candidate requires those conversions - as a strict subset of their conversions. */ - if (cp[i].user == cp[-1].user) - goto non_subset; - - /* Look at subset relationship more closely. */ - while (i != -1) - { - for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), - ttf0 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)), - index = 0; index < len; index++) - { - if (USER_HARSHNESS (cp[i].v.old_harshness[index])) - { - /* If our "best" candidate also needs a conversion, - it must be the same one. */ - if (USER_HARSHNESS (cp[-1].v.old_harshness[index]) - && TREE_VALUE (ttf) != TREE_VALUE (ttf0)) - goto non_subset; - } - ttf = TREE_CHAIN (ttf); - ttf0 = TREE_CHAIN (ttf0); - /* Handle `...' gracefully. */ - if (ttf == NULL_TREE || ttf0 == NULL_TREE) - break; - } - i++; - } - /* The best was the best. */ - return cp - 1; - non_subset: - /* Use other rules for determining "bestness". */ - ; - } - - /* If the best two candidates we find require user-defined - conversions, we may need to report and error message. */ - if (cp[-1].user && cp[-2].user - && (cp[-1].b_or_d || cp[-2].b_or_d == 0)) - { - /* If the best two methods found involved user-defined - type conversions, then we must see whether one - of them is exactly what we wanted. If not, then - we have an ambiguity. */ - int best = 0; - tree tta = parms; - tree f1; -#if 0 - /* for LUCID */ - tree p1; -#endif - - /* Stash all of our parameters in safe places - so that we can perform type conversions in place. */ - while (tta) - { - TREE_PURPOSE (tta) = TREE_VALUE (tta); - tta = TREE_CHAIN (tta); - } - - i = 0; - do - { - int exact_conversions = 0; - - i -= 1; - tta = parms; - if (DECL_STATIC_FUNCTION_P (cp[i].function)) - tta = TREE_CHAIN (tta); - /* special note, we don't go through len parameters, because we - may only need len-1 parameters because of a call to a static - member. */ - for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), index = 0; - tta; - tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++) - { - /* If this is a varargs function, there's no conversion to do, - but don't accept an arg that needs a copy ctor. */ - if (ttf == NULL_TREE) - { - /* FIXME: verify that we cannot get here with an - arg that needs a ctor. */ - break; - } - - if (USER_HARSHNESS (cp[i].v.old_harshness[index])) - { - tree this_parm = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_PURPOSE (tta), 2); - if (basetype != NULL_TREE) - TREE_VALUE (tta) = this_parm; - if (this_parm) - { - if (TREE_CODE (this_parm) != CONVERT_EXPR - && (TREE_CODE (this_parm) != NOP_EXPR - || comp_target_types (TREE_TYPE (this_parm), - TREE_TYPE (TREE_OPERAND (this_parm, 0)), 1))) - exact_conversions += 1; - } - else if (PROMOTES_TO_AGGR_TYPE (TREE_VALUE (ttf), REFERENCE_TYPE)) - { - /* To get here we had to have succeeded via - a constructor. */ - TREE_VALUE (tta) = TREE_PURPOSE (tta); - exact_conversions += 1; - } - } - } - if (exact_conversions == cp[i].user) - { - if (best == 0) - { - best = i; - f1 = cp[best].function; -#if 0 - /* For LUCID */ - p1 = TYPE_ARG_TYPES (TREE_TYPE (f1)); -#endif - } - else - { - /* Don't complain if next best is from base class. */ - tree f2 = cp[i].function; - - if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE - && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE - && BASE_DERIVED_HARSHNESS (cp[i].v.old_harshness[0]) - && cp[best].v.old_harshness[0] < cp[i].v.old_harshness[0]) - { -#if 0 - tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2)); - /* For LUCID. */ - if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1)) - goto ret0; - else -#endif - continue; - } - else - { - /* Ensure that there's nothing ambiguous about these - two fns. */ - int identical = 1; - for (index = 0; index < len; index++) - { - /* Type conversions must be piecewise equivalent. */ - if (USER_HARSHNESS (cp[best].v.old_harshness[index]) - != USER_HARSHNESS (cp[i].v.old_harshness[index])) - goto ret0; - /* If there's anything we like better about the - other function, consider it ambiguous. */ - if (cp[i].v.old_harshness[index] < cp[best].v.old_harshness[index]) - goto ret0; - /* If any single one it diffent, then the whole is - not identical. */ - if (cp[i].v.old_harshness[index] != cp[best].v.old_harshness[index]) - identical = 0; - } - - /* If we can't tell the difference between the two, it - is ambiguous. */ - if (identical) - goto ret0; - - /* If we made it to here, it means we're satisfied that - BEST is still best. */ - continue; - } - } - } - } while (cp + i != candidates); - - if (best) - { - int exact_conversions = cp[best].user; - tta = parms; - if (DECL_STATIC_FUNCTION_P (cp[best].function)) - tta = TREE_CHAIN (parms); - for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[best].function)), index = 0; - exact_conversions > 0; - tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++) - { - if (USER_HARSHNESS (cp[best].v.old_harshness[index])) - { - /* We must now fill in the slot we left behind. - @@ This could be optimized to use the value previously - @@ computed by build_type_conversion in some cases. */ - if (basetype != NULL_TREE) - TREE_VALUE (tta) = convert (TREE_VALUE (ttf), TREE_PURPOSE (tta)); - exact_conversions -= 1; - } - else - TREE_VALUE (tta) = TREE_PURPOSE (tta); - } - return cp + best; - } - goto ret0; - } - /* If the best two candidates we find both use default parameters, - we may need to report and error. Don't need to worry if next-best - candidate is forced to use user-defined conversion when best is not. */ - if (cp[-2].user == 0 - && cp[-1].v.old_harshness[len] != 0 && cp[-2].v.old_harshness[len] != 0) - { - tree tt1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)); - tree tt2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function)); - unsigned i = cp[-1].v.old_harshness[len]; - - if (cp[-2].v.old_harshness[len] < i) - i = cp[-2].v.old_harshness[len]; - while (--i > 0) - { - if (TYPE_MAIN_VARIANT (TREE_VALUE (tt1)) - != TYPE_MAIN_VARIANT (TREE_VALUE (tt2))) - /* These lists are not identical, so we can choose our best candidate. */ - return cp - 1; - tt1 = TREE_CHAIN (tt1); - tt2 = TREE_CHAIN (tt2); - } - /* To get here, both lists had the same parameters up to the defaults - which were used. This is an ambiguous request. */ - goto ret0; - } - - /* Otherwise, return our best candidate. Note that if we get candidates - from independent base classes, we have an ambiguity, even if one - argument list look a little better than another one. */ - if (cp[-1].b_or_d && basetype && TYPE_USES_MULTIPLE_INHERITANCE (basetype)) - { - int i = n_candidates - 1, best = i; - tree base1 = NULL_TREE; - - if (TREE_CODE (TREE_TYPE (candidates[i].function)) == FUNCTION_TYPE) - return cp - 1; - - for (; i >= 0 && candidates[i].user == 0 && candidates[i].evil == 0; i--) - { - if (TREE_CODE (TREE_TYPE (candidates[i].function)) == METHOD_TYPE) - { - tree newbase = DECL_CLASS_CONTEXT (candidates[i].function); - - if (base1 != NULL_TREE) - { - /* newbase could be a base or a parent of base1 */ - if (newbase != base1 && ! UNIQUELY_DERIVED_FROM_P (newbase, base1) - && ! UNIQUELY_DERIVED_FROM_P (base1, newbase)) - { - cp_error ("ambiguous request for function from distinct base classes of type `%T'", basetype); - cp_error_at (" first candidate is `%#D'", - candidates[best].function); - cp_error_at (" second candidate is `%#D'", - candidates[i].function); - cp[-1].evil = 1; - return cp - 1; - } - } - else - { - best = i; - base1 = newbase; - } - } - else - return cp - 1; - } - } - - /* Don't accept a candidate as being ideal if it's indistinguishable - from another candidate. */ - if (rank_for_overload (cp-1, cp-2) == 0) - { - /* If the types are distinguishably different (like - `long' vs. `unsigned long'), that's ok. But if they are arbitrarily - different, such as `int (*)(void)' vs. `void (*)(int)', - that's not ok. */ - tree p1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)); - tree p2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function)); - while (p1 && p2) - { - if (TREE_CODE (TREE_VALUE (p1)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_VALUE (p1))) == FUNCTION_TYPE - && TREE_VALUE (p1) != TREE_VALUE (p2)) - return NULL; - p1 = TREE_CHAIN (p1); - p2 = TREE_CHAIN (p2); - } - if (p1 || p2) - return NULL; - } - - return cp - 1; - - ret0: - /* In the case where there is no ideal candidate, restore - TREE_VALUE slots of PARMS from TREE_PURPOSE slots. */ - while (parms) - { - TREE_VALUE (parms) = TREE_PURPOSE (parms); - parms = TREE_CHAIN (parms); - } - return NULL; -} - /* Subroutine of ideal_candidate. See if X or Y is a better match than the other. */ static int @@ -2216,8 +1075,20 @@ strictly_better (x, y) return 0; } +/* When one of several possible overloaded functions and/or methods + can be called, choose the best candidate for overloading. + + BASETYPE is the context from which we start method resolution + or NULL if we are comparing overloaded functions. + CANDIDATES is the array of candidates we have to choose from. + N_CANDIDATES is the length of CANDIDATES. + PARMS is a TREE_LIST of parameters to the function we'll ultimately + choose. It is modified in place when resolving methods. It is not + modified in place when resolving overloaded functions. + LEN is the length of the parameter list. */ + static struct candidate * -ideal_candidate_ansi (basetype, candidates, n_candidates, parms, len) +ideal_candidate (basetype, candidates, n_candidates, parms, len) tree basetype; struct candidate *candidates; int n_candidates; @@ -2278,27 +1149,27 @@ ideal_candidate_ansi (basetype, candidates, n_candidates, parms, len) rank_for_ideal); for (i = 0; i < len; i++) { - if (cp[-1].v.ansi_harshness[i].code < cp[-2].v.ansi_harshness[i].code) + if (cp[-1].harshness[i].code < cp[-2].harshness[i].code) better = 1; - else if (cp[-1].v.ansi_harshness[i].code > cp[-2].v.ansi_harshness[i].code) + else if (cp[-1].harshness[i].code > cp[-2].harshness[i].code) worse = 1; - else if (cp[-1].v.ansi_harshness[i].code & STD_CODE) + else if (cp[-1].harshness[i].code & STD_CODE) { /* If it involves a standard conversion, let the inheritance lattice be the final arbiter. */ - if (cp[-1].v.ansi_harshness[i].distance > cp[-2].v.ansi_harshness[i].distance) + if (cp[-1].harshness[i].distance > cp[-2].harshness[i].distance) worse = 1; - else if (cp[-1].v.ansi_harshness[i].distance < cp[-2].v.ansi_harshness[i].distance) + else if (cp[-1].harshness[i].distance < cp[-2].harshness[i].distance) better = 1; } - else if (cp[-1].v.ansi_harshness[i].code & PROMO_CODE) + else if (cp[-1].harshness[i].code & PROMO_CODE) { /* For integral promotions, take into account a finer granularity for determining which types should be favored over others in such promotions. */ - if (cp[-1].v.ansi_harshness[i].int_penalty > cp[-2].v.ansi_harshness[i].int_penalty) + if (cp[-1].harshness[i].int_penalty > cp[-2].harshness[i].int_penalty) worse = 1; - else if (cp[-1].v.ansi_harshness[i].int_penalty < cp[-2].v.ansi_harshness[i].int_penalty) + else if (cp[-1].harshness[i].int_penalty < cp[-2].harshness[i].int_penalty) better = 1; } } @@ -2309,22 +1180,6 @@ ideal_candidate_ansi (basetype, candidates, n_candidates, parms, len) return cp-1; } -static struct candidate * -ideal_candidate (basetype, candidates, n_candidates, parms, len) - tree basetype; - struct candidate *candidates; - int n_candidates; - tree parms; - int len; -{ - if (flag_ansi_overloading) - return ideal_candidate_ansi (basetype, candidates, n_candidates, parms, - len); - else - return ideal_candidate_old (basetype, candidates, n_candidates, parms, - len); -} - /* Assume that if the class referred to is not in the current class hierarchy, that it may be remote. PARENT is assumed to be of aggregate type here. */ @@ -3252,12 +2107,8 @@ build_method_call (instance, name, parms, basetype_path, flags) my_friendly_abort (167); cp->h_len = len; - if (flag_ansi_overloading) - cp->v.ansi_harshness = (struct harshness_code *) - alloca ((len + 1) * sizeof (struct harshness_code)); - else - cp->v.old_harshness = (unsigned short *) - alloca ((len + 1) * sizeof (unsigned short)); + cp->harshness = (struct harshness_code *) + alloca ((len + 1) * sizeof (struct harshness_code)); result = build_overload_call (name, friend_parms, 0, cp); /* If it turns out to be the one we were actually looking for @@ -3266,30 +2117,16 @@ build_method_call (instance, name, parms, basetype_path, flags) if (TREE_CODE (result) == CALL_EXPR) return result; - if (flag_ansi_overloading) - while ((cp->h.code & EVIL_CODE) == 0) - { - /* non-standard uses: set the field to 0 to indicate - we are using a non-member function. */ - cp->u.field = 0; - if (cp->v.ansi_harshness[len].distance == 0 - && cp->h.code < best) - best = cp->h.code; - cp += 1; - } - else - while (cp->evil == 0) - { - /* non-standard uses: set the field to 0 to indicate - we are using a non-member function. */ - cp->u.field = 0; - if (cp->v.old_harshness[len] == 0 - && cp->v.old_harshness[len] == 0 - && cp->ellipsis == 0 && cp->user == 0 && cp->b_or_d == 0 - && cp->easy < best) - best = cp->easy; - cp += 1; - } + while ((cp->h.code & EVIL_CODE) == 0) + { + /* non-standard uses: set the field to 0 to indicate + we are using a non-member function. */ + cp->u.field = 0; + if (cp->harshness[len].distance == 0 + && cp->h.code < best) + best = cp->h.code; + cp += 1; + } } } @@ -3357,22 +2194,14 @@ build_method_call (instance, name, parms, basetype_path, flags) n_inner_fields_searched++; #endif cp->h_len = len; - if (flag_ansi_overloading) - cp->v.ansi_harshness = (struct harshness_code *) - alloca ((len + 1) * sizeof (struct harshness_code)); - else - cp->v.old_harshness = (unsigned short *) - alloca ((len + 1) * sizeof (unsigned short)); + cp->harshness = (struct harshness_code *) + alloca ((len + 1) * sizeof (struct harshness_code)); if (DECL_STATIC_FUNCTION_P (function)) these_parms = TREE_CHAIN (these_parms); compute_conversion_costs (function, these_parms, cp, len); - if (!flag_ansi_overloading) - cp->b_or_d += b_or_d; - - if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE) == 0) - || (!flag_ansi_overloading && cp->evil == 0)) + if ((cp->h.code & EVIL_CODE) == 0) { cp->u.field = function; cp->function = function; @@ -3380,10 +2209,7 @@ build_method_call (instance, name, parms, basetype_path, flags) /* No "two-level" conversions. */ if (flags & LOOKUP_NO_CONVERSION - && ((flag_ansi_overloading - && (cp->h.code & USER_CODE)) - || (!flag_ansi_overloading - && cp->user != 0))) + && (cp->h.code & USER_CODE)) continue; /* If we used default parameters, we must @@ -3391,14 +2217,8 @@ build_method_call (instance, name, parms, basetype_path, flags) use them also, and report a possible ambiguity. */ if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype) - && ((flag_ansi_overloading - && cp->v.ansi_harshness[len].distance == 0 - && cp->h.code < best) - || (!flag_ansi_overloading - && cp->v.old_harshness[len] == 0 - && CONST_HARSHNESS (cp->v.old_harshness[0]) == 0 - && cp->ellipsis == 0 && cp->user == 0 && cp->b_or_d == 0 - && cp->easy < best))) + && cp->harshness[len].distance == 0 + && cp->h.code < best) { if (! DECL_STATIC_FUNCTION_P (function)) TREE_VALUE (parms) = cp->arg; @@ -3472,12 +2292,10 @@ build_method_call (instance, name, parms, basetype_path, flags) } return error_mark_node; } - if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE)) - || (!flag_ansi_overloading && cp->evil)) + if (cp->h.code & EVIL_CODE) return error_mark_node; } - else if ((flag_ansi_overloading && (cp[-1].h.code & EVIL_CODE)) - || (!flag_ansi_overloading && cp[-1].evil == 2)) + else if (cp[-1].h.code & EVIL_CODE) { if (flags & LOOKUP_COMPLAIN) cp_error ("ambiguous type conversion requested for %s `%D'", @@ -3546,10 +2364,7 @@ build_method_call (instance, name, parms, basetype_path, flags) continue; found_and_maybe_warn: - if (((flag_ansi_overloading - && (cp->v.ansi_harshness[0].code & CONST_CODE)) - || (!flag_ansi_overloading - && CONST_HARSHNESS (cp->v.old_harshness[0]))) + if ((cp->harshness[0].code & CONST_CODE) /* 12.1p2: Constructors can be called for const objects. */ && ! DECL_CONSTRUCTOR_P (cp->function)) { @@ -3869,24 +2684,11 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) if (final_cp) { - if (flag_ansi_overloading) - { - final_cp[0].h.code = 0; - final_cp[0].h.distance = 0; - final_cp[0].function = 0; - /* end marker. */ - final_cp[1].h.code = EVIL_CODE; - } - else - { - final_cp[0].evil = 0; - final_cp[0].user = 0; - final_cp[0].b_or_d = 0; - final_cp[0].easy = 0; - final_cp[0].function = 0; - /* end marker. */ - final_cp[1].evil = 1; - } + final_cp[0].h.code = 0; + final_cp[0].h.distance = 0; + final_cp[0].function = 0; + /* end marker. */ + final_cp[1].h.code = EVIL_CODE; } for (parm = parms; parm; parm = TREE_CHAIN (parm)) @@ -3896,12 +2698,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) if (t == error_mark_node) { if (final_cp) - { - if (flag_ansi_overloading) - final_cp->h.code = EVIL_CODE; - else - final_cp->evil = 1; - } + final_cp->h.code = EVIL_CODE; return error_mark_node; } if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == OFFSET_TYPE) @@ -3920,26 +2717,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) else parmtypes = void_list_node; - if (! flag_ansi_overloading) - { - tree fn; - - /* This is a speed improvement that ends up not working properly in - the situation of fns with and without default parameters. I turned - this off in the new method so it'll go through the argument matching - code to properly diagnose a match/failure. (bpk) */ - overload_name = build_decl_overload (fnname, parmtypes, 0); - fn = lookup_name_nonclass (overload_name); - - /* Now check to see whether or not we can win. - Note that if we are called from `build_method_call', - then we cannot have a mis-match, because we would have - already found such a winning case. */ - - if (fn && TREE_CODE (fn) == FUNCTION_DECL) - return build_function_call (DECL_MAIN_VARIANT (fn), parms); - } - functions = lookup_name_nonclass (fnname); if (functions == NULL_TREE) @@ -3949,12 +2726,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) if (flags & LOOKUP_COMPLAIN) error ("only member functions apply"); if (final_cp) - { - if (flag_ansi_overloading) - final_cp->h.code = EVIL_CODE; - else - final_cp->evil = 1; - } + final_cp->h.code = EVIL_CODE; return error_mark_node; } @@ -3982,12 +2754,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) cp_error ("function `%D' declared overloaded, but no instances of that function declared", TREE_PURPOSE (functions)); if (final_cp) - { - if (flag_ansi_overloading) - final_cp->h.code = EVIL_CODE; - else - final_cp->evil = 1; - } + final_cp->h.code = EVIL_CODE; return error_mark_node; } @@ -4061,10 +2828,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) /* Unconverted template -- failed match. */ cp->function = function; cp->u.bad_arg = -4; - if (flag_ansi_overloading) - cp->h.code = EVIL_CODE; - else - cp->evil = 1; + cp->h.code = EVIL_CODE; } else { @@ -4086,60 +2850,30 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) /* Can't use alloca here, since result might be passed to calling function. */ cp->h_len = parmlength; - if (flag_ansi_overloading) - cp->v.ansi_harshness = (struct harshness_code *) - oballoc ((parmlength + 1) * sizeof (struct harshness_code)); - else - cp->v.old_harshness = (unsigned short *) - oballoc ((parmlength + 1) * sizeof (unsigned short)); + cp->harshness = (struct harshness_code *) + oballoc ((parmlength + 1) * sizeof (struct harshness_code)); compute_conversion_costs (function, parms, cp, parmlength); - if (flag_ansi_overloading) - /* Make sure this is clear as well. */ - cp->h.int_penalty += template_cost; - else - /* Should really add another field... */ - cp->easy = cp->easy * 128 + template_cost; + /* Make sure this is clear as well. */ + cp->h.int_penalty += template_cost; - /* It seemed easier to have both if stmts in here, rather - than excluding the hell out of it with flag_ansi_overloading - everywhere. (bpk) */ - if (flag_ansi_overloading) - { - if ((cp[0].h.code & EVIL_CODE) == 0) - { - cp[1].h.code = EVIL_CODE; - - /* int_penalty is set by convert_harshness_ansi for cases - where we need to know about any penalties that would - otherwise make a TRIVIAL_CODE pass. */ - if (final_cp - && template_cost == 0 - && cp[0].h.code <= TRIVIAL_CODE - && cp[0].h.int_penalty == 0) - { - final_cp[0].h = cp[0].h; - return function; - } - cp++; - } - } - else + if ((cp[0].h.code & EVIL_CODE) == 0) { - if (cp[0].evil == 0) + cp[1].h.code = EVIL_CODE; + + /* int_penalty is set by convert_harshness_ansi for cases + where we need to know about any penalties that would + otherwise make a TRIVIAL_CODE pass. */ + if (final_cp + && template_cost == 0 + && cp[0].h.code <= TRIVIAL_CODE + && cp[0].h.int_penalty == 0) { - cp[1].evil = 1; - if (final_cp - && cp[0].user == 0 && cp[0].b_or_d == 0 - && template_cost == 0 - && cp[0].easy <= 1) - { - final_cp[0].easy = cp[0].easy; - return function; - } - cp++; + final_cp[0].h = cp[0].h; + return function; } + cp++; } } } @@ -4149,10 +2883,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) tree rval = error_mark_node; /* Leave marker. */ - if (flag_ansi_overloading) - cp[0].h.code = EVIL_CODE; - else - cp[0].evil = 1; + cp[0].h.code = EVIL_CODE; if (cp - candidates > 1) { struct candidate *best_cp @@ -4173,8 +2904,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx) else { cp -= 1; - if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE)) - || (!flag_ansi_overloading && cp->evil > 1)) + if (cp->h.code & EVIL_CODE) { if (flags & LOOKUP_COMPLAIN) error ("type conversion ambiguous"); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 27e9a4b0d8c..4fab523b25f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1490,6 +1490,12 @@ finish_base_struct (t, b, t_binfo) if (b->has_virtual == 0) { first_vfn_base_index = i; + + /* Update these two, now that we know what vtable we are + going to extend. This is so that we can add virtual + functions, and override them properly. */ + BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); + BINFO_VIRTUALS (t_binfo) = TYPE_BINFO_VIRTUALS (basetype); b->has_virtual = CLASSTYPE_VSIZE (basetype); b->vfield = CLASSTYPE_VFIELD (basetype); CLASSTYPE_VFIELD (t) = b->vfield; @@ -1678,7 +1684,9 @@ finish_struct_bits (t, max_has_virtual) else conv_index = ptr_conv; } - else if (typecode_p (return_type, INTEGER_TYPE)) + 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; @@ -2160,9 +2168,11 @@ modify_one_vtable (binfo, t, fndecl, pfn) } } - /* Find the right offset for the this pointer based on the base - class we just found. */ - base_offset = BINFO_OFFSET (binfo); + /* Find the right offset for the this pointer based on the + base class we just found. We have to take into + consideration the virtual base class pointers that we + stick in before the virtual function table pointer. */ + base_offset = get_vfield_offset (binfo); this_offset = size_binop (MINUS_EXPR, offset, base_offset); /* Make sure we can modify the derived association with immunity. */ @@ -2929,10 +2939,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) /* Invalid bit-field size done by grokfield. */ /* Detect invalid bit-field type. */ if (DECL_INITIAL (x) - && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE - && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE) + && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) { - cp_error_at ("bit-field `%D' has invalid type", x); + cp_error_at ("bit-field `%#D' with non-integral type", x); DECL_INITIAL (x) = NULL; } @@ -3499,6 +3508,27 @@ finish_struct (t, list_of_fieldlists, warn_anon) } } + /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we + might need to know it for setting up the offsets in the vtable + (or in thunks) below. */ + if (vfield != NULL_TREE + && DECL_FIELD_CONTEXT (vfield) != t) + { + tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); + tree offset = BINFO_OFFSET (binfo); + + vfield = copy_node (vfield); + copy_lang_decl (vfield); + + if (! integer_zerop (offset)) + offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT)); + DECL_FIELD_CONTEXT (vfield) = t; + DECL_CLASS_CONTEXT (vfield) = t; + DECL_FIELD_BITPOS (vfield) + = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield)); + CLASSTYPE_VFIELD (t) = vfield; + } + #ifdef NOTQUITE cp_warning ("Doing hard virtuals for %T...", t); #endif @@ -3739,6 +3769,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) DECL_REGISTER (vtbl_ptr) = 1; CLASSTYPE_VTBL_PTR (t) = vtbl_ptr; } +#if 0 + /* This is now done above. */ if (DECL_FIELD_CONTEXT (vfield) != t) { tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0); @@ -3755,6 +3787,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield)); CLASSTYPE_VFIELD (t) = vfield; } +#endif /* In addition to this one, all the other vfields should be listed. */ /* Before that can be done, we have to have FIELD_DECLs for them, and diff --git a/gcc/cp/class.h b/gcc/cp/class.h index 7e138243c01..6f31e15ee83 100644 --- a/gcc/cp/class.h +++ b/gcc/cp/class.h @@ -39,34 +39,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ and one uses pointers of strictly higher type (derived where another uses base), then that alternative is silently chosen. - If two candidates have a non-monotonic derived/base pointer - relationship, and/or a non-monotonic easy conversion relationship, - then a warning is emitted to show which paths are possible, and - which one is being chosen. - - For example: - - int i; - double x; - - overload f; - int f (int, int); - double f (double, double); - - f (i, x); // draws a warning - - struct B - { - f (int); - } *bb; - struct D : B - { - f (double); - } *dd; - - dd->f (x); // exact match - dd->f (i); // draws warning - Note that this technique really only works for 255 arguments. Perhaps this is not enough. */ @@ -102,36 +74,19 @@ struct harshness_code struct candidate { - /* OLD METHOD */ - unsigned char evil; /* !0 if this will never convert. */ - unsigned char ellipsis; /* !0 if a match against an ellipsis occurred */ - unsigned char user; /* !0 if at least one user-defined type conv. */ - unsigned short b_or_d; /* count number of derived->base or - base->derived conv. */ - unsigned short easy; /* count number of builtin type conv. */ - - /* NEW METHOD */ struct harshness_code h; /* Used for single-argument conversions. */ int h_len; /* The length of the harshness vector. */ - /* Both methods. */ tree function; /* A FUNCTION_DECL */ tree basetypes; /* The path to function. */ tree arg; /* first parm to function. */ - /* This union is only here while we maintain both the old and new - argument matching schemes. When it goes away, all v.ansi_harshness - references will be just `harshness'. */ - union - { - /* Indexed by argument number, encodes evil, user, d_to_b, and easy - strikes for that argument. At end of array, we store the index+1 - of where we started using default parameters, or 0 if there are - none. */ - struct harshness_code *ansi_harshness; /* NEW METHOD */ - unsigned short *old_harshness; /* OLD METHOD */ - } v; + /* Indexed by argument number, encodes evil, user, d_to_b, and easy + strikes for that argument. At end of array, we store the index+1 + of where we started using default parameters, or 0 if there are + none. */ + struct harshness_code *harshness; union { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5d7cfa763d7..061c7f1e28a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -280,11 +280,6 @@ extern int flag_ansi; extern int flag_handle_exceptions; -/* Nonzero means do argument matching for overloading according to the - ANSI rules, rather than what g++ used to believe to be correct. */ - -extern int flag_ansi_overloading; - /* Nonzero means recognize and handle signature language constructs. */ extern int flag_handle_signatures; @@ -1132,6 +1127,10 @@ struct lang_decl || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) +#define INTEGRAL_CODE_P(CODE) \ + (CODE == INTEGER_TYPE || CODE == ENUMERAL_TYPE || CODE == BOOLEAN_TYPE) +#define ARITHMETIC_TYPE_P(TYPE) (INTEGRAL_TYPE_P (TYPE) || FLOAT_TYPE_P (TYPE)) + /* Mark which labels are explicitly declared. These may be shadowed, and may be referenced from nested functions. */ #define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label) @@ -1367,6 +1366,7 @@ extern tree delta_type_node; extern tree long_long_integer_type_node, long_long_unsigned_type_node; /* For building calls to `delete'. */ extern tree integer_two_node, integer_three_node; +extern tree bool_type_node, true_node, false_node; /* in except.c */ extern tree current_exception_type; @@ -1938,6 +1938,7 @@ extern tree reparse_absdcl_as_casts PROTO((tree, tree)); extern tree reparse_decl_as_expr PROTO((tree, tree)); extern tree finish_decl_parsing PROTO((tree)); extern tree lookup_name_nonclass PROTO((tree)); +extern tree check_cp_case_value PROTO((tree)); /* in edsel.c */ @@ -2217,6 +2218,7 @@ extern tree array_type_nelts_total PROTO((tree)); extern tree array_type_nelts_top PROTO((tree)); /* in typeck.c */ +extern tree bool_truthvalue_conversion PROTO((tree)); extern tree target_type PROTO((tree)); extern tree require_complete_type PROTO((tree)); extern int type_unknown_p PROTO((tree)); @@ -2262,6 +2264,9 @@ extern tree build_x_conditional_expr PROTO((tree, tree, tree)); extern tree build_conditional_expr PROTO((tree, tree, tree)); extern tree build_x_compound_expr PROTO((tree)); extern tree build_compound_expr PROTO((tree)); +extern tree build_static_cast PROTO((tree, tree)); +extern tree build_reinterpret_cast PROTO((tree, tree)); +extern tree build_const_cast PROTO((tree, tree)); extern tree build_c_cast PROTO((tree, tree)); extern tree build_modify_expr PROTO((tree, enum tree_code, tree)); extern int language_lvalue_valid PROTO((tree)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index d614c70dbb8..7bfe80233a8 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -186,7 +186,7 @@ cp_convert_to_pointer (type, expr) return expr; } - if (form == INTEGER_TYPE || form == ENUMERAL_TYPE) + if (INTEGRAL_CODE_P (form)) { if (type_precision (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); @@ -950,16 +950,11 @@ convert_to_aggr (type, expr, msgp, protect) { function = fndecl; cp->h_len = 2; - if (flag_ansi_overloading) - cp->v.ansi_harshness = (struct harshness_code *) - alloca (3 * sizeof (struct harshness_code)); - else - cp->v.old_harshness = (unsigned short *) - alloca (3 * sizeof (short)); + cp->harshness = (struct harshness_code *) + alloca (3 * sizeof (struct harshness_code)); compute_conversion_costs (fndecl, parmlist, cp, 2); - if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE) == 0) - || (!flag_ansi_overloading && cp->evil == 0)) + if ((cp->h.code & EVIL_CODE) == 0) { cp->u.field = fndecl; if (protect) @@ -983,10 +978,7 @@ convert_to_aggr (type, expr, msgp, protect) || purpose_member (basetype, DECL_ACCESS (fndecl))) : 1) { - if ((flag_ansi_overloading && cp->h.code <= TRIVIAL_CODE) - || (!flag_ansi_overloading - && cp->user == 0 && cp->b_or_d == 0 - && cp->easy <= 1)) + if (cp->h.code <= TRIVIAL_CODE) goto found_and_ok; cp++; } @@ -1014,8 +1006,7 @@ convert_to_aggr (type, expr, msgp, protect) rank_for_overload); /* int (*compar)() */ --cp; - if ((flag_ansi_overloading && (cp->h.code & EVIL_CODE)) - || (!flag_ansi_overloading && cp->evil > 1)) + if (cp->h.code & EVIL_CODE) { if (msgp) *msgp = "ambiguous type conversion possible for `%s'"; @@ -1235,15 +1226,14 @@ cp_convert (type, expr, convtype, flags) else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); - if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) + if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); /* enum = enum, enum = int, enum = float are all errors. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (type) == ENUMERAL_TYPE - && (form == INTEGER_TYPE || form == REAL_TYPE - || form == ENUMERAL_TYPE)) + && ARITHMETIC_TYPE_P (intype)) { cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type); @@ -1258,9 +1248,23 @@ cp_convert (type, expr, convtype, flags) tree rval; rval = build_type_conversion (CONVERT_EXPR, type, expr, 1); if (rval) return rval; - cp_error ("`%#T' used where an `int' was expected", intype); + if (code == BOOLEAN_TYPE) + cp_error ("`%#T' used where a `bool' was expected", intype); + else + cp_error ("`%#T' used where an `int' was expected", intype); return error_mark_node; } + if (code == BOOLEAN_TYPE) + { + tree newe = truthvalue_conversion (e); + /* Avoid stupid (infinite) recursion from backend. */ + if (TREE_CODE (newe) != NOP_EXPR || e != TREE_OPERAND (newe, 0)) + e = newe; + if (TREE_TYPE (e) == bool_type_node) + return e; + else + return build1 (NOP_EXPR, bool_type_node, e); + } return fold (convert_to_integer (type, e)); } if (code == POINTER_TYPE) @@ -1554,6 +1558,14 @@ 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; @@ -1651,6 +1663,30 @@ build_type_conversion (code, xtype, expr, for_sure) 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 */ @@ -1686,8 +1722,6 @@ build_type_conversion (code, xtype, expr, for_sure) } } - try_pointer: - if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type))) { /* Try converting to some other const pointer type and then using @@ -1747,7 +1781,7 @@ build_type_conversion (code, xtype, expr, for_sure) { /* Only accept using an operator double() if there isn't a conflicting operator int(). */ - if (flag_ansi_overloading && TYPE_HAS_INT_CONVERSION (basetype)) + if (TYPE_HAS_INT_CONVERSION (basetype)) { error ("two possible conversions for type `%s'", TYPE_NAME_STRING (type)); @@ -1758,17 +1792,6 @@ build_type_conversion (code, xtype, expr, for_sure) return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); } - /* THIS IS A KLUDGE. */ - if (TREE_CODE (type) != POINTER_TYPE - && (code == TRUTH_ANDIF_EXPR - || code == TRUTH_ORIF_EXPR - || code == TRUTH_NOT_EXPR)) - { - /* Here's when we can convert to a pointer. */ - type = ptr_type_node; - goto try_pointer; - } - /* THESE ARE TOTAL KLUDGES. */ /* Default promotion yields no new alternatives, try conversions which are anti-default, such as @@ -1777,7 +1800,7 @@ build_type_conversion (code, xtype, expr, for_sure) */ if (type_default == type - && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE)) + && (INTEGRAL_TYPE_P (type) || TREE_CODE (type) == REAL_TYPE)) { int not_again = 0; @@ -1819,19 +1842,10 @@ build_type_conversion (code, xtype, expr, for_sure) /* Now, try C promotions... float -> int - int -> float, void * - void * -> int - - Truthvalue conversions let us try to convert - to pointer if we were going for int, and to int - if we were looking for pointer. */ + int -> float */ basetype = save_basetype; - if (TREE_CODE (type) == REAL_TYPE - || (TREE_CODE (type) == POINTER_TYPE - && (code == TRUTH_ANDIF_EXPR - || code == TRUTH_ORIF_EXPR - || code == TRUTH_NOT_EXPR))) + if (TREE_CODE (type) == REAL_TYPE) type = integer_type_node; else if (TREE_CODE (type) == INTEGER_TYPE) if (TYPE_HAS_REAL_CONVERSION (basetype)) @@ -1917,11 +1931,17 @@ build_default_binary_type_conversion (code, arg1, arg2) return 0; } - if (TYPE_HAS_INT_CONVERSION (type1) && TYPE_HAS_REAL_CONVERSION (type1)) - cp_warning ("ambiguous type conversion for type `%T', defaulting to int", - type1); - if (TYPE_HAS_INT_CONVERSION (type1)) + if (code == TRUTH_ANDIF_EXPR + || code == TRUTH_ORIF_EXPR) { + *arg1 = convert (bool_type_node, *arg1); + *arg2 = convert (bool_type_node, *arg2); + } + else if (TYPE_HAS_INT_CONVERSION (type1)) + { + if (TYPE_HAS_REAL_CONVERSION (type1)) + cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int", + type1); *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1); *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1); } @@ -1956,7 +1976,7 @@ build_default_binary_type_conversion (code, arg1, arg2) return 1; } -/* Must convert two aggregate types to non-aggregate type. +/* Must convert an aggregate type to non-aggregate type. Attempts to find a non-ambiguous, "best" type conversion. Return 1 on success, 0 on failure. @@ -1970,21 +1990,22 @@ build_default_unary_type_conversion (code, arg) tree *arg; { tree type = TREE_TYPE (*arg); - tree id = TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - ? TYPE_IDENTIFIER (type) : TYPE_NAME (type); - char *name = IDENTIFIER_POINTER (id); if (! TYPE_HAS_CONVERSION (type)) { - error ("type conversion required for type `%s'", name); + cp_error ("type conversion required for type `%T'", type); return 0; } - if (TYPE_HAS_INT_CONVERSION (type) && TYPE_HAS_REAL_CONVERSION (type)) - warning ("ambiguous type conversion for type `%s', defaulting to int", - name); - if (TYPE_HAS_INT_CONVERSION (type)) - *arg = build_type_conversion (code, integer_type_node, *arg, 1); + if (code == TRUTH_NOT_EXPR) + *arg = convert (bool_type_node, *arg); + else if (TYPE_HAS_INT_CONVERSION (type)) + { + if (TYPE_HAS_REAL_CONVERSION (type)) + cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int", + type); + *arg = build_type_conversion (code, integer_type_node, *arg, 1); + } else if (TYPE_HAS_REAL_CONVERSION (type)) *arg = build_type_conversion (code, double_type_node, *arg, 1); else @@ -1995,7 +2016,7 @@ build_default_unary_type_conversion (code, arg) } if (*arg == NULL_TREE) { - error ("default type conversion for type `%s' failed", name); + cp_error ("default type conversion for type `%T' failed", type); return 0; } return 1; @@ -2009,17 +2030,21 @@ type_promotes_to (type) int constp = TYPE_READONLY (type); int volatilep = TYPE_VOLATILE (type); type = TYPE_MAIN_VARIANT (type); - - /* Normally convert enums to int, - but convert wide enums to something wider. */ - if (TREE_CODE (type) == ENUMERAL_TYPE - || type == wchar_type_node) - type = type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - ((flag_traditional - || (TYPE_PRECISION (type) - >= TYPE_PRECISION (integer_type_node))) - && TREE_UNSIGNED (type))); + + /* bool always promotes to int (not unsigned), even if it's the same + size. */ + if (type == bool_type_node) + type = integer_type_node; + + /* Normally convert enums to int, but convert wide enums to something + wider. */ + else if (TREE_CODE (type) == ENUMERAL_TYPE + || type == wchar_type_node) + type = type_for_size + (MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)), + (flag_traditional + || (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))) + && TREE_UNSIGNED (type)); else if (C_PROMOTING_INTEGER_TYPE_P (type)) { /* Traditionally, unsignedness is preserved in default promotions. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1c9905f7b36..fd73388d65d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -204,6 +204,9 @@ tree int_array_type_node; tree wchar_array_type_node; +/* The bool data type, and constants */ +tree bool_type_node, true_node, false_node; + /* type `int ()' -- used for implicit declaration of functions. */ tree default_function_type; @@ -412,9 +415,7 @@ extern int flag_no_builtin; extern int flag_implement_inlines; -/* Nonzero means handle things in ANSI, instead of GNU fashion. This - flag should be tested for language behavior that's different between - ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */ +/* Nonzero means disable GNU extensions. */ extern int flag_ansi; @@ -1709,7 +1710,7 @@ pushtag (name, type, globalize) { register struct binding_level *b; tree context = 0; - tree cdecl = 0; + tree c_decl = 0; b = inner_binding_level; while (b->tag_transparent @@ -1727,7 +1728,7 @@ pushtag (name, type, globalize) if (! context && ! globalize) context = current_scope (); if (context) - cdecl = TREE_CODE (context) == FUNCTION_DECL + c_decl = TREE_CODE (context) == FUNCTION_DECL ? context : TYPE_NAME (context); /* Record the identifier as the type's name if it has none. */ @@ -1746,7 +1747,7 @@ pushtag (name, type, globalize) if (b->parm_flag != 2 || TYPE_SIZE (current_class_type) != NULL_TREE) { - d = lookup_nested_type (type, cdecl); + d = lookup_nested_type (type, c_decl); if (d == NULL_TREE) { @@ -1824,7 +1825,7 @@ pushtag (name, type, globalize) else if (context && TREE_CODE (context) == FUNCTION_DECL) { /* Function-nested class. */ - set_nested_typename (d, DECL_ASSEMBLER_NAME (cdecl), + set_nested_typename (d, DECL_ASSEMBLER_NAME (c_decl), name, type); /* This builds the links for classes nested in fn scope. */ DECL_CONTEXT (d) = context; @@ -1834,7 +1835,7 @@ pushtag (name, type, globalize) else if (context && TREE_CODE (context) == RECORD_TYPE) { /* Class-nested class. */ - set_nested_typename (d, DECL_NESTED_TYPENAME (cdecl), + set_nested_typename (d, DECL_NESTED_TYPENAME (c_decl), name, type); /* This builds the links for classes nested in type scope. */ DECL_CONTEXT (d) = context; @@ -4373,6 +4374,14 @@ init_decl_processing () TREE_TYPE (integer_three_node) = integer_type_node; empty_init_node = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE); + bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE); + TREE_SET_CODE (bool_type_node, BOOLEAN_TYPE); + record_builtin_type (RID_BOOL, "bool", bool_type_node); + false_node = build_int_2 (0, 0); + TREE_TYPE (false_node) = bool_type_node; + true_node = build_int_2 (1, 0); + TREE_TYPE (true_node) = bool_type_node; + /* These are needed by stor-layout.c. */ size_zero_node = size_int (0); size_one_node = size_int (1); @@ -5007,7 +5016,7 @@ shadow_tag (declspecs) { int found_tag = 0; int warned = 0; - int static_or_extern = 0; + tree ob_modifier = NULL_TREE; register tree link; register enum tree_code code, ok_code = ERROR_MARK; register tree t = NULL_TREE; @@ -5018,11 +5027,12 @@ shadow_tag (declspecs) code = TREE_CODE (value); if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE) - /* Used to test also that TYPE_SIZE (value) != 0. - That caused warning for `struct foo;' at top level in the file. */ { register tree name = TYPE_NAME (value); + if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0) + cp_error ("forward declaration of `%#T'", value); + if (name == NULL_TREE) name = lookup_tag_reverse (value, NULL_TREE); @@ -5041,7 +5051,6 @@ shadow_tag (declspecs) pushtag (name, t, 0); pop_obstacks (); ok_code = code; - break; } else if (name != NULL_TREE || code == ENUMERAL_TYPE) ok_code = code; @@ -5056,8 +5065,10 @@ shadow_tag (declspecs) } } else if (value == ridpointers[(int) RID_STATIC] - || value == ridpointers[(int) RID_EXTERN]) - static_or_extern = 1; + || value == ridpointers[(int) RID_EXTERN] + || value == ridpointers[(int) RID_AUTO] + || value == ridpointers[(int) RID_REGISTER]) + ob_modifier = value; } /* This is where the variables in an anonymous union are @@ -5086,9 +5097,10 @@ shadow_tag (declspecs) else { /* Anonymous unions are objects, that's why we only check for - static/extern specifiers in this branch. */ - if (static_or_extern) - error ("static/extern can only be specified for objects and functions"); + inappropriate specifiers in this branch. */ + if (ob_modifier) + cp_error ("`%D' can only be specified for objects and functions", + ob_modifier); if (ok_code == RECORD_TYPE && found_tag == 1 @@ -5113,8 +5125,10 @@ shadow_tag (declspecs) pop_obstacks (); } } + else if (found_tag == 0) + pedwarn ("abstract declarator used as declaration"); else if (!warned && found_tag > 1) - warning ("multiple types in one declaration"); + pedwarn ("multiple types in one declaration"); } } @@ -5967,14 +5981,16 @@ finish_decl (decl, init, asmspec_tree, need_pop) && (TYPE_READONLY (type) || TREE_READONLY (decl))) cp_error ("uninitialized const `%D'", decl); - /* Initialize variables in need of static initialization - with `empty_init_node' to keep assemble_variable from putting them - in the wrong program space. (Common storage is okay for non-public - uninitialized data; the linker can't match it with storage from other - files, and we may save some disk space.) */ + /* Initialize variables in need of static initialization with + `empty_init_node' to keep assemble_variable from putting them in + the wrong program space. Common storage is okay for non-public + uninitialized data; the linker can't match it with storage from + other files, and we may save some disk space. Consts have to go + into data, though, since the backend would put them in text + otherwise. */ if (flag_pic == 0 && TREE_STATIC (decl) - && TREE_PUBLIC (decl) + && (TREE_PUBLIC (decl) || was_readonly) && ! DECL_EXTERNAL (decl) && TREE_CODE (decl) == VAR_DECL && TYPE_NEEDS_CONSTRUCTING (type) @@ -7341,6 +7357,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } goto found; } + if (id == ridpointers[(int) RID_BOOL]) + { + if (type) + error ("extraneous `bool' ignored"); + else + { + type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id)); + } + goto found; + } if (id == ridpointers[(int) RID_WCHAR]) { if (type) @@ -7445,7 +7471,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Save warning until we know what is really going on. */ warn_about_return_type = 1; } - else if (class_binding_level && declarator + else if (decl_context == FIELD && declarator && TREE_CODE (declarator) == SCOPE_REF) /* OK -- access declaration */; else if (declspecs == NULL_TREE && @@ -8007,7 +8033,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } if (TREE_READONLY_DECL_P (size)) size = decl_constant_value (size); - if (pedantic && integer_zerop (size)) + if (flag_ansi && integer_zerop (size)) cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname); if (TREE_CONSTANT (size)) { @@ -8022,7 +8048,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } else { - if (pedantic) + if (flag_ansi) cp_pedwarn ("ANSI C++ forbids variable-size array `%D'", dname); dont_grok_size: @@ -8909,7 +8935,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 (pedantic || flag_ansi || ! constp) + else if (flag_ansi || ! constp) pedwarn ("ANSI C++ forbids initialization of %s `%s'", constp ? "const member" : "member", IDENTIFIER_POINTER (declarator)); @@ -9061,7 +9087,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (RIDBIT_SETP (RID_EXTERN, specbits)) { current_extern_inline = 1; - if (flag_ansi || pedantic || flag_pedantic_errors) + if (flag_ansi) pedwarn ("ANSI C++ does not permit `extern inline'"); } } @@ -10245,31 +10271,34 @@ finish_enum (enumtype, values) register HOST_WIDE_INT minvalue = 0; register HOST_WIDE_INT i; - TYPE_VALUES (enumtype) = values; - /* Calculate the maximum value of any enumerator in this type. */ if (values) { /* Speed up the main loop by performing some precalculations */ - HOST_WIDE_INT value = TREE_INT_CST_LOW (TREE_VALUE (values)); + HOST_WIDE_INT value; TREE_TYPE (TREE_VALUE (values)) = enumtype; TREE_TYPE (DECL_INITIAL (TREE_VALUE (values))) = enumtype; + TREE_VALUE (values) = DECL_INITIAL (TREE_VALUE (values)); + value = TREE_INT_CST_LOW (TREE_VALUE (values)); minvalue = maxvalue = value; for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) { + TREE_TYPE (TREE_VALUE (pair)) = enumtype; + TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype; + TREE_VALUE (pair) = DECL_INITIAL (TREE_VALUE (pair)); value = TREE_INT_CST_LOW (TREE_VALUE (pair)); if (value > maxvalue) maxvalue = value; else if (value < minvalue) minvalue = value; - TREE_TYPE (TREE_VALUE (pair)) = enumtype; - TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype; } } + TYPE_VALUES (enumtype) = values; + if (flag_short_enums) { /* Determine the precision this type needs, lay it out, and define @@ -10970,7 +10999,7 @@ store_return_init (return_id, init) { tree decl = DECL_RESULT (current_function_decl); - if (pedantic) + if (flag_ansi) /* 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. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c5ab8dbd7fc..55414dfba2a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -96,17 +96,10 @@ int flag_signed_bitfields = 1; int flag_no_ident = 0; -/* Nonzero means handle things in ANSI, instead of GNU fashion. This - flag should be tested for language behavior that's different between - ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */ +/* Nonzero means disable GNU extensions. */ int flag_ansi = 0; -/* Nonzero means do argument matching for overloading according to the - ANSI rules, rather than what g++ used to believe to be correct. */ - -int flag_ansi_overloading = 1; - /* Nonzero means do emit exported implementations of functions even if they can be inlined. */ @@ -359,7 +352,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"nonnull-objects", &flag_assume_nonnull_objects, 1}, {"implement-inlines", &flag_implement_inlines, 1}, {"external-templates", &flag_external_templates, 1}, - {"ansi-overloading", &flag_ansi_overloading, 1}, {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, @@ -797,9 +789,11 @@ grokclassfn (ctype, cname, function, flags, quals) we may wish to make it special. */ tree type = TREE_VALUE (arg_types); - if (flags == DTOR_FLAG) + if ((flag_this_is_variable > 0) + && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))) type = TYPE_MAIN_VARIANT (type); - else if (DECL_CONSTRUCTOR_P (function)) + + if (DECL_CONSTRUCTOR_P (function)) { if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) { @@ -824,14 +818,7 @@ grokclassfn (ctype, cname, function, flags, quals) /* We can make this a register, so long as we don't accidentally complain if someone tries to take its address. */ DECL_REGISTER (parm) = 1; -#if 0 - /* it is wrong to flag the object as readonly, when - flag_this_is_variable is 0. */ - if (flags != DTOR_FLAG - && (flag_this_is_variable <= 0 || TYPE_READONLY (type))) -#else - if (flags != DTOR_FLAG && TYPE_READONLY (type)) -#endif + if (TYPE_READONLY (type)) TREE_READONLY (parm) = 1; TREE_CHAIN (parm) = last_function_parms; last_function_parms = parm; @@ -1044,7 +1031,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete) case 2: maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1); if (! flag_traditional) - pedwarn ("ANSI C++ forbids array size in vector delete"); + pedwarn ("anachronistic use of array size in vector delete"); /* Fall through. */ case 1: elt_size = c_sizeof (type); @@ -1800,7 +1787,7 @@ build_push_scope (cname, name) void cplus_decl_attributes (decl, attributes) tree decl, attributes; { - if (decl) + if (decl && decl != void_type_node) decl_attributes (decl, attributes); } @@ -2952,3 +2939,43 @@ finish_decl_parsing (decl) return NULL_TREE; } } + +tree +check_cp_case_value (value) + tree value; +{ + if (value == NULL_TREE) + return value; + + /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. + Strip such NOP_EXPRs. */ + if (TREE_CODE (value) == NOP_EXPR + && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) + value = TREE_OPERAND (value, 0); + + if (TREE_READONLY_DECL_P (value)) + { + value = decl_constant_value (value); + /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. + Strip such NOP_EXPRs. */ + if (TREE_CODE (value) == NOP_EXPR + && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) + value = TREE_OPERAND (value, 0); + } + value = fold (value); + + if (TREE_CODE (value) != INTEGER_CST + && value != error_mark_node) + { + cp_error ("case label `%E' does not reduce to an integer constant", + value); + value = error_mark_node; + } + else + /* Promote char or short to int. */ + value = default_conversion (value); + + constant_expression_warning (value); + + return value; +} diff --git a/gcc/cp/errfn.c b/gcc/cp/errfn.c index 2cf2b87ff23..1b345fda9c2 100644 --- a/gcc/cp/errfn.c +++ b/gcc/cp/errfn.c @@ -120,7 +120,7 @@ cp_thing (errfn, atarg1, format, arglist) if (arg >= NARGS) abort (); - if (maybe_here && atarg) + if (maybe_here && atarg1) atarg = args[arg]; /* Must use a temporary to avoid calling *function twice */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 629c70b92b1..6d2ec7fc8b8 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -198,6 +198,7 @@ dump_type (t, v) /* fall through. */ case REAL_TYPE: case VOID_TYPE: + case BOOLEAN_TYPE: dump_readonly_or_volatile (t, after); OB_PUTID (TYPE_IDENTIFIER (t)); break; @@ -356,6 +357,10 @@ dump_type_prefix (t, v) switch (TREE_CODE (sub)) { + case ARRAY_TYPE: + OB_PUTC2 (' ', '('); + break; + case POINTER_TYPE: /* We don't want "char * &" */ if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub))) @@ -405,6 +410,7 @@ dump_type_prefix (t, v) case ERROR_MARK: case IDENTIFIER_NODE: case INTEGER_TYPE: + case BOOLEAN_TYPE: case REAL_TYPE: case RECORD_TYPE: case TEMPLATE_TYPE_PARM: @@ -476,6 +482,7 @@ dump_type_suffix (t, v) case ERROR_MARK: case IDENTIFIER_NODE: case INTEGER_TYPE: + case BOOLEAN_TYPE: case REAL_TYPE: case RECORD_TYPE: case TEMPLATE_TYPE_PARM: diff --git a/gcc/cp/gxx.gperf b/gcc/cp/gxx.gperf index a3585341614..aa59484a305 100644 --- a/gcc/cp/gxx.gperf +++ b/gcc/cp/gxx.gperf @@ -28,6 +28,7 @@ __volatile__, TYPE_QUAL, RID_VOLATILE __wchar_t, TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */, asm, ASM_KEYWORD, NORID, auto, SCSPEC, RID_AUTO, +bool, TYPESPEC, RID_BOOL, break, BREAK, NORID, case, CASE, NORID, catch, CATCH, NORID, @@ -45,6 +46,7 @@ dynamic_cast, DYNAMIC_CAST, NORID, else, ELSE, NORID, enum, ENUM, NORID, extern, SCSPEC, RID_EXTERN, +false, CXX_FALSE, NORID, float, TYPESPEC, RID_FLOAT, for, FOR, NORID, friend, SCSPEC, RID_FRIEND, @@ -76,6 +78,7 @@ switch, SWITCH, NORID, this, THIS, NORID, throw, THROW, NORID, template, TEMPLATE, RID_TEMPLATE, +true, CXX_TRUE, NORID, try, TRY, NORID, typedef, SCSPEC, RID_TYPEDEF, typeof, TYPEOF, NORID, diff --git a/gcc/cp/hash.h b/gcc/cp/hash.h index 0780d025d32..8453c4bec35 100644 --- a/gcc/cp/hash.h +++ b/gcc/cp/hash.h @@ -3,12 +3,12 @@ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */ struct resword { char *name; short token; enum rid rid;}; -#define TOTAL_KEYWORDS 83 +#define TOTAL_KEYWORDS 86 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 16 #define MIN_HASH_VALUE 4 -#define MAX_HASH_VALUE 170 -/* maximum key range = 167, duplicates = 0 */ +#define MAX_HASH_VALUE 171 +/* maximum key range = 168, duplicates = 0 */ #ifdef __GNUC__ inline @@ -20,19 +20,19 @@ hash (str, len) { static unsigned char asso_values[] = { - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, - 171, 171, 171, 171, 171, 0, 171, 62, 5, 65, - 27, 0, 18, 7, 10, 48, 171, 1, 30, 7, - 79, 0, 33, 171, 18, 0, 4, 26, 13, 0, - 1, 24, 171, 171, 171, 171, 171, 171, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 0, 172, 36, 1, 61, + 0, 0, 30, 44, 44, 35, 172, 7, 12, 53, + 40, 17, 6, 172, 28, 2, 4, 35, 31, 51, + 5, 7, 172, 172, 172, 172, 172, 172, }; register int hval = len; @@ -65,120 +65,120 @@ is_reserved_word (str, len) { {"",}, {"",}, {"",}, {"",}, {"else", ELSE, NORID,}, - {"",}, {"",}, + {"",}, + {"delete", DELETE, NORID,}, + {"double", TYPESPEC, RID_DOUBLE,}, + {"true", CXX_TRUE, NORID,}, {"__asm__", GCC_ASM_KEYWORD, NORID}, + {"typeid", TYPEID, NORID,}, + {"",}, {"this", THIS, NORID,}, - {"throw", THROW, NORID,}, + {"",}, + {"try", TRY, NORID,}, + {"",}, {"",}, {"",}, {"",}, + {"do", DO, NORID,}, + {"",}, + {"static_cast", STATIC_CAST, NORID,}, + {"template", TEMPLATE, RID_TEMPLATE,}, + {"protected", VISSPEC, RID_PROTECTED,}, + {"",}, + {"__classof__", CLASSOF, NORID}, + {"",}, {"__headof__", HEADOF, NORID}, - {"goto", GOTO, NORID,}, - {"__asm", GCC_ASM_KEYWORD, NORID}, + {"",}, + {"bool", TYPESPEC, RID_BOOL,}, {"__const__", TYPE_QUAL, RID_CONST}, {"__volatile", TYPE_QUAL, RID_VOLATILE}, {"__const", TYPE_QUAL, RID_CONST}, {"__volatile__", TYPE_QUAL, RID_VOLATILE}, - {"",}, - {"enum", ENUM, NORID,}, - {"static_cast", STATIC_CAST, NORID,}, - {"switch", SWITCH, NORID,}, - {"",}, {"",}, - {"sigof", SIGOF, NORID /* Extension */,}, + {"__typeof__", TYPEOF, NORID}, + {"void", TYPESPEC, RID_VOID,}, + {"friend", SCSPEC, RID_FRIEND,}, + {"false", CXX_FALSE, NORID,}, {"sizeof", SIZEOF, NORID,}, - {"",}, - {"__headof", HEADOF, NORID}, {"short", TYPESPEC, RID_SHORT,}, {"typeof", TYPEOF, NORID,}, - {"do", DO, NORID,}, - {"",}, - {"try", TRY, NORID,}, - {"",}, - {"delete", DELETE, NORID,}, - {"__typeof__", TYPEOF, NORID}, - {"while", WHILE, NORID,}, - {"struct", AGGR, RID_RECORD,}, - {"typeid", TYPEID, NORID,}, - {"double", TYPESPEC, RID_DOUBLE,}, - {"for", FOR, NORID,}, - {"",}, - {"__classof__", CLASSOF, NORID}, - {"",}, {"",}, - {"operator", OPERATOR, NORID,}, - {"",}, {"",}, - {"typedef", SCSPEC, RID_TYPEDEF,}, - {"long", TYPESPEC, RID_LONG,}, - {"template", TEMPLATE, RID_TEMPLATE,}, - {"__typeof", TYPEOF, NORID}, - {"friend", SCSPEC, RID_FRIEND,}, - {"",}, - {"private", VISSPEC, RID_PRIVATE,}, {"",}, {"int", TYPESPEC, RID_INT,}, - {"",}, - {"__classof", CLASSOF, NORID}, + {"__signed", TYPESPEC, RID_SIGNED}, + {"private", VISSPEC, RID_PRIVATE,}, {"__signed__", TYPESPEC, RID_SIGNED}, - {"",}, {"",}, - {"headof", HEADOF, NORID,}, - {"",}, + {"extern", SCSPEC, RID_EXTERN,}, + {"struct", AGGR, RID_RECORD,}, + {"signed", TYPESPEC, RID_SIGNED,}, + {"break", BREAK, NORID,}, {"__attribute", ATTRIBUTE, NORID}, - {"",}, + {"default", DEFAULT, NORID,}, {"__attribute__", ATTRIBUTE, NORID}, - {"auto", SCSPEC, RID_AUTO,}, + {"__classof", CLASSOF, NORID}, + {"sigof", SIGOF, NORID /* Extension */,}, + {"__headof", HEADOF, NORID}, + {"switch", SWITCH, NORID,}, + {"__label__", LABEL, NORID}, + {"__extension__", EXTENSION, NORID}, + {"",}, + {"__asm", GCC_ASM_KEYWORD, NORID}, + {"for", FOR, NORID,}, + {"__typeof", TYPEOF, NORID}, + {"__alignof__", ALIGNOF, NORID}, {"",}, - {"if", IF, NORID,}, {"case", CASE, NORID,}, + {"virtual", SCSPEC, RID_VIRTUAL,}, + {"if", IF, NORID,}, + {"while", WHILE, NORID,}, + {"",}, {"class", AGGR, RID_CLASS,}, - {"void", TYPESPEC, RID_VOID,}, - {"asm", ASM_KEYWORD, NORID,}, - {"break", BREAK, NORID,}, + {"typedef", SCSPEC, RID_TYPEDEF,}, {"const", TYPE_QUAL, RID_CONST,}, {"static", SCSPEC, RID_STATIC,}, - {"mutable", SCSPEC, RID_MUTABLE,}, - {"protected", VISSPEC, RID_PROTECTED,}, - {"",}, {"",}, {"",}, {"",}, - {"new", NEW, NORID,}, - {"__signed", TYPESPEC, RID_SIGNED}, - {"virtual", SCSPEC, RID_VIRTUAL,}, - {"extern", SCSPEC, RID_EXTERN,}, - {"",}, {"",}, {"",}, + {"auto", SCSPEC, RID_AUTO,}, {"float", TYPESPEC, RID_FLOAT,}, + {"inline", SCSPEC, RID_INLINE,}, + {"throw", THROW, NORID,}, + {"unsigned", TYPESPEC, RID_UNSIGNED,}, + {"",}, + {"headof", HEADOF, NORID,}, + {"",}, + {"goto", GOTO, NORID,}, {"",}, {"",}, + {"public", VISSPEC, RID_PUBLIC,}, + {"signature", AGGR, RID_SIGNATURE /* Extension */,}, + {"volatile", TYPE_QUAL, RID_VOLATILE,}, + {"__inline", SCSPEC, RID_INLINE}, + {"overload", OVERLOAD, NORID,}, + {"__inline__", SCSPEC, RID_INLINE}, + {"__alignof", ALIGNOF, NORID}, + {"asm", ASM_KEYWORD, NORID,}, + {"",}, + {"new", NEW, NORID,}, + {"",}, + {"mutable", SCSPEC, RID_MUTABLE,}, + {"union", AGGR, RID_UNION,}, + {"operator", OPERATOR, NORID,}, {"register", SCSPEC, RID_REGISTER,}, - {"__extension__", EXTENSION, NORID}, {"",}, {"",}, {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, - {"",}, {"",}, {"",}, {"",}, - {"__label__", LABEL, NORID}, - {"inline", SCSPEC, RID_INLINE,}, + {"",}, + {"long", TYPESPEC, RID_LONG,}, + {"",}, {"",}, {"",}, {"continue", CONTINUE, NORID,}, - {"default", DEFAULT, NORID,}, - {"char", TYPESPEC, RID_CHAR,}, + {"return", RETURN, NORID,}, + {"enum", ENUM, NORID,}, {"",}, {"",}, - {"classof", CLASSOF, NORID,}, - {"unsigned", TYPESPEC, RID_UNSIGNED,}, - {"union", AGGR, RID_UNION,}, - {"",}, - {"signed", TYPESPEC, RID_SIGNED,}, - {"volatile", TYPE_QUAL, RID_VOLATILE,}, - {"signature", AGGR, RID_SIGNATURE /* Extension */,}, - {"overload", OVERLOAD, NORID,}, + {"dynamic_cast", DYNAMIC_CAST, NORID,}, + {"",}, {"",}, + {"reinterpret_cast", REINTERPRET_CAST, NORID,}, {"",}, {"",}, {"",}, {"",}, - {"__alignof__", ALIGNOF, NORID}, + {"char", TYPESPEC, RID_CHAR,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"return", RETURN, NORID,}, - {"",}, {"",}, {"",}, {"",}, - {"public", VISSPEC, RID_PUBLIC,}, - {"reinterpret_cast", REINTERPRET_CAST, NORID,}, - {"__alignof", ALIGNOF, NORID}, + {"classof", CLASSOF, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"const_cast", CONST_CAST, NORID,}, - {"catch", CATCH, NORID,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"",}, {"",}, - {"__inline", SCSPEC, RID_INLINE}, - {"",}, - {"__inline__", SCSPEC, RID_INLINE}, - {"",}, - {"dynamic_cast", DYNAMIC_CAST, NORID,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, + {"catch", CATCH, NORID,}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 6ce92a3d0d4..186741421c2 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3566,7 +3566,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) if (TREE_CODE (type) == POINTER_TYPE) { - type = TREE_TYPE (type); + type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (TYPE_SIZE (type) == 0) { incomplete_type_error (0, type); @@ -3582,6 +3582,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) } if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); + + /* throw away const and volatile on target type of addr */ + addr = convert_force (build_pointer_type (type), addr); ref = build_indirect_ref (addr, NULL_PTR); ptr = 1; } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 22cf0a51cd8..595ba826667 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -577,6 +577,9 @@ init_lex () ridpointers[(int) RID_INT] = get_identifier ("int"); SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT], build_tree_list (NULL_TREE, ridpointers[(int) RID_INT])); + ridpointers[(int) RID_BOOL] = get_identifier ("bool"); + SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL], + build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL])); ridpointers[(int) RID_CHAR] = get_identifier ("char"); SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR], build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR])); @@ -4442,9 +4445,9 @@ real_yylex () value = MIN_MAX; nextchar = c1; } - if (pedantic) - error ("use of `operator %s' is not standard C++", - token_buffer); + if (flag_ansi) + pedwarn ("use of `operator %s' is not standard C++", + token_buffer); goto done; } diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index f9bf3f1aea3..a9ea60efa0a 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -26,6 +26,7 @@ enum rid { RID_UNUSED, RID_INT, + RID_BOOL, RID_CHAR, RID_WCHAR, RID_FLOAT, diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d4ce558abb9..d0b847e8789 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -366,6 +366,11 @@ build_overload_value (type, value) icat (TREE_INT_CST_LOW (value)); return; } + case BOOLEAN_TYPE: + { + icat (TREE_INT_CST_LOW (value)); + return; + } #ifndef REAL_IS_NOT_DOUBLE case REAL_TYPE: { @@ -587,10 +592,7 @@ build_overload_name (parmtypes, begin, end) OB_PUTC ('A'); if (TYPE_DOMAIN (parmtype) == NULL_TREE) - { - error ("parameter type with unspecified array bounds invalid"); - icat (1); - } + error ("pointer or reference to array of unknown bound in parm type"); else { length = array_type_nelts (parmtype); @@ -701,6 +703,10 @@ build_overload_name (parmtypes, begin, end) my_friendly_abort (73); break; + case BOOLEAN_TYPE: + OB_PUTC ('b'); + break; + case REAL_TYPE: parmtype = TYPE_MAIN_VARIANT (parmtype); if (parmtype == long_double_type_node) @@ -1703,7 +1709,7 @@ emit_thunk (thunk_fndecl) int delta = THUNK_DELTA (thunk_fndecl); int tem; int failure = 0; - extern int current_call_is_indirect; /* Needed for (at least) HPPA. */ + int current_call_is_indirect = 0; /* needed for HPPA FUNCTION_ARG */ /* Used to remember which regs we need to emit a USE rtx for. */ rtx need_use[FIRST_PSEUDO_REGISTER]; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index dd8a96ab5c6..30e076c6579 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -149,7 +149,7 @@ empty_parms () /* the reserved words... C++ extensions */ %token <ttype> AGGR %token <itype> VISSPEC -%token DELETE NEW OVERLOAD THIS OPERATOR +%token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE %token LEFT_RIGHT TEMPLATE %token TYPEID DYNAMIC_CAST STATIC_CAST REINTERPRET_CAST CONST_CAST %token <itype> SCOPE @@ -197,14 +197,15 @@ empty_parms () %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist %type <ttype> paren_expr_or_null nontrivial_exprlist %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING -%type <ttype> typed_declspecs reserved_declspecs +%type <ttype> typed_declspecs reserved_declspecs boolean.literal %type <ttype> typed_typespecs reserved_typespecquals %type <ttype> declmods typespec typespecqual_reserved %type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual %type <itype> initdecls notype_initdecls initdcl /* C++ modification */ %type <ttype> init initlist maybeasm %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers -%type <ttype> maybe_attribute attribute_list attrib +%type <ttype> maybe_attribute attributes attribute attribute_list attrib +%type <ttype> any_word %type <ttype> compstmt implicitly_scoped_stmt @@ -284,7 +285,6 @@ static tree current_aggr; #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL) extern void yyprint (); extern tree combine_strings PROTO((tree)); -extern tree truthvalue_conversion PROTO((tree)); %} %% @@ -320,8 +320,7 @@ extdefs: ; asm_keyword: - ASM_KEYWORD { if (pedantic) - pedwarn ("ANSI C++ forbids use of `asm' keyword"); } + ASM_KEYWORD | GCC_ASM_KEYWORD ; @@ -551,15 +550,6 @@ datadef: else if (CLASSTYPE_USE_TEMPLATE (t) == 1) error ("override declaration for already-expanded template"); } - else if (TREE_CODE (t) == ENUMERAL_TYPE - && !TYPE_SIZE (t)) - cp_error ("forward declaration of `%#T'", t); - else if (TREE_CODE (t) == IDENTIFIER_NODE) - { - tree v = lookup_name (t, 1); - cp_error ("abstract declarator `%T' used as declaration", - v); - } } note_list_got_semicolon ($<ttype>$); } @@ -1098,7 +1088,7 @@ new_initializer: syntactically valid but semantically invalid. */ | '=' init { - if (pedantic || flag_ansi) + if (flag_ansi) pedwarn ("ANSI C++ forbids initialization of new expression with `='"); $$ = $2; } @@ -1125,7 +1115,7 @@ cast_expr: { tree init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($3)); - if (pedantic) + if (flag_ansi) pedwarn ("ANSI C++ forbids constructor-expressions"); /* Indicate that this was a GNU C constructor expression. */ TREE_HAS_CONSTRUCTOR (init) = 1; @@ -1279,6 +1269,7 @@ primary: $$ = do_identifier ($$); } | CONSTANT + | boolean.literal | string { $$ = combine_strings ($$); } | '(' expr ')' @@ -1295,7 +1286,7 @@ primary: $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' { tree rtl_exp; - if (pedantic) + if (flag_ansi) pedwarn ("ANSI C++ forbids braced-groups within expressions"); rtl_exp = expand_end_stmt_expr ($<ttype>2); /* The statements have side effects, so the group does. */ @@ -1576,7 +1567,7 @@ primary_no_id: } $<ttype>$ = expand_start_stmt_expr (); } compstmt ')' - { if (pedantic) + { if (flag_ansi) pedwarn ("ANSI C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($<ttype>2); } | primary_no_id '(' nonnull_exprlist ')' @@ -1611,6 +1602,13 @@ delete: DELETE { got_scope = NULL_TREE; $$ = 1; } ; +boolean.literal: + CXX_TRUE + { $$ = true_node; } + | CXX_FALSE + { $$ = false_node; } + ; + /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */ string: STRING @@ -1802,11 +1800,11 @@ typespec: structsp | complete_type_name | TYPEOF '(' expr ')' { $$ = TREE_TYPE ($3); - if (pedantic) + if (flag_ansi) pedwarn ("ANSI C++ forbids `typeof'"); } | TYPEOF '(' type_id ')' { $$ = groktypename ($3); - if (pedantic) + if (flag_ansi) pedwarn ("ANSI C++ forbids `typeof'"); } | SIGOF '(' expr ')' { tree type = TREE_TYPE ($3); @@ -1912,9 +1910,9 @@ initdcl: /* Note how the declaration of the variable is in effect while its init is parsed! */ { finish_decl ($<ttype>6, $7, $3, 0); } | declarator maybe_raises maybeasm maybe_attribute - { tree d = start_decl ($<ttype>1, current_declspecs, 0, $2); + { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0, $2); cplus_decl_attributes ($<ttype>$, $4); - finish_decl (d, NULL_TREE, $3, 0); } + finish_decl ($<ttype>$, NULL_TREE, $3, 0); } ; notype_initdcl0: @@ -1958,64 +1956,53 @@ nomods_initdcl0: /* the * rules are dummies to accept the Apollo extended syntax so that the header files compile. */ maybe_attribute: + /* empty */ + { $$ = NULL_TREE; } + | attributes + { $$ = $1; } + ; + +attributes: + attribute + { $$ = $1; } + | attributes attribute + { $$ = chainon ($1, $2); } + ; + +attribute: + ATTRIBUTE '(' '(' attribute_list ')' ')' + { $$ = $4; } + ; + +attribute_list: + attrib + { $$ = build_tree_list (NULL_TREE, $1); } + | attribute_list ',' attrib + { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); } + ; + +attrib: /* empty */ - { $$ = NULL_TREE; } - | maybe_attribute ATTRIBUTE '(' '(' attribute_list ')' ')' - { $$ = chainon ($5, $1); } - ; - -attribute_list - : attrib - { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); } - | attribute_list ',' attrib - { $$ = tree_cons (NULL_TREE, $3, $1); } - ; - -attrib - : identifier - { if (strcmp (IDENTIFIER_POINTER ($1), "packed") - && strcmp (IDENTIFIER_POINTER ($1), "noreturn")) - warning ("`%s' attribute directive ignored", - IDENTIFIER_POINTER ($1)); - $$ = $1; } - | TYPE_QUAL - | identifier '(' expr_no_commas ')' - { /* If not aligned(n), section(name), or mode(name), - then issue warning */ - if (strcmp (IDENTIFIER_POINTER ($1), "section") == 0 - || strcmp (IDENTIFIER_POINTER ($1), "mode") == 0) - { - if (TREE_CODE ($3) != STRING_CST) - { - error ("invalid argument in `%s' attribute", - IDENTIFIER_POINTER ($1)); - $$ = $1; - } - $$ = tree_cons ($1, $3, NULL_TREE); - } - else if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0) - { - warning ("`%s' attribute directive ignored", - IDENTIFIER_POINTER ($1)); - $$ = $1; - } - else - $$ = tree_cons ($1, $3, NULL_TREE); } - | identifier '(' IDENTIFIER ',' expr_no_commas ',' expr_no_commas ')' - { /* if not "format(...)", then issue warning */ - if (strcmp (IDENTIFIER_POINTER ($1), "format") != 0) - { - warning ("`%s' attribute directive ignored", - IDENTIFIER_POINTER ($1)); - $$ = $1; - } - else - $$ = tree_cons ($1, - tree_cons ($3, - tree_cons ($5, $7, NULL_TREE), - NULL_TREE), - NULL_TREE); } - ; + { $$ = NULL_TREE; } + | any_word + { $$ = $1; } + | any_word '(' IDENTIFIER ')' + { $$ = tree_cons ($1, NULL_TREE, build_tree_list (NULL_TREE, $3)); } + | any_word '(' IDENTIFIER ',' nonnull_exprlist ')' + { $$ = tree_cons ($1, NULL_TREE, tree_cons (NULL_TREE, $3, $5)); } + | any_word '(' nonnull_exprlist ')' + { $$ = tree_cons ($1, NULL_TREE, $3); } + ; + +/* This still leaves out most reserved keywords, + shouldn't we include them? */ + +any_word: + identifier + | SCSPEC + | TYPESPEC + | TYPE_QUAL + ; /* A nonempty list of identifiers, including typenames. */ identifiers_or_typenames: @@ -2663,7 +2650,7 @@ new_type_id: non-constant dimension. */ | '(' type_id ')' '[' expr ']' { - if (pedantic || flag_ansi) + if (flag_ansi) pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new"); $$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5); $$ = build_decl_list (TREE_PURPOSE ($2), $$); @@ -3003,7 +2990,7 @@ errstmt: error ';' maybe_label_decls: /* empty */ | label_decls - { if (pedantic) + { if (flag_ansi) pedwarn ("ANSI C++ forbids label declarations"); } ; @@ -3040,6 +3027,10 @@ compstmt: '{' .pushlevel '}' { expand_end_bindings (getdecls (), kept_level_p(), 1); $$ = poplevel (kept_level_p (), 1, 0); pop_momentary (); } + | '{' .pushlevel maybe_label_decls stmts error '}' + { expand_end_bindings (getdecls (), kept_level_p(), 1); + $$ = poplevel (kept_level_p (), 0, 0); + pop_momentary (); } | '{' .pushlevel maybe_label_decls error '}' { expand_end_bindings (getdecls (), kept_level_p(), 1); $$ = poplevel (kept_level_p (), 0, 0); @@ -3051,7 +3042,7 @@ simple_if: { cond_stmt_keyword = "if"; } .pushlevel paren_cond_or_null { emit_line_note (input_filename, lineno); - expand_start_cond (truthvalue_conversion ($4), 0); } + expand_start_cond (bool_truthvalue_conversion ($4), 0); } implicitly_scoped_stmt ; @@ -3059,7 +3050,7 @@ implicitly_scoped_stmt: compstmt { finish_stmt (); } | .pushlevel simple_stmt - { expand_end_bindings (getdecls (), getdecls() != NULL_TREE, 1); + { expand_end_bindings (getdecls (), kept_level_p (), 1); $$ = poplevel (kept_level_p (), 1, 0); pop_momentary (); } ; @@ -3106,7 +3097,7 @@ simple_stmt: expand_start_loop (1); cond_stmt_keyword = "while"; } .pushlevel paren_cond_or_null - { expand_exit_loop_if_false (0, truthvalue_conversion ($4)); } + { expand_exit_loop_if_false (0, bool_truthvalue_conversion ($4)); } already_scoped_stmt { expand_end_bindings (getdecls (), kept_level_p (), 1); poplevel (kept_level_p (), 1, 0); @@ -3122,7 +3113,7 @@ simple_stmt: cond_stmt_keyword = "do"; } paren_expr_or_null ';' { emit_line_note (input_filename, lineno); - expand_exit_loop_if_false (0, truthvalue_conversion ($6)); + expand_exit_loop_if_false (0, bool_truthvalue_conversion ($6)); expand_end_loop (); clear_momentary (); finish_stmt (); } @@ -3133,7 +3124,7 @@ simple_stmt: expand_start_loop_continue_elsewhere (1); } .pushlevel xcond ';' { emit_line_note (input_filename, lineno); - if ($4) expand_exit_loop_if_false (0, truthvalue_conversion ($4)); } + if ($4) expand_exit_loop_if_false (0, bool_truthvalue_conversion ($4)); } xexpr ')' /* Don't let the tree nodes for $7 be discarded by clear_momentary during the parsing of the next stmt. */ @@ -3154,7 +3145,7 @@ simple_stmt: expand_start_loop_continue_elsewhere (1); } .pushlevel xcond ';' { emit_line_note (input_filename, lineno); - if ($4) expand_exit_loop_if_false (0, truthvalue_conversion ($4)); } + if ($4) expand_exit_loop_if_false (0, bool_truthvalue_conversion ($4)); } xexpr ')' /* Don't let the tree nodes for $7 be discarded by clear_momentary during the parsing of the next stmt. */ @@ -3185,36 +3176,10 @@ simple_stmt: pop_momentary (); finish_stmt (); } | CASE expr_no_commas ':' - { register tree value = $2; + { register tree value = check_cp_case_value ($2); register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value) == NOP_EXPR - && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) - value = TREE_OPERAND (value, 0); - - if (TREE_READONLY_DECL_P (value)) - { - value = decl_constant_value (value); - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value) == NOP_EXPR - && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0))) - value = TREE_OPERAND (value, 0); - } - value = fold (value); - - if (TREE_CODE (value) != INTEGER_CST - && value != error_mark_node) - { - cp_error ("case label `%E' does not reduce to an integer constant", $2); - value = error_mark_node; - } - else - /* Promote char or short to int. */ - value = default_conversion (value); if (value != error_mark_node) { tree duplicate; @@ -3236,61 +3201,13 @@ simple_stmt: } stmt | CASE expr_no_commas RANGE expr_no_commas ':' - { register tree value1 = $2; - register tree value2 = $4; + { register tree value1 = check_cp_case_value ($2); + register tree value2 = check_cp_case_value ($4); register tree label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - if (pedantic) + if (flag_ansi) pedwarn ("ANSI C++ forbids range expressions in switch statement"); - - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value1) == NOP_EXPR - && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0))) - value1 = TREE_OPERAND (value1, 0); - - if (TREE_READONLY_DECL_P (value1)) - { - value1 = decl_constant_value (value1); - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value1) == NOP_EXPR - && TREE_TYPE (value1) == TREE_TYPE (TREE_OPERAND (value1, 0))) - value1 = TREE_OPERAND (value1, 0); - } - value1 = fold (value1); - - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value2) == NOP_EXPR - && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0))) - value2 = TREE_OPERAND (value2, 0); - - if (TREE_READONLY_DECL_P (value2)) - { - value2 = decl_constant_value (value2); - /* build_c_cast puts on a NOP_EXPR to make a non-lvalue. - Strip such NOP_EXPRs. */ - if (TREE_CODE (value2) == NOP_EXPR - && TREE_TYPE (value2) == TREE_TYPE (TREE_OPERAND (value2, 0))) - value2 = TREE_OPERAND (value2, 0); - } - value2 = fold (value2); - - - if (TREE_CODE (value1) != INTEGER_CST - && value1 != error_mark_node) - { - error ("case label does not reduce to an integer constant"); - value1 = error_mark_node; - } - if (TREE_CODE (value2) != INTEGER_CST - && value2 != error_mark_node) - { - error ("case label does not reduce to an integer constant"); - value2 = error_mark_node; - } if (value1 != error_mark_node && value2 != error_mark_node) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 528bbdd34dc..997941c5a02 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -782,6 +782,7 @@ uses_template_parms (t) case REAL_TYPE: case VOID_TYPE: case ENUMERAL_TYPE: + case BOOLEAN_TYPE: return 0; /* constants */ @@ -1142,6 +1143,7 @@ tsubst (t, args, nargs, in_decl) case VOID_TYPE: case REAL_TYPE: case ENUMERAL_TYPE: + case BOOLEAN_TYPE: case INTEGER_CST: case REAL_CST: case STRING_CST: @@ -1351,6 +1353,11 @@ tsubst (t, args, nargs, in_decl) DECL_CONTEXT (t) != NULL_TREE); r = build_lang_decl (FUNCTION_DECL, r, type); } + else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r)) + { + /* This overrides the template version, use it. */ + return r; + } } } TREE_PUBLIC (r) = TREE_PUBLIC (t); @@ -1638,8 +1645,10 @@ instantiate_template (tmpl, targ_ptr) DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); } + /* If we have a preexisting version of this function, don't expand + the template version, use the other instead. */ t = DECL_TEMPLATE_INFO (tmpl); - if (t->text) + if (t->text && !(DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))) { p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p->parm_vec = t->parm_vec; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c81f1e1488d..ea7de8f9f6f 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2426,7 +2426,7 @@ dfs_init_vbase_pointers (binfo) this_vbase_ptr = vbase_decl_ptr_intermediate; - if (TYPE_POINTER_TO (type) != TREE_TYPE (this_vbase_ptr)) + if (TYPE_POINTER_TO (type) != TYPE_MAIN_VARIANT (TREE_TYPE (this_vbase_ptr))) my_friendly_abort (125); while (fields && DECL_NAME (fields) @@ -2525,9 +2525,30 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets) if (use_computed_offsets) addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases)); else - addr = convert_pointer_to_real (vbases, vbase_decl_ptr); - if (addr == error_mark_node) - continue; + { + tree vbinfo = get_binfo (TREE_TYPE (vbases), + TREE_TYPE (vbase_decl), + 0); + + /* See is we can get lucky. */ + if (TREE_VIA_VIRTUAL (vbinfo)) + addr = convert_pointer_to_real (vbinfo, vbase_decl_ptr); + else + { + /* We go through all these contortions to avoid this + call, as it will fail when the virtual base type + is ambiguous from here. We don't yet have a way + to search for and find just an instance of the + virtual base class. Searching for the binfo in + vbases won't work, as we don't have the vbase + pointer field, for all vbases in the main class, + only direct vbases. */ + addr = convert_pointer_to_real (TREE_TYPE (vbases), + vbase_decl_ptr); + if (addr == error_mark_node) + continue; + } + } /* Do all vtables from this virtual base. */ /* This assumes that virtual bases can never serve as parent @@ -2877,12 +2898,16 @@ dfs_pushdecls (binfo) { /* Only complain if we shadow something we can access. */ if (old + && warn_shadow && ((DECL_LANG_SPECIFIC (old) && DECL_CLASS_CONTEXT (old) == current_class_type) || ! TREE_PRIVATE (old))) /* Should figure out access control more accurately. */ - cp_warning ("shadowing member `%#D' with member function `%#D'", - old, *methods); + { + cp_warning_at ("member `%#D' is shadowed", old); + cp_warning_at ("by member function `%#D'", *methods); + warning ("in this context"); + } tmp = build_tree_list (DECL_NAME (*methods), *methods); } pop_obstacks (); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index d8df8e48df8..b4712a6ac4d 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -94,6 +94,9 @@ lvalue_p (ref) return (lvalue_p (TREE_OPERAND (ref, 1)) && lvalue_p (TREE_OPERAND (ref, 2))); + case MODIFY_EXPR: + return 1; + case COMPOUND_EXPR: return lvalue_p (TREE_OPERAND (ref, 1)); } @@ -111,7 +114,7 @@ lvalue_or_else (ref, string) { int win = lvalue_p (ref); if (! win) - error ("invalid lvalue in %s", string); + error ("non-lvalue in %s", string); return win; } @@ -305,13 +308,7 @@ build_cplus_method_type (basetype, rettype, argtypes) else { ptype = build_pointer_type (basetype); -#if 0 - /* it is wrong to flag the object the pointer points to as readonly - when flag_this_is_variable is 0. */ - ptype = build_type_variant (ptype, flag_this_is_variable <= 0, 0); -#else - ptype = build_type_variant (ptype, 0, 0); -#endif + ptype = build_type_variant (ptype, 1, 0); } /* The actual arglist for this function includes a "hidden" argument which is "this". Put it into the list of argument types. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 490d9988f07..f2b375bf40f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -47,7 +47,6 @@ static tree pointer_int_sum (); static tree pointer_diff (); static tree convert_sequence (); /* static */ tree unary_complex_lvalue (); -tree truthvalue_conversion (); extern rtx original_result_rtx; @@ -258,6 +257,7 @@ common_type (t1, t2) { register enum tree_code code1; register enum tree_code code2; + tree attributes; /* Save time if the two types are the same. */ @@ -269,6 +269,40 @@ common_type (t1, t2) if (t2 == error_mark_node) return t1; + /* Merge the attributes */ + + { register tree a1, a2; + a1 = TYPE_ATTRIBUTES (t1); + a2 = TYPE_ATTRIBUTES (t2); + + /* Either one unset? Take the set one. */ + + if (!(attributes = a1)) + attributes = a2; + + /* One that completely contains the other? Take it. */ + + else if (a2 && !attribute_list_contained (a1, a2)) + if (attribute_list_contained (a2, a1)) + attributes = a2; + else + { + /* Pick the longest list, and hang on the other + list. */ + + if (list_length (a1) < list_length (a2)) + attributes = a2, a2 = a1; + + for (; a2; a2 = TREE_CHAIN (a2)) + if (!value_member (attributes, a2)) + { + a1 = copy_node (a2); + TREE_CHAIN (a1) = attributes; + attributes = a1; + } + } + } + /* Treat an enum type as the unsigned integer type of the same width. */ if (TREE_CODE (t1) == ENUMERAL_TYPE) @@ -286,23 +320,24 @@ common_type (t1, t2) /* If only one is real, use it as the result. */ if (code1 == REAL_TYPE && code2 != REAL_TYPE) - return t1; + return build_type_attribute_variant (t1, attributes); if (code2 == REAL_TYPE && code1 != REAL_TYPE) - return t2; + return build_type_attribute_variant (t2, attributes); /* Both real or both integers; use the one with greater precision. */ if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) - return t1; + return build_type_attribute_variant (t1, attributes); else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1)) - return t2; + return build_type_attribute_variant (t2, attributes); /* Same precision. Prefer longs to ints even when same size. */ - + if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node) - return long_unsigned_type_node; + return build_type_attribute_variant (long_unsigned_type_node, + attributes); if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node || TYPE_MAIN_VARIANT (t2) == long_integer_type_node) @@ -310,15 +345,18 @@ common_type (t1, t2) /* But preserve unsignedness from the other type, since long cannot hold all the values of an unsigned int. */ if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2)) - return long_unsigned_type_node; - return long_integer_type_node; + t1 = long_unsigned_type_node; + else + t1 = long_integer_type_node; + return build_type_attribute_variant (t1, attributes); } /* Otherwise prefer the unsigned one. */ if (TREE_UNSIGNED (t1)) - return t1; - else return t2; + return build_type_attribute_variant (t1, attributes); + else + return build_type_attribute_variant (t2, attributes); case POINTER_TYPE: case REFERENCE_TYPE: @@ -336,16 +374,19 @@ common_type (t1, t2) = TYPE_VOLATILE (TREE_TYPE (t1)) || TYPE_VOLATILE (TREE_TYPE (t2)); target = build_type_variant (target, constp, volatilep); if (code1 == POINTER_TYPE) - return build_pointer_type (target); + t1 = build_pointer_type (target); else - return build_reference_type (target); + t1 = build_reference_type (target); + return build_type_attribute_variant (t1, attributes); } #if 0 case POINTER_TYPE: - return build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); + t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); + return build_type_attribute_variant (t1, attributes); case REFERENCE_TYPE: - return build_reference_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); + t1 = build_reference_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2))); + return build_type_attribute_variant (t1, attributes); #endif case ARRAY_TYPE: @@ -353,11 +394,12 @@ common_type (t1, t2) tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)) - return t1; + return build_type_attribute_variant (t1, attributes); if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) - return t2; + return build_type_attribute_variant (t2, attributes); /* Merge the element types, and have a size if either arg has one. */ - return build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + return build_type_attribute_variant (t1, attributes); } case FUNCTION_TYPE: @@ -371,9 +413,9 @@ common_type (t1, t2) /* Save space: see if the result is identical to one of the args. */ if (valtype == TREE_TYPE (t1) && ! p2) - return t1; + return build_type_attribute_variant (t1, attributes); if (valtype == TREE_TYPE (t2) && ! p1) - return t2; + return build_type_attribute_variant (t2, attributes); /* Simple way if one arg fails to specify argument types. */ if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node) @@ -381,7 +423,7 @@ common_type (t1, t2) rval = build_function_type (valtype, p2); if ((raises = TYPE_RAISES_EXCEPTIONS (t2))) rval = build_exception_variant (NULL_TREE, rval, raises); - return rval; + return build_type_attribute_variant (rval, attributes); } raises = TYPE_RAISES_EXCEPTIONS (t1); if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node) @@ -389,11 +431,12 @@ common_type (t1, t2) rval = build_function_type (valtype, p1); if (raises) rval = build_exception_variant (NULL_TREE, rval, raises); - return rval; + return build_type_attribute_variant (rval, attributes); } rval = build_function_type (valtype, commonparms (p1, p2)); - return build_exception_variant (NULL_TREE, rval, raises); + rval = build_exception_variant (NULL_TREE, rval, raises); + return build_type_attribute_variant (rval, attributes); } case RECORD_TYPE: @@ -401,10 +444,9 @@ common_type (t1, t2) my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1 && TYPE_MAIN_VARIANT (t2) == t2, 306); - if (binfo_or_else (t1, t2)) - return t1; - compiler_error ("common_type called with uncommon aggregate types"); - return t1; + if (! binfo_or_else (t1, t2)) + compiler_error ("common_type called with uncommon aggregate types"); + return build_type_attribute_variant (t1, attributes); case METHOD_TYPE: if (comptypes (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), 1) @@ -424,24 +466,28 @@ common_type (t1, t2) t2 = build_function_type (TREE_TYPE (t2), TREE_CHAIN (TYPE_ARG_TYPES (t2))); t3 = common_type (t1, t2); t3 = build_cplus_method_type (basetype, TREE_TYPE (t3), TYPE_ARG_TYPES (t3)); - return build_exception_variant (basetype, t3, raises); + t1 = build_exception_variant (basetype, t3, raises); } - compiler_error ("common_type called with uncommon method types"); - return t1; + else + compiler_error ("common_type called with uncommon method types"); + + return build_type_attribute_variant (t1, attributes); case OFFSET_TYPE: if (TYPE_OFFSET_BASETYPE (t1) == TYPE_OFFSET_BASETYPE (t2) && TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) { tree basetype = TYPE_OFFSET_BASETYPE (t1); - return build_offset_type (basetype, + t1 = build_offset_type (basetype, common_type (TREE_TYPE (t1), TREE_TYPE (t2))); } - compiler_error ("common_type called with uncommon member types"); - return t1; + else + compiler_error ("common_type called with uncommon member types"); + + /* ... falls through ... */ default: - return t1; + return build_type_attribute_variant (t1, attributes); } } @@ -514,6 +560,7 @@ comptypes (type1, type2, strict) { register tree t1 = type1; register tree t2 = type2; + int attrval, val; /* Suppress errors caused by previously reported errors */ @@ -571,20 +618,30 @@ comptypes (type1, type2, strict) if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; +#ifdef COMP_TYPE_ATTRIBUTES + if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2))) + return 0; +#else + /* 1 if no need for warning yet, 2 if warning cause has been seen. */ + attrval = 1; +#endif + + /* 1 if no need for warning yet, 2 if warning cause has been seen. */ + val = 0; + switch (TREE_CODE (t1)) { case RECORD_TYPE: case UNION_TYPE: - if (t1 == t2) - return 1; if (strict <= 0) goto look_hard; return 0; case OFFSET_TYPE: - return (comptypes (TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t1)), + val = (comptypes (TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t1)), TYPE_POINTER_TO (TYPE_OFFSET_BASETYPE (t2)), strict) && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)); + break; case METHOD_TYPE: if (! compexcepttypes (t1, t2, strict)) @@ -595,17 +652,22 @@ comptypes (type1, type2, strict) to something expecting a derived member (or member function), but not vice-versa! */ - return (comptypes (TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t2)), + val = (comptypes (TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t2)), TYPE_POINTER_TO (TYPE_METHOD_BASETYPE (t1)), strict) && comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict) && compparms (TREE_CHAIN (TYPE_ARG_TYPES (t1)), TREE_CHAIN (TYPE_ARG_TYPES (t2)), strict)); + break; + case POINTER_TYPE: case REFERENCE_TYPE: t1 = TREE_TYPE (t1); t2 = TREE_TYPE (t2); if (t1 == t2) - return 1; + { + val = 1; + break; + } if (strict <= 0) { if (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE) @@ -615,26 +677,35 @@ comptypes (type1, type2, strict) rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2); if (rval) - return 1; + { + val = 1; + break; + } if (strict < 0) - return UNIQUELY_DERIVED_FROM_P (t2, t1); + { + val = UNIQUELY_DERIVED_FROM_P (t2, t1); + break; + } } return 0; } else - return comptypes (t1, t2, strict); + val = comptypes (t1, t2, strict); + break; case FUNCTION_TYPE: if (! compexcepttypes (t1, t2, strict)) return 0; - return ((TREE_TYPE (t1) == TREE_TYPE (t2) - || comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)) - && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict)); + val = ((TREE_TYPE (t1) == TREE_TYPE (t2) + || comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict)) + && compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict)); + break; case ARRAY_TYPE: /* Target types must match incl. qualifiers. */ - return comp_array_types (comptypes, t1, t2, strict); + val = comp_array_types (comptypes, t1, t2, strict); + break; case TEMPLATE_TYPE_PARM: return 1; @@ -642,7 +713,7 @@ comptypes (type1, type2, strict) case UNINSTANTIATED_P_TYPE: return UPT_TEMPLATE (t1) == UPT_TEMPLATE (t2); } - return 0; + return attrval == 2 && val == 1 ? 2 : val; } /* Return 1 if TTL and TTR are pointers to types that are equivalent, @@ -683,7 +754,8 @@ comp_target_types (ttl, ttr, nptrs) case 1: return 1; case 2: - warning ("contravariance violation for method types ignored"); + cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", + ttr, ttl); return 1; default: my_friendly_abort (112); @@ -702,7 +774,8 @@ comp_target_types (ttl, ttr, nptrs) else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0) && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs)) { - warning ("contravariance violation for member types ignored"); + cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", + ttr, ttl); return 1; } } @@ -1224,7 +1297,7 @@ default_conversion (exp) /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */ - if (code == ENUMERAL_TYPE || code == INTEGER_TYPE) + if (INTEGRAL_CODE_P (code)) { tree t = type_promotes_to (type); if (t != TYPE_MAIN_VARIANT (type)) @@ -2656,14 +2729,21 @@ build_binary_op (code, arg1, arg2, convert_p) tree types[2], try; types[0] = type1; types[1] = type2; - try = build_type_conversion (code, types[convert_index ^ 1], - args[convert_index], 1); - - if (try == 0 - && args[1] == integer_zero_node - && (code == NE_EXPR || code == EQ_EXPR)) - try = build_type_conversion (code, ptr_type_node, + if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) + try = build_type_conversion (code, bool_type_node, args[convert_index], 1); + else + { + try = build_type_conversion (code, types[convert_index ^ 1], + args[convert_index], 1); + + if (try == 0 + && args[1] == integer_zero_node + && (code == NE_EXPR || code == EQ_EXPR)) + try = build_type_conversion (code, ptr_type_node, + args[convert_index], 1); + } + if (try == 0) { cp_error ("no match for `%O(%#T, %#T)'", code, @@ -2875,17 +2955,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case TRUTH_ORIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: - if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE || code1 == REAL_TYPE)) - { - /* Result of these operations is always an int, - but that does not mean the operands should be - converted to ints! */ - result_type = integer_type_node; - op0 = truthvalue_conversion (op0); - op1 = truthvalue_conversion (op1); - converted = 1; - } + result_type = bool_type_node; + op0 = bool_truthvalue_conversion (op0); + op1 = bool_truthvalue_conversion (op1); + converted = 1; break; /* Shift operations: result has same type as first operand; @@ -2966,9 +3039,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case EQ_EXPR: case NE_EXPR: - /* Result of comparison is always int, - but don't convert the args to int! */ - result_type = integer_type_node; + result_type = bool_type_node; converted = 1; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) @@ -2984,10 +3055,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) { tree base = common_base_type (tt0, tt1); if (base == NULL_TREE) - warning ("comparison of distinct object pointer types"); + cp_warning ("comparison of distinct object pointer types `%T' and `%T'", type0, type1); else if (base == error_mark_node) { - message_2_types (error, "comparison of pointer types `%s*' and `%s*' requires conversion to ambiguous supertype", tt0, tt1); + cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1); return error_mark_node; } else @@ -3017,9 +3088,13 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer"); } else if ((TYPE_SIZE (tt0) != 0) != (TYPE_SIZE (tt1) != 0)) - pedwarn ("comparison of complete and incomplete pointers"); + cp_pedwarn ("comparison of %scomplete and %scomplete pointers `%T' and `%T'", + TYPE_SIZE (tt0) == 0 ? "in" : "", + TYPE_SIZE (tt1) == 0 ? "in" : "", + type0, type1); else - pedwarn ("comparison of distinct pointer types lacks a cast"); + cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", + type0, type1); } else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) @@ -3137,10 +3212,14 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { if (! comp_target_types (type0, type1, 1)) - pedwarn ("comparison of distinct pointer types lacks a cast"); + cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", + type0, type1); else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) - pedwarn ("comparison of complete and incomplete pointers"); + cp_pedwarn ("comparison of %scomplete and %scomplete pointers", + TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "", + TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "", + type0, type1); else if (pedantic && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); @@ -3158,19 +3237,21 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { if (! comp_target_types (type0, type1, 1)) - pedwarn ("comparison of distinct pointer types lacks a cast"); + cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast", + type0, type1); else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0) != (TYPE_SIZE (TREE_TYPE (type1)) != 0)) - pedwarn ("comparison of complete and incomplete pointers"); + cp_pedwarn ("comparison of %scomplete and %scomplete pointers", + TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "", + TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "", + type0, type1); else if (pedantic && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE) pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions"); - result_type = integer_type_node; } else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) { - result_type = integer_type_node; op1 = null_pointer_node; if (pedantic) pedwarn ("ordered comparison of pointer with integer zero"); @@ -3178,14 +3259,12 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST && integer_zerop (op0)) { - result_type = integer_type_node; op0 = null_pointer_node; if (pedantic) pedwarn ("ANSI C++ forbids ordered comparison of pointer with integer zero"); } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { - result_type = integer_type_node; if (pedantic) pedwarn ("ANSI C++ forbids comparison between pointer and integer"); else if (! flag_traditional) @@ -3194,13 +3273,13 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { - result_type = integer_type_node; if (pedantic) pedwarn ("ANSI C++ forbids comparison between pointer and integer"); else if (! flag_traditional) warning ("comparison between pointer and integer"); op0 = convert (TREE_TYPE (op1), op0); } + result_type = bool_type_node; converted = 1; break; } @@ -3332,8 +3411,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return val; - op0 = xop0, op1 = xop1, result_type = xresult_type; + return convert (bool_type_node, val); + op0 = xop0, op1 = xop1, result_type = bool_type_node; resultcode = xresultcode; } @@ -3659,6 +3738,17 @@ build_x_unary_op (code, xarg) return build_unary_op (code, xarg, 0); } +/* Just like truthvalue_conversion, but we want a BOOLEAN_TYPE */ +tree +bool_truthvalue_conversion (expr) + tree expr; +{ + /* We really want to preform the optimizations in truthvalue_conversion + but, not this way. */ + /* expr = truthvalue_conversion (expr); */ + return convert (bool_type_node, expr); +} + /* C++: Must handle pointers to members. Perhaps type instantiation should be extended to handle conversion @@ -3771,23 +3861,11 @@ build_unary_op (code, xarg, noconvert) break; case TRUTH_NOT_EXPR: - if (isaggrtype) - { - arg = truthvalue_conversion (arg); - typecode = TREE_CODE (TREE_TYPE (arg)); - } - - if (typecode != INTEGER_TYPE - && typecode != REAL_TYPE && typecode != POINTER_TYPE - /* These will convert to a pointer. */ - && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE) - { - errstring = "wrong type argument to unary exclamation mark"; - break; - } - arg = truthvalue_conversion (arg); + arg = bool_truthvalue_conversion (arg); val = invert_truthvalue (arg); - if (val) return val; + if (arg != error_mark_node) + return val; + errstring = "in argument to unary !"; break; case NOP_EXPR: @@ -4426,7 +4504,7 @@ build_conditional_expr (ifexp, op1, op2) ifexp = op1 = save_expr (ifexp); } - ifexp = truthvalue_conversion (default_conversion (ifexp)); + ifexp = bool_truthvalue_conversion (default_conversion (ifexp)); if (TREE_CODE (ifexp) == ERROR_MARK) return error_mark_node; @@ -4841,21 +4919,7 @@ build_c_cast (type, expr) if (TREE_TYPE (value) && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (value))) - { - /* For C++, we must copy the constness of TYPE into VALUE. */ - if (TREE_READONLY (value) != TYPE_READONLY (type)) - { - value = copy_node (value); - TREE_READONLY (value) = TYPE_READONLY (type); - } - else if (pedantic) - { - if (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - pedwarn ("ANSI C++ forbids casting nonscalar to the same type"); - } - return value; - } + return build1 (NOP_EXPR, type, value); /* If there's only one function in the overloaded space, just take it. */ @@ -5262,12 +5326,6 @@ build_modify_expr (lhs, modifycode, rhs) if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; - /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. - Strip such NOP_EXPRs, since RHS is being used in non-lvalue context. */ - if (TREE_CODE (rhs) == NOP_EXPR - && TREE_TYPE (rhs) == TREE_TYPE (TREE_OPERAND (rhs, 0))) - rhs = TREE_OPERAND (rhs, 0); - /* Decide early if we are going to protect RHS from GC before assigning it to LHS. */ if (type_needs_gc_entry (TREE_TYPE (rhs)) @@ -5432,6 +5490,7 @@ build_modify_expr (lhs, modifycode, rhs) newrhs = build_binary_op (modifycode, lhs, rhs, 1); } +#if 0 /* Handle a cast used as an "lvalue". We have already performed any binary operator using the value as cast. Now convert the result to the cast type of the lhs, @@ -5464,6 +5523,7 @@ build_modify_expr (lhs, modifycode, rhs) return convert_force (TREE_TYPE (lhs), result); } } +#endif if (TREE_CODE (lhs) == OFFSET_REF) { @@ -5521,16 +5581,10 @@ build_modify_expr (lhs, modifycode, rhs) /* check to see if there is an assignment to `this' */ if (lhs == current_class_decl) { - if (DECL_NAME (current_function_decl) != NULL_TREE) - { - /* ARM 18.3.3 and draft standard section C.11 say that assigning - something to this is an anachronism. */ - if (pedantic) - warning ("anachronistic assignment to `this' pointer"); - else if (flag_this_is_variable > 0 - && current_class_name != DECL_NAME (current_function_decl)) - warning ("assignment to `this' not in constructor or destructor"); - } + if (flag_this_is_variable > 0 + && DECL_NAME (current_function_decl) != NULL_TREE + && current_class_name != DECL_NAME (current_function_decl)) + warning ("assignment to `this' not in constructor or destructor"); current_function_just_assigned_this = 1; } @@ -6151,8 +6205,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return error_mark_node; } /* Arithmetic types all interconvert. */ - if ((codel == INTEGER_TYPE || codel == REAL_TYPE) - && (coder == INTEGER_TYPE || coder == REAL_TYPE)) + if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE) + && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE)) { /* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */ if (coder == REAL_TYPE && codel == INTEGER_TYPE) @@ -6165,7 +6219,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } /* And we should warn if assigning a negative value to an unsigned variable. */ - else if (TREE_UNSIGNED (type)) + else if (TREE_UNSIGNED (type) && codel != BOOLEAN_TYPE) { if (TREE_CODE (rhs) == INTEGER_CST && TREE_NEGATED_INT (rhs)) @@ -6268,12 +6322,14 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) 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)); - else - pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s", - errtype); + { + if (coder == RECORD_TYPE) + pedwarn ("implicit conversion of signature pointer to type `%s'", + type_as_string (type, 0)); + else + pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s", + errtype); + } /* Const and volatile mean something different for function types, so the usual warnings are not appropriate. */ else if ((TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE) @@ -6286,7 +6342,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) sorry ("%s between pointer to members converting across virtual baseclasses", errtype); return error_mark_node; } - if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) + else if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) { if (fndecl) cp_pedwarn ("passing `%T' as argument %P of `%D' discards const", @@ -6295,7 +6351,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) cp_pedwarn ("%s to `%T' from `%T' discards const", errtype, type, rhstype); } - if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) + else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) { if (fndecl) cp_pedwarn ("passing `%T' as argument %P of `%D' discards volatile", @@ -6304,6 +6360,16 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) cp_pedwarn ("%s to `%T' from `%T' discards volatile", errtype, type, rhstype); } + else if (TREE_CODE (ttl) == TREE_CODE (ttr) + && ! comp_target_types (type, rhstype, 1)) + { + if (fndecl) + cp_pedwarn ("passing `%T' as argument %P of `%D' changes signedness", + rhstype, parmnum, fndecl); + else + cp_pedwarn ("%s to `%T' from `%T' changes signedness", + errtype, type, rhstype); + } } } else if (TREE_CODE (ttr) == OFFSET_TYPE @@ -6570,8 +6636,24 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) return here before checking if RHS is of complete type. */ if (codel == REFERENCE_TYPE) - return convert_to_reference (type, rhs, CONV_IMPLICIT, flags, - exp ? exp : error_mark_node); + { + /* This should eventually happen in convert_arguments. */ + extern int warningcount, errorcount; + int savew, savee; + + if (fndecl) + savew = warningcount, savee = errorcount; + rhs = convert_to_reference (type, rhs, CONV_IMPLICIT, flags, + exp ? exp : error_mark_node); + if (fndecl) + { + if (warningcount > savew) + cp_warning_at ("in passing argument %P of `%+D'", parmnum, fndecl); + else if (errorcount > savee) + cp_error_at ("in passing argument %P of `%+D'", parmnum, fndecl); + } + return rhs; + } rhs = require_complete_type (rhs); if (rhs == error_mark_node) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 858896a4f11..baf55a41b9f 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -766,6 +766,7 @@ digest_init (type, init, tail) if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE || code == ENUMERAL_TYPE || code == REFERENCE_TYPE + || code == BOOLEAN_TYPE || (code == RECORD_TYPE && ! raw_constructor && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))) { @@ -951,13 +952,7 @@ process_init_constructor (type, init, elts) continue; } - if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL) - continue; - - /* A static member isn't considered "part of the object", so - it has no business even thinking about involving itself in - what an initializer-list is trying to do. */ - if (TREE_CODE (field) == VAR_DECL && TREE_STATIC (field)) + if (TREE_CODE (field) != FIELD_DECL) continue; if (TREE_VALUE (tail) != 0) @@ -1462,16 +1457,18 @@ build_functional_cast (exp, parms) } { - int flags = LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN; + int flags = LOOKUP_SPECULATIVELY|LOOKUP_NORMAL; if (parms && TREE_CHAIN (parms) == NULL_TREE) flags |= LOOKUP_NO_CONVERSION; - try_again: expr_as_ctor = build_method_call (NULL_TREE, name, parms, NULL_TREE, flags); - if (expr_as_ctor && expr_as_ctor != error_mark_node) + if (expr_as_ctor == error_mark_node) + return error_mark_node; + + else if (expr_as_ctor) { if (expr_as_conversion && expr_as_conversion != error_mark_node) { @@ -1514,18 +1511,6 @@ build_functional_cast (exp, parms) return expr_as_ctor; } - /* If it didn't work going through constructor, try type conversion. */ - if (! (flags & LOOKUP_COMPLAIN)) - { - if (expr_as_conversion) - return expr_as_conversion; - if (flags & LOOKUP_NO_CONVERSION) - { - flags = LOOKUP_NORMAL; - goto try_again; - } - } - if (expr_as_conversion) return expr_as_conversion; |