/* * Copyright (c) 2002, The Tendra Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * Crown Copyright (c) 1997 * * This TenDRA(r) Computer Program is subject to Copyright * owned by the United Kingdom Secretary of State for Defence * acting through the Defence Evaluation and Research Agency * (DERA). It is made available to Recipients with a * royalty-free licence for its use, reproduction, transfer * to other parties and amendment for any purpose not excluding * product development provided that any such use et cetera * shall be deemed to be acceptance of the following conditions:- * * (1) Its Recipients shall ensure that this Notice is * reproduced upon any copies or amended versions of it; * * (2) Any amended version of it shall be clearly marked to * show both the nature of and the organisation responsible * for the relevant amendment or amendments; * * (3) Its onward transfer from a recipient to another * party shall be deemed to be that party's acceptance of * these conditions; * * (4) DERA gives no warranty or assurance as to its * quality or suitability for any purpose and DERA accepts * no liability whatsoever in relation to any use to which * it may be put. * * $TenDRA: tendra/src/producers/common/construct/convert.c,v 1.9 2004/08/14 15:15:35 bp Exp $ */ #include "config.h" #include "producer.h" #include "c_types.h" #include "ctype_ops.h" #include "etype_ops.h" #include "exp_ops.h" #include "ftype_ops.h" #include "graph_ops.h" #include "hashid_ops.h" #include "id_ops.h" #include "itype_ops.h" #include "nat_ops.h" #include "type_ops.h" #include "error.h" #include "catalog.h" #include "option.h" #include "basetype.h" #include "cast.h" #include "check.h" #include "chktype.h" #include "constant.h" #include "construct.h" #include "convert.h" #include "derive.h" #include "expression.h" #include "function.h" #include "identifier.h" #include "initialise.h" #include "instance.h" #include "inttype.h" #include "literal.h" #include "member.h" #include "namespace.h" #include "overload.h" #include "predict.h" #include "quality.h" #include "syntax.h" #include "template.h" #include "tokdef.h" #include "token.h" /* * FIND THE PROMOTION OF A TYPE * * This routine finds the promoted type for the type t. For integral * types the promoted type is calculated and stored when the type is * first constructed. Enumeration types and bitfield types are promoted * according to their underlying types. Other types (including floating * point types) are their own promotions. */ TYPE promote_type(TYPE t) { switch (TAG_type (t)) { case type_integer_tag : { /* Retrieve the promotion of an integral type */ INT_TYPE it = DEREF_itype (type_integer_rep (t)); t = DEREF_type (itype_prom (it)); break; } case type_enumerate_tag : { /* Find the underlying type of an enumeration */ ENUM_TYPE et = DEREF_etype (type_enumerate_defn (t)); t = DEREF_type (etype_rep (et)); t = promote_type (t); break; } case type_bitfield_tag : { /* Retrieve the promotion of a bitfield type */ INT_TYPE it = DEREF_itype (type_bitfield_defn (t)); t = DEREF_type (itype_prom (it)); break; } } return (t); } /* * FIND THE ARGUMENT PROMOTION OF A TYPE * * This routine finds the argument promotion type for the type t. This * is identical to the normal arithmetic promotion type for integral types, * but differs for floating point types (float promotes to double etc.). * Any errors are added to the end of err. */ TYPE arg_promote_type(TYPE t, ERROR *err) { switch (TAG_type (t)) { case type_integer_tag : case type_enumerate_tag : case type_bitfield_tag : { /* Promote integral types */ t = promote_type (t); break; } case type_floating_tag : { /* Retrieve the promotion of a floating point type */ FLOAT_TYPE ft = DEREF_ftype (type_floating_rep (t)); t = DEREF_type (ftype_arg_prom (ft)); break; } case type_top_tag : case type_bottom_tag : { /* Can't have 'void' arguments */ add_error (err, ERR_basic_fund_void_exp (t)); break; } case type_func_tag : { /* Apply function-to-pointer conversion */ MAKE_type_ptr (cv_none, t, t); break; } case type_array_tag : { /* Apply array-to-pointer conversion */ TYPE s = DEREF_type (type_array_sub (t)); MAKE_type_ptr (cv_none, s, t); break; } case type_compound_tag : { /* Types with constructors are suspicious */ if (pass_complex_type (t)) { add_error (err, ERR_expr_call_struct (t)); } break; } } return (t); } /* * IS A TYPE EQUAL TO ITS ARGUMENT PROMOTION TYPE? * * This routine checks whether the integral or floating point type t is * equal to its argument promotion type. */ int is_arg_promote(TYPE t) { int eq = 1; if (!IS_NULL_type (t)) { t = expand_type (t, 1); switch (TAG_type (t)) { case type_integer_tag : case type_floating_tag : { TYPE s = arg_promote_type (t, KILL_err); if (!EQ_type (s, t)) { int ft = force_tokdef; force_tokdef = 0; eq = eq_type_unqual (s, t); force_tokdef = ft; } break; } } } return (eq); } /* * FIND THE TYPE WHICH PROMOTES TO A GIVEN TYPE * * This routine is a partial inverse to arg_promote_type which finds a * type whose promotion is t. */ TYPE unpromote_type(TYPE t) { if (!IS_NULL_type (t)) { switch (TAG_type (t)) { case type_integer_tag : { INT_TYPE it = DEREF_itype (type_integer_rep (t)); INT_TYPE is = DEREF_itype (type_integer_sem (t)); if (!EQ_itype (is, it)) t = make_itype (is, is); break; } case type_floating_tag : { FLOAT_TYPE ft = DEREF_ftype (type_floating_rep (t)); FLOAT_TYPE fs = DEREF_ftype (type_floating_sem (t)); if (!EQ_ftype (fs, ft)) t = make_ftype (fs, fs); break; } } } return (t); } /* * FIND THE TYPE FOR AN ARITHMETIC OPERATION * * This routine performs finds the result type for an arithmetic operation * involving operands of types t and s. These will always be arithmetic * types. The operands a and b are passed in order to help determine the * semantic type of the result. */ TYPE arith_type(TYPE t, TYPE s, EXP a, EXP b) { TYPE r; if (EQ_type (t, s)) { /* Equal types, promote the result */ r = promote_type (t); } else { unsigned nt = TAG_type (t); unsigned ns = TAG_type (s); if (nt == type_floating_tag) { if (ns == type_floating_tag) { /* Two floating point types */ r = arith_ftype (t, s); } else { /* If there is one floating type, this is the result */ r = t; } } else { if (ns == type_floating_tag) { /* If there is one floating type, this is the result */ r = s; } else { /* Two integer types, promote them both */ TYPE pt = promote_type (t); TYPE ps = promote_type (s); if (EQ_type (pt, ps)) { r = pt; } else { r = arith_itype (pt, ps, a, b); } } } } return (r); } /* * QUALIFIER DEPTH * * The value qualifier depth is set by check_qualifier to the depth of * the deepest different cv-qualifier it encounters. The easy cases * are 0 (the types are identically qualified) and 1 (the conversion * is of the form 'cv1 T *' to 'cv2 T *'). The value qualifier_diff * gives the qualifiers added at this stage. */ int qualifier_depth = 0; static CV_SPEC qualifier_diff = cv_none; /* * CHECK QUALIFICATION CONVERSIONS * * This routine checks for qualification conversions from the pointer or * pointer to member type s to the pointer or pointer to member type t. * For the qualification conversion to be valid, the two types have to obey * four rules. They have to be similar (i.e. the same up to cv-qualifiers) * - this is assumed to be true if safe is true. Each target qualifier * must be more const-qualified and more volatile-qualified than the * corresponding source qualifier. Finally if two qualifiers differ * then all the previous target qualifiers must involve const. The C * rules are slightly different. Only one level of pointers is * considered and the types pointed to must be compatible. Note that * for pointer to member types it is not checked that the underlying * classes are the same at the top level. This is to allow base class * pointer to member conversion to be checked elsewhere. */ unsigned check_qualifier(TYPE t, TYPE s, int safe) { int j = 0; int all_const = 1; unsigned res = QUAL_EQUAL; t = expand_type (t, 1); s = expand_type (s, 1); qualifier_depth = 0; qualifier_diff = cv_none; while (!EQ_type (t, s)) { unsigned nt = TAG_type (t); unsigned ns = TAG_type (s); CV_SPEC qt = DEREF_cv (type_qual (t)); CV_SPEC qs = DEREF_cv (type_qual (s)); /* Check qualifiers */ if (j == 0) { /* Don't bother with top level qualifiers */ /* EMPTY */ } else { if (nt == type_array_tag) qt = find_cv_qual (t); if (ns == type_array_tag) qs = find_cv_qual (s); qt &= cv_qual; qs &= cv_qual; if (qt != qs) { CV_SPEC qr = (qs & ~qt); if (qr & cv_const) res &= ~QUAL_CONST; if (qr & cv_volatile) res &= ~QUAL_VOLATILE; res &= ~QUAL_EXACT; if (!all_const) { /* For inequality should have all consts in t */ res &= ~QUAL_ALL_CONST; } qualifier_depth = j; qualifier_diff = (qt & ~qs); } if (!(qt & cv_const)) all_const = 0; } /* Check next type */ switch (nt) { case type_ptr_tag : case type_ref_tag : { /* Pointer types */ if (ns != nt) goto error_lab; #if LANGUAGE_C if (j > 0) goto error_lab; #endif t = DEREF_type (type_ptr_etc_sub (t)); s = DEREF_type (type_ptr_etc_sub (s)); break; } #if LANGUAGE_CPP case type_ptr_mem_tag : { /* Pointer to member types */ CLASS_TYPE cs, ct; if (ns != nt) goto error_lab; ct = DEREF_ctype (type_ptr_mem_of (t)); cs = DEREF_ctype (type_ptr_mem_of (s)); if (j == 0) { /* Top level classes checked elsewhere */ /* EMPTY */ } else if (!eq_ctype (ct, cs)) { /* Must point to members of the same class */ if (in_template_decl) { /* Mark template parameter types */ TYPE ft = DEREF_type (ctype_form (ct)); TYPE fs = DEREF_type (ctype_form (cs)); if (is_templ_depend (ft)) res |= QUAL_TEMPL; if (is_templ_depend (fs)) res |= QUAL_TEMPL; } res &= ~(QUAL_EXACT | QUAL_SIMILAR); return (res); } t = DEREF_type (type_ptr_mem_sub (t)); s = DEREF_type (type_ptr_mem_sub (s)); break; } #endif case type_func_tag : { /* Function types */ int eq; if (ns != nt) goto error_lab; if (safe) { eq = 3; } else { eq = eq_func_type (t, s, 1, 0); if (eq < 2) goto error_lab; } if (res == QUAL_EQUAL) res |= QUAL_FUNC; if (eq != 3) { /* Linkage specifiers don't match */ res &= ~(QUAL_EXACT | QUAL_SIMILAR); } return (res); } case type_top_tag : case type_bottom_tag : case type_compound_tag : { /* Don't trust 'safe' in these cases */ if (ns == nt && eq_type_unqual (t, s)) return (res); goto error_lab; } default : { /* Check other types */ if (safe) return (res); if (ns == nt && eq_type_unqual (t, s)) return (res); goto error_lab; } error_lab : { /* Unequal types */ #if LANGUAGE_C TYPE r = type_composite (t, s, 1, 0, KILL_err, 0); if (!IS_NULL_type (r)) { if (IS_type_func (r)) { if (res == QUAL_EQUAL) res |= QUAL_FUNC; } return (res); } #endif if (in_template_decl) { /* Mark template parameter types */ if (is_templ_depend (t)) res |= QUAL_TEMPL; if (is_templ_depend (s)) res |= QUAL_TEMPL; } if (ns == type_error_tag || nt == type_error_tag) { /* Mark error types */ res |= QUAL_TEMPL; } res &= ~(QUAL_EXACT | QUAL_SIMILAR); return (res); } } j++; } return (res); } /* * FIND THE TYPE FOR A POINTER OPERATION * * This routine finds the common type for a pointer operation involving * the pointer types t and s (as used, for example, in the relational * operators). Pointer conversions and qualification conversions are * applied (including base class conversions if base is true), but the * result must be a qualified version of one of the arguments, so only * depth 1 qualification conversions are applied. If t and s cannot be * brought to a common type then the suspect flag is set to 2 and * qualified 'void *' is returned. suspect is set to 1 if precisely * one of the types is 'void *'. The routine also operates on reference * types except that it returns a null type in the 'void *' case. */ TYPE ptr_common_type(TYPE t, TYPE s, int base, int *suspect) { CV_SPEC qt, qs; TYPE r = NULL_type; unsigned tag = TAG_type (t); TYPE pt = DEREF_type (type_ptr_etc_sub (t)); TYPE ps = DEREF_type (type_ptr_etc_sub (s)); unsigned nt = TAG_type (pt); unsigned ns = TAG_type (ps); /* Find the common type */ if (nt == ns) { if (eq_type_unqual (pt, ps)) { /* Pointers to the same type */ r = pt; } else if (nt == type_compound_tag && base) { /* Check for base class conversions */ CLASS_TYPE ct = DEREF_ctype (type_compound_defn (pt)); CLASS_TYPE cs = DEREF_ctype (type_compound_defn (ps)); CLASS_TYPE cr = compare_base_class (ct, cs, 1); if (EQ_ctype (cr, ct)) { /* p is a base class of q */ r = pt; } else if (EQ_ctype (cr, cs)) { /* q is a base class of p */ r = ps; } } } else if (nt == type_top_tag || nt == type_bottom_tag) { /* One pointer is 'void *' */ *suspect = 1; r = pt; } else if (ns == type_top_tag || ns == type_bottom_tag) { /* One pointer is 'void *' */ *suspect = 1; r = ps; } #if LANGUAGE_C if (IS_NULL_type (r)) { /* In C, compatible types are allowed */ r = type_composite (pt, ps, 1, 0, KILL_err, 1); } #endif if (IS_NULL_type (r)) { /* Can't bring to common pointer type */ if (is_templ_type (t) || is_templ_type (s)) { *suspect = -1; } else { *suspect = 2; } if (tag == type_ref_tag) { /* There are no generic references */ return (NULL_type); } r = type_void; } /* Qualify the common type appropriately */ qt = find_cv_qual (pt); qs = find_cv_qual (ps); r = qualify_type (r, (qt | qs), 0); /* Form the result type */ if (EQ_type (r, pt)) return (t); if (EQ_type (r, ps)) return (s); MAKE_type_ptr_etc (tag, cv_none, r, r); return (r); } /* * FIND THE TYPE FOR A POINTER MEMBER OPERATION * * This routine finds the common type for a pointer to member operation * involving the pointer to member types t and s (as used, for example, * in the equality operators). If t and s cannot be brought to a common * type then suspect is set to 2 and the error type is returned. If * the cv-qualifier of the common type is not equal to the cv-qualifier * of either t or s then suspect is set to 1. */ TYPE ptr_mem_common_type(TYPE t, TYPE s, int *suspect) { /* Check for base class conversions */ CLASS_TYPE ct = DEREF_ctype (type_ptr_mem_of (t)); CLASS_TYPE cs = DEREF_ctype (type_ptr_mem_of (s)); CLASS_TYPE cr = compare_base_class (ct, cs, 1); if (!IS_NULL_ctype (cr)) { TYPE pr; TYPE pt = DEREF_type (type_ptr_mem_sub (t)); TYPE ps = DEREF_type (type_ptr_mem_sub (s)); if (EQ_ctype (cr, ct)) { cr = cs; pr = ps; } else { cr = ct; pr = pt; } /* Check that underlying types are the same */ if (eq_type_unqual (pt, ps)) { /* Form the result type */ CV_SPEC qt = find_cv_qual (pt); CV_SPEC qs = find_cv_qual (ps); CV_SPEC qr = (qt | qs); pr = qualify_type (pr, qr, 0); if (qt != qs && qr != qs) *suspect = 1; if (EQ_ctype (cr, ct) && EQ_type (pr, pt)) return (t); if (EQ_ctype (cr, cs) && EQ_type (pr, ps)) return (s); MAKE_type_ptr_mem (cv_none, cr, pr, pr); return (pr); } } /* Can't bring to common pointer member type */ if (is_templ_type (t) || is_templ_type (s)) { *suspect = -1; } else { *suspect = 2; } return (type_error); } /* * FIND A COMMON TYPE * * This routine finds the common type for the types t and s. This is * the other type if either type is null, the single type if they are * equal, the arithmetic type if they are both arithmetic and the common * pointer, reference or pointer-to-member type if these are appropriate. * The null type is returned if the common type cannot be formed and * suspect is set accordingly. The rules are essentially the same as * for the '?:' operation. */ TYPE common_type(TYPE t, TYPE s, int *suspect) { unsigned nt, ns; TYPE r = NULL_type; if (IS_NULL_type (t)) return (s); if (IS_NULL_type (s)) return (t); nt = TAG_type (t); ns = TAG_type (s); if (nt == ns) { switch (nt) { case type_ptr_tag : case type_ref_tag : { /* Common pointer or reference type */ r = ptr_common_type (t, s, 1, suspect); if (*suspect != 2) return (r); r = NULL_type; break; } case type_ptr_mem_tag : { /* Common pointer to member type */ r = ptr_mem_common_type (t, s, suspect); if (*suspect != 2) return (r); r = NULL_type; break; } default : { /* Other types */ if (eq_type_unqual (t, s)) { CV_SPEC qt = find_cv_qual (t); CV_SPEC qs = find_cv_qual (s); if (qt != qs) { *suspect = 1; t = qualify_type (t, (qt | qs), 0); } return (t); } break; } } } switch (nt) { case type_integer_tag : case type_enumerate_tag : case type_bitfield_tag : case type_floating_tag : { switch (ns) { case type_integer_tag : case type_enumerate_tag : case type_bitfield_tag : case type_floating_tag : { /* Common arithmetic type */ r = arith_type (t, s, NULL_exp, NULL_exp); return (r); } } } } #if LANGUAGE_C if (IS_NULL_type (r)) { r = type_composite (t, s, 1, 0, KILL_err, 1); if (!IS_NULL_type (r)) return (r); } #endif if (nt == type_error_tag) return (s); if (ns == type_error_tag) return (t); *suspect = 2; return (r); } /* * CONVERT AN EXPRESSION TO ITS PROMOTED TYPE * * This routine converts the expression e to its promoted type, t * (previously calculated using promote_type). Note that there is no * effect unless t is an integral type. */ EXP convert_promote(TYPE t, EXP e) { if (IS_type_integer (t)) { TYPE s = DEREF_type (exp_type (e)); if (!EQ_type (t, s)) { /* Perform non-trivial integral promotions */ e = cast_int_int (t, e, KILL_err, CAST_IMPLICIT, 0); } } return (e); } /* * CONVERT AN EXPRESSION TO ITS ARITHMETIC TYPE * * This routine converts the expression e to an arithmetic result type, t, * formed by arith_type using the type of e as its nth argument. Note that * there are three cases: integer->integer, integer->float and float->float. */ EXP convert_arith(TYPE t, EXP e, int op, int n) { TYPE s = DEREF_type (exp_type (e)); if (!EQ_type (t, s)) { ERROR err = NULL_err; if (IS_type_floating (t)) { unsigned tag = TAG_type (s); if (tag == type_floating_tag) { e = cast_float_float (t, e, &err, CAST_IMPLICIT); } else { if (tag == type_bitfield_tag) { s = find_bitfield_type (s); e = cast_int_int (s, e, &err, CAST_IMPLICIT, -1); } e = cast_int_float (t, e, &err, CAST_IMPLICIT); } } else { e = cast_int_int (t, e, &err, CAST_IMPLICIT, -1); } if (!IS_NULL_err (err)) { unsigned m = (unsigned) n; err = concat_error (err, ERR_expr_convert_op (m, op)); report (crt_loc, err); } } return (e); } /* * CONVERT A POINTER TO A COMMON POINTER TYPE * * This routine converts the pointer expression e to a common pointer * type, t, formed by ptr_common_type using the type of e as its nth * argument. */ EXP convert_ptr_common(TYPE t, EXP e, int op, int n) { TYPE s = DEREF_type (exp_type (e)); if (!EQ_type (t, s)) { ERROR err = NULL_err; e = cast_ptr_ptr (t, e, &err, CAST_IMPLICIT, 1, 1); if (!IS_NULL_err (err)) { unsigned m = (unsigned) n; err = concat_error (err, ERR_expr_convert_op (m, op)); report (crt_loc, err); } } return (e); } /* * CONVERT A POINTER MEMBER TO A COMMON POINTER MEMBER TYPE * * This routine converts the pointer member expression e to a common * pointer to member type, t, formed by ptr_mem_common_type using the * type of e as its nth argument. */ EXP convert_ptr_mem_common(TYPE t, EXP e, int op, int n) { TYPE s = DEREF_type (exp_type (e)); if (!EQ_type (t, s)) { ERROR err = NULL_err; e = cast_ptr_mem_ptr_mem (t, e, &err, CAST_IMPLICIT, 1, 1); if (!IS_NULL_err (err)) { unsigned m = (unsigned) n; err = concat_error (err, ERR_expr_convert_op (m, op)); report (crt_loc, err); } } return (e); } /* * CHECK FOR ASSIGNMENT IN A BOOLEAN * * This routine checks whether the expression a, which is to be converted * to a boolean, is an assignment. A warning is issued for 'x = y' and * 'x /= y' because of possible confusion with 'x == y' and 'x != y' * respectively. If the original expression was enclosed in brackets * (as indicated by tag) then no warning is issued. */ static void boolean_assign(EXP a, unsigned tag) { if (tag != exp_paren_tag && !suppress_quality) { if (IS_exp_assign (a)) { report (crt_loc, ERR_conv_bool_assign ()); } else if (IS_exp_preinc (a)) { int op = DEREF_int (exp_preinc_becomes (a)); if (op == lex_assign || op == lex_div_Heq) { report (crt_loc, ERR_conv_bool_assign ()); } } } return; } /* * CONVERT AN EXPRESSION TO A BOOLEAN * * This routine converts the expression a to a boolean if this is possible, * returning the corresponding boolean expression. Any error arising are * added to the position indicated by the err argument. User-defined * conversions are handled elsewhere. */ EXP convert_boolean(EXP a, unsigned tag, ERROR *err) { EXP e; TYPE t = DEREF_type (exp_type (a)); switch (TAG_exp (a)) { case exp_int_lit_tag : { /* Check for integer literals */ e = make_test_nat (a); return (e); } case exp_float_lit_tag : { /* Check for floating-point literals */ FLOAT f = DEREF_flt (exp_float_lit_flt (a)); unsigned v = BOOL_VALUE (!is_zero_float (f)); e = make_bool_exp (v, exp_float_lit_tag); return (e); } case exp_contents_tag : { /* Check for assignment in boolean */ EXP b = DEREF_exp (exp_contents_ptr (a)); switch (TAG_exp (b)) { case exp_assign_tag : case exp_preinc_tag : case exp_postinc_tag : { boolean_assign (b, tag); break; } } break; } case exp_assign_tag : case exp_preinc_tag : case exp_postinc_tag : { /* Check for assignment in boolean */ boolean_assign (a, tag); break; } } /* Perform the conversion */ switch (TAG_type (t)) { case type_integer_tag : { /* Integral types are allowed */ if (check_int_type (t, btype_bool)) return (a); break; } case type_bitfield_tag : { /* Convert bitfields to integers */ a = convert_bitfield (a); break; } case type_enumerate_tag : case type_floating_tag : case type_ptr_tag : case type_ptr_mem_tag : { /* These types are allowed */ break; } case type_error_tag : { /* Allow for error propagation */ break; } default : { /* These types are not allowed */ add_error (err, ERR_conv_bool_cast (t)); break; } } MAKE_exp_test (type_bool, ntest_not_eq, a, e); return (e); } /* * REPORT OVERLOADED FUNCTIONS * * This routine prints an error and returns true if e represents an * overloaded function. If it represents a non-overloaded function which * has not already resolved using resolve_cast then the function is * marked as used. */ static int is_overloaded(EXP e) { if (!IS_NULL_exp (e) && IS_exp_identifier_etc (e)) { IDENTIFIER id = DEREF_id (exp_identifier_etc_id (e)); if (IS_id_function_etc (id)) { QUALIFIER q = DEREF_qual (exp_identifier_etc_qual (e)); if (!(q & qual_mark)) { /* Not already resolved */ TYPE fn = DEREF_type (id_function_etc_type (id)); IDENTIFIER over = DEREF_id (id_function_etc_over (id)); if (!IS_NULL_id (over) || IS_type_templ (fn)) { /* Overloaded function */ report (crt_loc, ERR_over_over_context (id)); return (1); } use_id (id, suppress_usage); } } } return (0); } /* * PERFORM QUALIFICATION CONVERSIONS ON A TYPE * * This routine removes any type qualifiers from a rvalue, non-class * type t. Class types maintain their type qualifiers, lvalue types * lose theirs in convert_lvalue. */ TYPE convert_qual_type(TYPE t) { CV_SPEC qual = DEREF_cv (type_qual (t)); if (qual && !(qual & cv_lvalue)) { #if LANGUAGE_CPP if (IS_type_compound (t)) return (t); #endif t = qualify_type (t, cv_none, 0); } return (t); } /* * EVALUATE A CONST VARIABLE * * This routine evaluates the 'const' variable expression a, so that * for example, if 'const int c = 5 ;' then 'c' is evaluated to '5'. */ EXP convert_const(EXP a) { #if LANGUAGE_CPP IDENTIFIER id = DEREF_id (exp_identifier_id (a)); EXP e = DEREF_exp (id_variable_etc_init (id)); if (!IS_NULL_exp (e)) { switch (TAG_exp (e)) { case exp_int_lit_tag : { /* Propagate simple constants */ NAT n; TYPE t; unsigned tag; DECONS_exp_int_lit (t, n, tag, e); MAKE_exp_int_lit (t, n, tag, e); return (e); } case exp_null_tag : { /* Propagate null constants */ TYPE t; int ptr_const; DECONS_exp_null (t, ptr_const, e); MAKE_exp_null (t, e); COPY_int (exp_null_ptr_const (e), ptr_const); return (e); } } } #endif return (a); } /* * PERFORM ARRAY TO POINTER CONVERSION * * This routine performs array to pointer conversion on the array * expression a. If a is a string literal and str is true then the * const qualifiers are removed from the string. A warning is also * added to err if str is 2. */ EXP convert_array(EXP a, int str, ERROR *err) { TYPE t = DEREF_type (exp_type (a)); TYPE s = DEREF_type (type_array_sub (t)); if (str && IS_exp_string_lit (a)) { /* Remove const from string literals */ CV_SPEC cv = DEREF_cv (type_qual (s)); if (cv & cv_const) { cv &= ~cv_const; s = qualify_type (s, cv, 0); if (str == 2) add_error (err, ERR_conv_array_string ()); } } else if (option (OPT_addr_register) && used_register) { /* Can't apply to a register variable in C */ EXP b = NULL_exp; DECL_SPEC ds = find_exp_linkage (a, &b, 1); if ((ds & dspec_register) && !(ds & dspec_temp)) { if (IS_exp_identifier (b)) { IDENTIFIER id = DEREF_id (exp_identifier_id (b)); add_error (err, ERR_expr_unary_op_ref_register (id)); } } } MAKE_type_ptr (cv_none, s, t); MAKE_exp_address (t, a, a); return (a); } /* * PERFORM LVALUE CONVERSIONS * * This routine performs the lvalue conversions on the expression a. * If e is an lvalue, the lvalue-to-rvalue, array-to-pointer and * function-to-pointer conversions are applied to transform it into an * rvalue. Checks for overloaded functions are also applied at this * stage to both lvalues and rvalues. */ EXP convert_lvalue(EXP a) { EXP e = a; TYPE t = DEREF_type (exp_type (a)); CV_SPEC qual = DEREF_cv (type_qual (t)); if (qual & cv_lvalue) { CV_SPEC cv = cv_none; switch (TAG_type (t)) { case type_array_tag : { /* Array-to-pointer conversion */ ERROR err = NULL_err; e = convert_array (a, 0, &err); if (!IS_NULL_err (err)) report (crt_loc, err); break; } case type_func_tag : { /* Function-to-pointer conversion */ if (is_overloaded (a)) { e = make_error_exp (0); break; } if (IS_exp_member (a)) goto default_lab; MAKE_type_ptr (cv_none, t, t); MAKE_exp_address (t, a, e); break; } #if LANGUAGE_CPP case type_compound_tag : { /* Classes preserve qualifiers in lvalue conversion */ cv = (qual & cv_qual); goto default_lab; } #endif case type_templ_tag : { /* Can't have template expressions */ if (!is_overloaded (a)) { report (crt_loc, ERR_temp_local_not (t)); } e = make_error_exp (0); break; } default : default_lab : { /* Lvalue-to-rvalue conversion */ ERROR err; if (qual == (cv_const | cv_lvalue)) { /* Check for constants at this stage */ if (IS_exp_identifier (a)) { e = convert_const (a); if (!EQ_exp (e, a)) return (e); } } t = qualify_type (t, cv, 0); err = check_incomplete (t); if (!IS_NULL_err (err)) { err = concat_error (err, ERR_conv_lval_incompl ()); report (crt_loc, err); } MAKE_exp_contents (t, a, e); break; } } } else { /* Check rvalues for overloaded functions */ switch (TAG_exp (e)) { case exp_address_tag : { /* Address of object or function */ EXP b = DEREF_exp (exp_address_arg (a)); if (is_overloaded (b)) e = make_error_exp (0); break; } case exp_address_mem_tag : { /* Address of member or member function */ EXP b = DEREF_exp (exp_address_mem_arg (a)); if (is_overloaded (b)) e = make_error_exp (0); break; } case exp_token_tag : { /* Check for tokenised arrays */ if (IS_type_array (t)) { ERROR err = NULL_err; e = convert_array (a, 0, &err); if (!IS_NULL_err (err)) report (crt_loc, err); } break; } } } return (e); } /* * CHECK AMBIGUOUS IDENTIFIERS * * This routine checks whether the identifier id represents a non-member * function or an ambiguous set of such functions. It is required because * overload resolution is used to distinguish between the ambiguous cases * for non-member functions, whereas it is an error otherwise. */ int is_ambiguous_func(IDENTIFIER id) { switch (TAG_id (id)) { case id_ambig_tag : { /* Deal with ambiguous identifiers */ LIST (IDENTIFIER) p = DEREF_list (id_ambig_ids (id)); while (!IS_NULL_list (p)) { id = DEREF_id (HEAD_list (p)); if (!is_ambiguous_func (id)) return (0); p = TAIL_list (p); } return (1); } case id_function_tag : { /* These are functions */ return (1); } } return (0); } /* * PERFORM REFERENCE CONVERSIONS * * This routine performs the reference conversions on the expression a. * That is, if a has type reference to t, then it is transformed into an * lvalue of type t. Other checks are also applied to a - for example, * parentheses are removed, undeclared variables are reported, and * constants are evaluated. The precise checks applied depend on context * which can take one of the values from convert.h. */ EXP convert_reference(EXP a, int context) { /* Remove parentheses */ TYPE t; unsigned etag = TAG_exp (a); if (etag == exp_paren_tag) { do { DESTROY_exp_paren (destroy, t, a, a); etag = TAG_exp (a); } while (etag == exp_paren_tag); } else { t = DEREF_type (exp_type (a)); } /* Apply extra checks */ switch (etag) { case exp_member_tag : { /* Non-static data members and all function members */ if (context == REF_ADDRESS) { /* Suppress reference conversions */ t = type_error; } else { IDENTIFIER id = DEREF_id (exp_member_id (a)); if (context == REF_NORMAL || IS_id_member (id)) { EXP b = make_this_field (id); if (IS_NULL_exp (b)) { report (crt_loc, ERR_expr_prim_mem (id)); a = make_error_exp (0); } else { a = b; if (IS_exp_call (a)) goto call_lab; } t = DEREF_type (exp_type (a)); etag = TAG_exp (a); } } break; } case exp_ambiguous_tag : { /* Ambiguous identifiers */ IDENTIFIER id = DEREF_id (exp_ambiguous_id (a)); if (context == REF_NORMAL || !is_ambiguous_func (id)) { /* Report ambiguous identifier */ IGNORE report_ambiguous (id, 0, 1, 0); a = make_error_exp (0); t = DEREF_type (exp_type (a)); } else { /* Allow ambiguous functions */ t = type_func_void; t = lvalue_type (t); COPY_type (exp_type (a), t); } break; } case exp_undeclared_tag : { /* Undeclared identifiers */ if (context == REF_FUNCTION || context == REF_ADDRESS) { /* Deal with undeclared functions later */ t = type_func_void; t = lvalue_type (t); COPY_type (exp_type (a), t); } else { /* Report undeclared identifiers */ IDENTIFIER id = DEREF_id (exp_undeclared_id (a)); crt_id_qualifier = DEREF_qual (exp_undeclared_qual (a)); a = implicit_id_exp (id, 0); t = DEREF_type (exp_type (a)); } break; } case exp_address_tag : { /* Address of object */ EXP b = DEREF_exp (exp_address_arg (a)); unsigned btag = TAG_exp (b); if (btag == exp_ambiguous_tag) { if (context != REF_FUNCTION && context != REF_ASSIGN) { /* Ambiguous function */ b = convert_reference (b, REF_NORMAL); a = make_ref_exp (b, 1); t = DEREF_type (exp_type (a)); } } else if (btag == exp_undeclared_tag) { if (context != REF_FUNCTION) { /* Undeclared function */ b = convert_reference (b, REF_NORMAL); a = make_ref_exp (b, 1); t = DEREF_type (exp_type (a)); } } else if (btag == exp_call_tag) { if (context != REF_ASSIGN) { b = DEREF_exp (exp_call_ptr (b)); if (IS_exp_member (b)) { /* Member function selector */ if (!is_overloaded (b)) { report (crt_loc, ERR_expr_ref_call ()); } a = make_error_exp (0); t = DEREF_type (exp_type (a)); } } } break; } case exp_call_tag : call_lab : { /* All member function calls */ if (context != REF_FUNCTION) { EXP b = DEREF_exp (exp_call_ptr (a)); unsigned btag = TAG_exp (b); if (btag == exp_identifier_tag) { /* Single static member function */ IDENTIFIER id = DEREF_id (exp_identifier_id (b)); use_id (id, suppress_usage); a = DEREF_exp (exp_call_arg (a)); a = join_exp (a, b); t = DEREF_type (exp_type (a)); break; } if (btag == exp_member_tag) { /* Other member functions */ if (context != REF_NORMAL) break; if (!is_overloaded (b)) { report (crt_loc, ERR_expr_ref_call ()); } } else { /* Pointer to member functions */ report (crt_loc, ERR_expr_mptr_oper_call ()); } a = make_error_exp (0); t = DEREF_type (exp_type (a)); } break; } } /* Check for reference conversions */ if (IS_type_ref (t)) { /* Reference to t becomes lvalue t */ if (etag == exp_indir_tag) { /* Can't have two indirections in a row */ MAKE_exp_contents (t, a, a); } t = DEREF_type (type_ref_sub (t)); /* Note that t is already an lvalue */ MAKE_exp_indir (t, a, a); } return (a); } /* * PROMOTE BITFIELD EXPRESSIONS * * In certain expressions, even though an integral operand is not subject * to integer promotion, bitfield expressions need to be converted to * integral expressions by promotion. This routine performs this conversion * for the expression a. */ EXP convert_bitfield(EXP a) { TYPE t = DEREF_type (exp_type (a)); if (IS_type_bitfield (t)) { t = promote_type (t); a = convert_promote (t, a); } return (a); } /* * CONVERT OPERAND WHERE NO CONTEXT IS GIVEN * * This routine performs conversions on the operand a in contexts where * there is no information to resolve overloaded functions etc. It also * introduces temporary variables for constructor call expressions. */ EXP convert_none(EXP a) { if (!IS_NULL_exp (a)) { ERROR err = NULL_err; if (IS_exp_constr (a)) { TYPE t = DEREF_type (exp_type (a)); a = make_temporary (t, a, NULL_exp, 0, &err); a = convert_lvalue (a); } else { LIST (IDENTIFIER) pids = NULL_list (IDENTIFIER); a = resolve_cast (type_void, a, &err, 1, 0, pids); } if (!IS_NULL_err (err)) report (crt_loc, err); } return (a); } /* * QUALIFICATION CONVERSIONS * * The values cv_const and cv_volatile are used to represent qualification * conversions which add the corresponding qualifiers at a single level. * cv_strlit is used to represent the removal of const from a string * literal. cv_multi is used to represent qualifications which add * qualifiers at more than one level. */ #define cv_strlit ((CV_SPEC) 0x10) #define cv_multi ((CV_SPEC) 0x20) /* * CHECK FOR OVERLOADED FUNCTION CONVERSION SEQUENCES * * This routine checks for conversion sequences between the overloaded * function id and the pointer or pointer to member (of the correct class) * type t. */ static unsigned overload_convert_seq(TYPE t, IDENTIFIER id, CONVERSION *p) { /* Check arguments */ TYPE fn; int eq = 0; CV_SPEC cv; unsigned conv = CONV_EXACT; unsigned tag = TAG_type (t); if (tag == type_ptr_tag) { fn = DEREF_type (type_ptr_sub (t)); } else { fn = DEREF_type (type_ptr_mem_sub (t)); } if (!IS_type_func (fn)) return (CONV_NONE); cv = DEREF_cv (type_qual (fn)); cv &= cv_qual; if (cv != cv_none) conv = CONV_QUAL; p->qual = cv; /* Check for matching overload function */ id = resolve_func (id, fn, 1, 0, NULL_list (IDENTIFIER), &eq); if (!IS_NULL_id (id) && eq == 3) { switch (TAG_id (id)) { case id_mem_func_tag : { /* A member function gives a pointer to member */ if (tag == type_ptr_mem_tag) return (conv); break; } case id_function_tag : case id_stat_mem_func_tag : { /* Other functions give pointers */ if (tag == type_ptr_tag) return (conv); break; } } } return (CONV_NONE); } /* * CHECK FOR REFERENCE CONVERSION SEQUENCES * * This routine checks the conversion sequence p, the destination type * of which is a reference type. If std is true then only standard * conversions will be applied. bind describes the form of reference * binding to take place. The normal value is 0, implements the normal * reference binding rules. A value of 1 is used to suppress all * rvalue reference bindings. Values of 2 and 3 allow rvalues of * related types to be bound to any reference (not just const references), * with 2 further regarding any base class conversions as exact matches. */ static unsigned ref_convert_seq(CONVERSION *p, EXP e, int bind, int std) { unsigned conv; TYPE t = DEREF_type (type_ref_sub (p->to)); TYPE s = p->from; unsigned nt = TAG_type (t); unsigned ns = TAG_type (s); CV_SPEC qs = DEREF_cv (type_qual (s)); if (qs & cv_lvalue) { CV_SPEC cv = cv_compare (t, s); if (cv == cv_none) { /* Qualifiers are alright */ cv = cv_compare (s, t); p->qual = cv; if (eq_type_unqual (s, t)) { if (cv == cv_none) { conv = CONV_EXACT; } else { conv = CONV_QUAL; } return (conv); } if (ns == type_compound_tag && nt == type_compound_tag) { CLASS_TYPE ct = DEREF_ctype (type_compound_defn (t)); CLASS_TYPE cs = DEREF_ctype (type_compound_defn (s)); if (eq_ctype (ct, cs)) { /* Classes match */ if (cv == cv_none) { conv = CONV_EXACT; } else { conv = CONV_QUAL; } return (conv); } else { /* Check for base classes */ GRAPH gr = find_base_class (cs, ct, 0); if (!IS_NULL_graph (gr)) { /* Base class conversion */ p->base = gr; if (bind == 2) { /* Base class conversions match exactly */ if (cv == cv_none) { conv = CONV_EXACT; } else { conv = CONV_QUAL; } } else { conv = CONV_BASE; } return (conv); } } } } } if (bind == 0) { /* Default - only const references allowed */ CV_SPEC qt = find_cv_qual (t); if (qt != (cv_lvalue | cv_const)) return (CONV_NONE); qs = find_cv_qual (s); if (qs & cv_volatile) return (CONV_NONE); } else if (bind == 1) { /* No references allowed */ return (CONV_NONE); } else { /* All references allowed */ std = 1; } p->to = t; p->from = s; if (std) { conv = std_convert_seq (p, e, bind, 1); } else { conv = convert_seq (p, e, bind, 1); } if (bind == 2) { /* Base class conversions match exactly */ if (conv == CONV_BASE) { if (p->qual == cv_none) { conv = CONV_EXACT; } else { conv = CONV_QUAL; } } } return (conv); } /* * CHECK FOR STANDARD CONVERSION SEQUENCES * * This routine checks whether there is a standard conversion sequence * between the types given by p. e gives the argument being converted * (this is only used in identifying null pointer and null pointer member * conversions). The arguments bind and ref describe how reference bindings * are to be treated (see above). Note that conversion are applied in * the canonical sequence, lvalue transformations, promotions, conversions * and qualification adjustments. The routine returns the value indicating * the rank of this conversion. */ unsigned std_convert_seq(CONVERSION *p, EXP e, int bind, int ref) { CV_SPEC qs; int str = 0; unsigned etag; TYPE t = p->to; TYPE s = p->from; unsigned nt, ns; unsigned conv = CONV_NONE; /* Conversion to the null type counts as exact */ if (IS_NULL_type (t)) return (CONV_EXACT); /* Conversion from the error type counts as ellipsis */ ns = TAG_type (s); if (ns == type_error_tag) return (CONV_ELLIPSIS); qs = DEREF_cv (type_qual (s)); /* Reference conversion */ if (ns == type_ref_tag) { s = DEREF_type (type_ref_sub (s)); p->from = s; ns = TAG_type (s); if (ns == type_error_tag) return (CONV_ELLIPSIS); qs = DEREF_cv (type_qual (s)); } /* Deal with conversions to reference types */ nt = TAG_type (t); if (nt == type_ref_tag) { conv = ref_convert_seq (p, e, bind, 1); return (conv); } /* Examine expression */ etag = (IS_NULL_exp (e) ? null_tag : TAG_exp (e)); /* Lvalue transformations */ if (qs & cv_lvalue) { if (ns == type_func_tag) { /* Function to pointer conversion */ if (etag != exp_member_tag) { TYPE ps = s; s = type_temp_star; COPY_type (type_ptr_sub (s), ps); ns = type_ptr_tag; } } else if (ns == type_array_tag) { /* Array to pointer conversion */ TYPE ps = DEREF_type (type_array_sub (s)); s = type_temp_star; COPY_type (type_ptr_sub (s), ps); ns = type_ptr_tag; } else { /* lvalue to rvalue conversion */ if (etag == exp_identifier_tag) { if (qs == (cv_lvalue | cv_const)) { IDENTIFIER id = DEREF_id (exp_identifier_id (e)); EXP d = DEREF_exp (id_variable_etc_init (id)); if (is_zero_exp (d)) { /* Propagate zero constants */ e = d; } } } } } /* Promotions and conversions */ switch (ns) { case type_integer_tag : case type_enumerate_tag : integral_lab : { /* Integral and similar arguments */ if (nt == ns && eq_type_unqual (t, s)) { /* Exact match */ conv = CONV_EXACT; } else { TYPE ps = promote_type (s); if (!EQ_type (ps, s) && eq_type_unqual (t, ps)) { /* Integral promotion */ conv = CONV_INT_PROM; } else if (nt == type_integer_tag) { /* Integral conversions (subsumes booleans) */ conv = CONV_INT_INT; } else if (nt == type_floating_tag) { /* Floating-integer conversions */ conv = CONV_INT_FLT; } else if (is_zero_exp (e)) { if (nt == type_ptr_tag) { /* Null pointers */ conv = CONV_PTR_NULL; } else if (nt == type_ptr_mem_tag) { /* Null pointer members */ conv = CONV_PTR_MEM_NULL; } } } break; } case type_bitfield_tag : { /* Ignore any bitfield qualifiers */ s = find_bitfield_type (s); ns = TAG_type (s); goto integral_lab; } case type_floating_tag : { /* Floating point arguments */ if (nt == type_floating_tag) { if (eq_type_unqual (t, s)) { /* Exact match */ conv = CONV_EXACT; } else { TYPE ps = arg_promote_type (s, KILL_err); if (!EQ_type (ps, s) && eq_type_unqual (t, ps)) { /* Floating point promotion */ conv = CONV_FLT_PROM; } else { /* Floating point conversions */ conv = CONV_FLT_FLT; } } } else if (nt == type_integer_tag) { /* Floating-integer conversions (subsumes booleans) */ conv = CONV_FLT_INT; } break; } case type_ptr_tag : pointer_lab : { /* Pointer arguments */ if (nt == type_ptr_tag) { /* Check for qualifier conversions */ unsigned qual = check_qualifier (t, s, 0); if (qualifier_depth <= 1) { CV_SPEC cv = qualifier_diff; if (str) cv |= cv_strlit; p->qual = cv; } else { p->qual = cv_multi; } if (qual == QUAL_EQUAL || qual == QUAL_EQ_FUNC) { /* Exact match */ conv = CONV_EXACT; if (str) conv = CONV_STRING; } else if (qual == QUAL_OK) { /* Qualification conversion */ conv = CONV_QUAL; if (str) conv = CONV_STRING; } else if (qual == QUAL_CV) { /* Conversion preserves cv-qualifiers */ TYPE pt = DEREF_type (type_ptr_sub (t)); TYPE ps = DEREF_type (type_ptr_sub (s)); nt = TAG_type (pt); ns = TAG_type (ps); if (nt == type_compound_tag && ns == nt) { /* Pointer base class conversions */ GRAPH gr; CLASS_TYPE ct, cs; ct = DEREF_ctype (type_compound_defn (pt)); cs = DEREF_ctype (type_compound_defn (ps)); gr = find_base_class (cs, ct, 0); if (!IS_NULL_graph (gr)) { /* Don't worry about ambiguity */ p->base = gr; conv = CONV_PTR_BASE; } } else if (nt == type_top_tag) { if (ns != type_func_tag) { /* Pointer to 'void *' conversions */ conv = CONV_PTR_VOID; } } else if (nt == type_bottom_tag) { if (ns != type_func_tag) { /* Pointer to 'void *' conversions */ conv = CONV_PTR_BOTTOM; } } } if (conv == CONV_NONE) { /* Check for string literals */ if (etag == exp_string_lit_tag && !str) { if (!(qual & QUAL_CONST)) { TYPE ps = DEREF_type (type_ptr_sub (s)); ps = qualify_type (ps, cv_none, 0); s = type_temp_star; COPY_type (type_ptr_sub (s), ps); str = 1; goto pointer_lab; } } /* Check for overloaded functions */ if (etag == exp_address_tag) { e = DEREF_exp (exp_address_arg (e)); etag = TAG_exp (e); } if (etag == exp_identifier_tag) { IDENTIFIER id = DEREF_id (exp_identifier_id (e)); conv = overload_convert_seq (t, id, p); } else if (etag == exp_ambiguous_tag) { IDENTIFIER id = DEREF_id (exp_ambiguous_id (e)); conv = overload_convert_seq (t, id, p); } } } else if (nt == type_integer_tag) { if (check_int_type (t, btype_bool)) { /* Boolean conversions */ conv = CONV_BOOL; } } break; } #if LANGUAGE_CPP case type_ptr_mem_tag : { /* Pointer to member arguments */ if (nt == type_ptr_mem_tag) { unsigned qual; int ctype_match = 0; CLASS_TYPE ct = DEREF_ctype (type_ptr_mem_of (t)); CLASS_TYPE cs = DEREF_ctype (type_ptr_mem_of (s)); if (eq_ctype (ct, cs)) { ctype_match = 2; } else { GRAPH gr = find_base_class (ct, cs, 0); if (!IS_NULL_graph (gr)) { ctype_match = 1; p->base = gr; } } if (ctype_match) { if (etag == exp_address_mem_tag) { /* Check overloaded functions */ IDENTIFIER id; e = DEREF_exp (exp_address_mem_arg (e)); id = DEREF_id (exp_member_id (e)); if (IS_id_function_etc (id)) { conv = overload_convert_seq (t, id, p); if (conv != CONV_NONE && ctype_match == 1) { conv = CONV_PTR_MEM_BASE; } break; } } /* Check other cases */ qual = check_qualifier (t, s, 0); if (qualifier_depth <= 1) { p->qual = qualifier_diff; } else { p->qual = cv_multi; } if (qual == QUAL_EQUAL || qual == QUAL_EQ_FUNC) { /* Exact match */ if (ctype_match == 2) { conv = CONV_EXACT; } else { conv = CONV_PTR_MEM_BASE; } } else if (qual == QUAL_OK) { /* Qualification conversion */ if (ctype_match == 2) { conv = CONV_QUAL; } else { conv = CONV_PTR_MEM_BASE; } } } } else if (nt == type_integer_tag) { if (check_int_type (t, btype_bool)) { /* Boolean conversions */ conv = CONV_BOOL; } } else if (nt == type_ptr_tag) { if (etag == exp_address_mem_tag) { /* Check overloaded functions */ IDENTIFIER id; e = DEREF_exp (exp_address_mem_arg (e)); id = DEREF_id (exp_member_id (e)); conv = overload_convert_seq (t, id, p); } } break; } #endif case type_compound_tag : { /* Class arguments */ if (nt == type_compound_tag) { CV_SPEC cv = cv_compare (t, s); if (cv == cv_none || !ref) { CLASS_TYPE ct, cs; cv = cv_compare (s, t); p->qual = cv; ct = DEREF_ctype (type_compound_defn (t)); cs = DEREF_ctype (type_compound_defn (s)); if (eq_ctype (ct, cs)) { /* Class types match */ if (cv == cv_none) { conv = CONV_EXACT; } else { conv = CONV_QUAL; } } else { /* Examine base classes */ GRAPH gr = find_base_class (cs, ct, 0); if (!IS_NULL_graph (gr)) { /* Base class conversion */ p->base = gr; conv = CONV_BASE; } } } } break; } case type_func_tag : { /* Address of overloaded static member function */ if (nt == type_ptr_tag && etag == exp_member_tag) { IDENTIFIER id = DEREF_id (exp_member_id (e)); conv = overload_convert_seq (t, id, p); } break; } case type_token_tag : { /* Exact conversion on tokenised type */ if (nt == ns && eq_type_unqual (t, s)) { conv = CONV_EXACT; } break; } } return (conv); } /* * CHECK FOR CONVERSION SEQUENCES * * This routine checks whether there is an implicit conversion sequence * corresponding to p. e gives the argument being converted. It returns * the value indicating the rank of this conversion. This is used in * overload resolution to determine the best viable function. */ unsigned convert_seq(CONVERSION *p, EXP e, int bind, int ref) { int match = 0; unsigned conv; TYPE t = p->to; TYPE s = p->from; unsigned nt, ns; CONVERSION user, best; best.rank = CONV_NONE; /* Conversion to the null type counts as exact */ if (IS_NULL_type (t)) return (CONV_EXACT); nt = TAG_type (t); /* Conversion from the error type counts as ellipsis */ ns = TAG_type (s); if (ns == type_error_tag) return (CONV_ELLIPSIS); /* Reference conversion */ if (ns == type_ref_tag) { s = DEREF_type (type_ref_sub (s)); ns = TAG_type (s); if (ns == type_error_tag) return (CONV_ELLIPSIS); } /* Conversion to class type */ if (nt == type_compound_tag && bind != 1) { IDENTIFIER id; CLASS_TYPE ct = DEREF_ctype (type_compound_defn (t)); complete_class (ct, 1); id = DEREF_id (ctype_constr (ct)); if (ns == type_compound_tag) { /* Check for base class conversion */ conv = std_convert_seq (p, e, bind, ref); if (conv != CONV_NONE) return (conv); p->from = s; p->to = t; } user.from = s; if (IS_id_function_etc (id)) { while (!IS_NULL_id (id)) { DECL_SPEC ds = DEREF_dspec (id_storage (id)); if (!(ds & dspec_explicit)) { LIST (TYPE) q; TYPE fn = DEREF_type (id_function_etc_type (id)); while (IS_type_templ (fn)) { fn = DEREF_type (type_templ_defn (fn)); } q = DEREF_list (type_func_ptypes (fn)); if (IS_NULL_list (q)) { /* Match with ellipsis */ int ell = DEREF_int (type_func_ellipsis (fn)); if (ell) { conv = CONV_ELLIPSIS; } else { conv = CONV_NONE; } } else { /* Match with parameter */ user.to = DEREF_type (HEAD_list (q)); if (min_no_args (fn) <= 2) { conv = std_convert_seq (&user, e, bind, 0); } else { conv = CONV_NONE; } } if (conv != CONV_NONE) { /* Compare against previous conversion */ if (!match) { user.rank = conv; user.usr = id; user.std = conv; best = user; } match++; } } id = DEREF_id (id_function_etc_over (id)); } } } /* Conversion from class type */ if (ns == type_compound_tag && bind != 1) { /* Check for user-defined conversions */ LIST (IDENTIFIER) convs; CLASS_TYPE cs = DEREF_ctype (type_compound_defn (s)); complete_class (cs, 1); convs = DEREF_list (ctype_conv (cs)); if (nt == type_ref_tag) { /* Check for base class conversion */ TYPE pt = DEREF_type (type_ref_sub (t)); if (IS_type_compound (pt)) { conv = ref_convert_seq (p, e, bind, 1); if (conv != CONV_NONE) return (conv); p->from = s; p->to = t; } } user.to = t; while (!IS_NULL_list (convs)) { IDENTIFIER id = DEREF_id (HEAD_list (convs)); DECL_SPEC ds = DEREF_dspec (id_storage (id)); if (!(ds & dspec_explicit)) { TYPE fn = DEREF_type (id_function_etc_type (id)); if (IS_type_templ (fn)) { /* Allow for template functions */ fn = deduce_conv (fn, t); } if (!IS_NULL_type (fn)) { TYPE r = DEREF_type (type_func_ret (fn)); user.from = r; if (eq_type (r, t)) { conv = CONV_EXACT; } else { conv = std_convert_seq (&user, e, bind, 0); } if (conv != CONV_NONE) { /* Compare against previous conversion */ if (!match) { user.rank = conv; user.usr = id; user.std = conv; best = user; } match++; } } } convs = TAIL_list (convs); } } /* User-defined conversion sequences */ if (match) { *p = best; if (match == 1) return (CONV_USER); return (CONV_USER_MULTI); } /* Deal with conversions to reference types */ if (nt == type_ref_tag) { conv = ref_convert_seq (p, e, bind, 0); return (conv); } /* Standard conversion sequences */ conv = std_convert_seq (p, e, bind, ref); return (conv); } /* * COMPARE TWO BASE CLASS CONVERSIONS * * This routine compares the base classes given by p and q. It returns 1 * if p is a proper subgraph of q, 2 if q is a proper subgraph of p and * 0 otherwise. */ static int base_compare_seq(GRAPH p, GRAPH q) { CLASS_TYPE ct; CLASS_TYPE pa, pb; CLASS_TYPE qa, qb; /* Decompose p into pa > pb */ pb = DEREF_ctype (graph_head (p)); p = DEREF_graph (graph_top (p)); pa = DEREF_ctype (graph_head (p)); /* Decompose q into qa > qb */ qb = DEREF_ctype (graph_head (q)); q = DEREF_graph (graph_top (q)); qa = DEREF_ctype (graph_head (q)); if (eq_ctype (pa, qa)) { /* Graph tops are equal, pa = qa */ if (eq_ctype (pb, qb)) { /* Graphs are equal */ return (0); } ct = compare_base_class (pb, qb, 0); if (EQ_ctype (ct, pb)) { /* pa = qa > qb > pb */ return (2); } if (EQ_ctype (ct, qb)) { /* pa = qa > pb > qb */ return (1); } } else if (eq_ctype (pb, qb)) { /* Graph bottoms are equal, pb = qb */ ct = compare_base_class (pa, qa, 0); if (EQ_ctype (ct, pa)) { /* qa > pa > pb = qb */ return (1); } if (EQ_ctype (ct, qa)) { /* pa > qa > pb = qb */ return (2); } } return (0); } /* * COMPARE TWO QUALIFICATION CONVERSIONS * * This routine compares the qualification conversions given by p and q. * It returns 3 if they are identical, 1 if p is better (in that every * qualifier added by p is also added by q), 2 if q is better, and 0 * otherwise. When qualifiers are added at only one level it is just * a matter of comparing the added qualifiers. If qualifiers are added * at more than one level a trial conversion is carried out. */ static int qual_compare_seq(CONVERSION *p, CONVERSION *q) { CV_SPEC cp = p->qual; CV_SPEC cq = q->qual; if (cp == cv_multi || cq == cv_multi) { /* Qualifiers at more than one level */ TYPE t; unsigned cmp; CONVERSION r; if (EQ_type (p->from, q->from)) { /* Compare to-types */ r.from = p->to; r.to = q->to; } else if (EQ_type (p->to, q->to)) { /* Compare from-types */ r.from = q->from; r.to = p->from; } else { /* This shouldn't happen */ return (0); } cmp = std_convert_seq (&r, NULL_exp, 0, 0); if (cmp == CONV_EXACT) return (3); if (cmp != CONV_NONE) return (1); t = r.from; r.from = r.to; r.to = t; cmp = std_convert_seq (&r, NULL_exp, 0, 0); if (cmp != CONV_NONE) return (2); } else { /* Qualifiers at only one level */ CV_SPEC cr; if (cp == cq) return (3); cr = (cp | cq); if (cr == cq) return (1); if (cr == cp) return (2); } return (0); } /* * COMPARE TWO CONVERSION SEQUENCES * * This routine compares the implicit conversion sequences given by * p1 and p2. In all cases either the from types of the two conversions * or the to types will be equal. The routine is used in determining * the best viable function in overload resolution, it returns 1 if the * first conversion is better, 2 if second is better, and some other * value otherwise. */ int compare_seq(CONVERSION *p1, CONVERSION *p2) { /* Compare the ranks of the conversions */ int cmp = 0; unsigned a1 = p1->rank; unsigned a2 = p2->rank; unsigned b1 = CONV_RANK (a1); unsigned b2 = CONV_RANK (a2); if (b1 > b2) return (1); if (b1 < b2) return (2); /* Check user-defined conversions */ if (a1 == CONV_USER && a2 == CONV_USER) { if (!EQ_id (p1->usr, p2->usr)) return (0); a1 = p1->std; a2 = p2->std; b1 = CONV_RANK (a1); b2 = CONV_RANK (a2); if (b1 > b2) return (1); if (b1 < b2) return (2); } /* Compare standard conversions */ switch (a1) { case CONV_PTR_BASE : { /* Pointer conversions */ if (a2 == a1) { /* Compare base pointer conversions */ GRAPH g1 = p1->base; GRAPH g2 = p2->base; if (eq_graph (g1, g2)) { cmp = qual_compare_seq (p1, p2); } else { cmp = base_compare_seq (g1, g2); } } else if (a2 == CONV_PTR_VOID || a2 == CONV_PTR_BOTTOM) { /* Base pointer conversion is better than 'void *' */ cmp = 1; } else if (a2 == CONV_BOOL) { /* Base pointer conversion is better than 'bool' */ cmp = 1; } break; } case CONV_PTR_VOID : case CONV_PTR_BOTTOM : { /* Pointer to 'void *' conversions */ if (a2 == CONV_PTR_VOID || a2 == CONV_PTR_BOTTOM) { /* Compare pointer conversions */ cmp = qual_compare_seq (p1, p2); } else if (a2 == CONV_PTR_BASE) { /* Base pointer conversion is better than 'void *' */ cmp = 2; } else if (a2 == CONV_BOOL) { /* Pointer conversion is better than 'bool' */ cmp = 1; } break; } case CONV_PTR_MEM_BASE : { /* Pointer member conversions */ if (a2 == a1) { /* Compare base pointer member conversions */ GRAPH g1 = p1->base; GRAPH g2 = p2->base; if (eq_graph (g1, g2)) { cmp = qual_compare_seq (p1, p2); } else { int bmp = base_compare_seq (g1, g2); if (bmp) { cmp = qual_compare_seq (p1, p2); switch (cmp) { case 1 : { if (bmp != 2) cmp = 0; break; } case 2 : { if (bmp != 1) cmp = 0; break; } case 3 : { cmp = bmp; break; } } } } } else if (a2 == CONV_BOOL) { /* Pointer conversion is better than 'bool' */ cmp = 1; } break; } case CONV_BASE : { /* Base class conversions */ if (a2 == a1) { /* Compare base class conversions */ GRAPH g1 = p1->base; GRAPH g2 = p2->base; if (eq_graph (g1, g2)) { cmp = qual_compare_seq (p1, p2); } else { cmp = base_compare_seq (g1, g2); } } break; } case CONV_BOOL : { /* Boolean conversions */ if (a2 == CONV_PTR_BASE || a2 == CONV_PTR_MEM_BASE || a2 == CONV_PTR_VOID || a2 == CONV_PTR_BOTTOM) { /* Pointer conversion is better than 'bool' */ cmp = 2; } break; } case CONV_STRING : { /* String literal conversions */ if (a2 == a1) { cmp = qual_compare_seq (p1, p2); } else if (a2 == CONV_QUAL) { /* Qualification conversion is better than string */ cmp = 2; } break; } case CONV_QUAL : { /* Qualification conversions */ if (a2 == a1) { cmp = qual_compare_seq (p1, p2); } else if (a2 == CONV_STRING) { /* Qualification conversion is better than string */ cmp = 1; } break; } } return (cmp); }