bool valid_compare(type t1, type t2, expression e1) { if (type_void(type_points_to(t1))) { if (pedantic && type_function(type_points_to(t2)) && !definite_null(e1)) pedwarn("ANSI C forbids comparison of `void *' with function pointer"); return TRUE; } return FALSE; }
static void check_dereference(expression result, type dereferenced, const char *errorstring) { if (type_pointer(dereferenced)) { type t = type_points_to(dereferenced); result->type = t; #if 0 if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE) { error ("dereferencing pointer to incomplete type"); return error_mark_node; } #endif if (type_void(t) && unevaluated_expression == 0) warning("dereferencing `void *' pointer"); result->side_effects |= type_volatile(t) || flag_volatile; } else { result->type = error_type; if (dereferenced != error_type) error("invalid type argument of `%s'", errorstring); } result->lvalue = TRUE; }
expression build_function_call(region r, location loc, expression fn, expression arglist) { expression result = CAST(expression, new_function_call(r, loc, fn, arglist, NULL, normal_call)); type fntype = type_default_conversion(fn->type), rettype; if (type_pointer(fntype)) /* All function types come this way because default_conversion makes them into pointers to functions... */ fntype = type_points_to(fntype); rettype = type_function_return_type(fntype); result->type = rettype; result->cst = fold_function_call(result, 0); return result; }
type pointer_int_sum(type ptype, type itype) { type pointed = type_points_to(ptype); if (type_void(pointed)) { if (pedantic || warn_pointer_arith) pedwarn("pointer of type `void *' used in arithmetic"); } else if (type_function(pointed)) { if (pedantic || warn_pointer_arith) pedwarn("pointer to a function used in arithmetic"); } else if (type_incomplete(pointed)) error("arithmetic on pointer to an incomplete type"); return ptype; }
type check_binary(int binop, expression e1, expression e2) { type t1 = default_conversion(e1), t2 = default_conversion(e2); type rtype = NULL; bool common = FALSE; /* XXX: Misc warnings (see build_binary_op) */ if (t1 == error_type || t2 == error_type) rtype = error_type; else switch(binop) { case kind_plus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t2) && type_integer(t1)) rtype = pointer_int_sum(t2, t1); else common = TRUE; break; case kind_minus: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else if (type_pointer(t1) && type_pointer(t2) && compatible_pointer_types(t1, t2)) rtype = ptrdiff_t_type; else common = TRUE; break; case kind_plus_assign: case kind_minus_assign: if (type_pointer(t1) && type_integer(t2)) rtype = pointer_int_sum(t1, t2); else common = TRUE; break; case kind_times: case kind_divide: case kind_times_assign: case kind_divide_assign: common = TRUE; break; case kind_modulo: case kind_bitand: case kind_bitor: case kind_bitxor: case kind_lshift: case kind_rshift: case kind_modulo_assign: case kind_bitand_assign: case kind_bitor_assign: case kind_bitxor_assign: case kind_lshift_assign: case kind_rshift_assign: if (type_integer(t1) && type_integer(t2)) rtype = common_type(t1, t2); break; case kind_leq: case kind_geq: case kind_lt: case kind_gt: rtype = int_type; /* Default to assuming success */ if (type_real(t1) && type_real(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (compatible_pointer_types(t1, t2)) { /* XXX: how can this happen ? */ if (type_incomplete(t1) != type_incomplete(t2)) pedwarn("comparison of complete and incomplete pointers"); else if (pedantic && type_function(type_points_to(t1))) pedwarn("ANSI C forbids ordered comparisons of pointers to functions"); } else pedwarn("comparison of distinct pointer types lacks a cast"); } /* XXX: Use of definite_zero may lead to extra warnings when !extra_warnings */ else if ((type_pointer(t1) && definite_zero(e2)) || (type_pointer(t2) && definite_zero(e1))) { if (pedantic || extra_warnings) pedwarn("ordered comparison of pointer with integer zero"); } else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_eq: case kind_ne: rtype = int_type; /* Default to assuming success */ if (type_arithmetic(t1) && type_arithmetic(t2)) ; else if (type_pointer(t1) && type_pointer(t2)) { if (!compatible_pointer_types(t1, t2) && !valid_compare(t1, t2, e1) && !valid_compare(t2, t1, e2)) pedwarn("comparison of distinct pointer types lacks a cast"); } else if ((type_pointer(t1) && definite_null(e2)) || (type_pointer(t2) && definite_null(e1))) ; else if ((type_pointer(t1) && type_integer(t2)) || (type_pointer(t2) && type_integer(t1))) { if (!flag_traditional) pedwarn("comparison between pointer and integer"); } else rtype = NULL; /* Force error */ break; case kind_andand: case kind_oror: if (type_scalar(t1) && type_scalar(t2)) rtype = int_type; break; default: assert(0); break; } if (common && type_arithmetic(t1) && type_arithmetic(t2)) rtype = common_type(t1, t2); if (!rtype) { error("invalid operands to binary %s", binary_op_name(binop)); rtype = error_type; } return rtype; }
expression make_cast(location loc, asttype t, expression e) { expression result = CAST(expression, new_cast(parse_region, loc, e, t)); type castto = t->type; if (castto == error_type || type_void(castto)) ; /* Do nothing */ else if (type_array(castto)) { error("cast specifies array type"); castto = error_type; } else if (type_function(castto)) { error("cast specifies function type"); castto = error_type; } else if (type_equal_unqualified(castto, e->type)) { if (pedantic && type_aggregate(castto)) pedwarn("ANSI C forbids casting nonscalar to the same type"); } else { type etype = e->type; /* Convert functions and arrays to pointers, but don't convert any other types. */ if (type_function(etype) || type_array(etype)) etype = default_conversion(e); if (type_union(castto)) { tag_declaration utag = type_tag(castto); field_declaration ufield; /* Look for etype as a field of the union */ for (ufield = utag->fieldlist; ufield; ufield = ufield->next) if (ufield->name && type_equal_unqualified(ufield->type, etype)) { if (pedantic) pedwarn("ANSI C forbids casts to union type"); break; } if (!ufield) error("cast to union type from type not present in union"); } else { /* Optionally warn about potentially worrisome casts. */ if (warn_cast_qual && type_pointer(etype) && type_pointer(castto)) { type ep = type_points_to(etype), cp = type_points_to(castto); if (type_volatile(ep) && !type_volatile(cp)) pedwarn("cast discards `volatile' from pointer target type"); if (type_const(ep) && !type_const(cp)) pedwarn("cast discards `const' from pointer target type"); } /* This warning is weird */ if (warn_bad_function_cast && is_function_call(e) && !type_equal_unqualified(castto, etype)) warning ("cast does not match function type"); #if 0 /* Warn about possible alignment problems. */ if (STRICT_ALIGNMENT && warn_cast_align && TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE /* Don't warn about opaque types, where the actual alignment restriction is unknown. */ && !((TREE_CODE (TREE_TYPE (otype)) == UNION_TYPE || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE) && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode) && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype))) warning ("cast increases required alignment of target type"); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (otype) == POINTER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) && !TREE_CONSTANT (value)) warning ("cast from pointer to integer of different size"); if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (otype) == INTEGER_TYPE && TYPE_PRECISION (type) != TYPE_PRECISION (otype) #if 0 /* Don't warn about converting 0 to pointer, provided the 0 was explicit--not cast or made by folding. */ && !(TREE_CODE (value) == INTEGER_CST && integer_zerop (value)) #endif /* Don't warn about converting any constant. */ && !TREE_CONSTANT (value)) warning ("cast to pointer from integer of different size"); #endif check_conversion(castto, etype); } } result->lvalue = !pedantic && e->lvalue; result->isregister = e->isregister; result->bitfield = e->bitfield; result->static_address = e->static_address; result->type = castto; result->cst = fold_cast(result); return result; }
static bool compatible_pointer_types(type tl, type tr) { return compatible_pointer_targets(type_points_to(tl), type_points_to(tr), pedantic); }
/* Return TRUE if no error and lhstype and rhstype are not error_type */ bool check_assignment(type lhstype, type rhstype, expression rhs, const char *context, data_declaration fundecl, const char *funname, int parmnum) { bool zerorhs = rhs && definite_zero(rhs); if (lhstype == error_type || rhstype == error_type) return FALSE; if (type_void(rhstype)) { error("void value not ignored as it ought to be"); return FALSE; } if (type_equal_unqualified(lhstype, rhstype)) return TRUE; if (type_arithmetic(lhstype) && type_arithmetic(rhstype)) { if (rhs) constant_overflow_warning(rhs->cst); return check_conversion(lhstype, rhstype); } if (parmnum && (type_qualifiers(lhstype) & transparent_qualifier)) { /* See if we can match any field of lhstype */ tag_declaration tag = type_tag(lhstype); field_declaration fields, marginal_field = NULL; /* I blame gcc for this horrible mess (and it's minor inconsistencies with the regular rules) */ /* pedantic warnings are skipped in here because we're already issuing a warning for the use of this construct */ for (fields = tag->fieldlist; fields; fields = fields->next) { type ft = fields->type; if (type_compatible(ft, rhstype)) break; if (!type_pointer(ft)) continue; if (type_pointer(rhstype)) { type ttl = type_points_to(ft), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, FALSE); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch) { /* If this type won't generate any warnings, use it. */ if ((type_function(ttr) && type_function(ttl)) ? (((!type_const(ttl)) | type_const(ttr)) & ((!type_volatile(ttl)) | type_volatile(ttr))) : (((type_const(ttl)) | (!type_const(ttr))) & (type_volatile(ttl) | (!type_volatile(ttr))))) break; /* Keep looking for a better type, but remember this one. */ if (!marginal_field) marginal_field = fields; } } /* Can convert integer zero to any pointer type. */ /* Note that this allows passing *any* null pointer (gcc bug?) */ if (zerorhs) break; } if (fields || marginal_field) { if (!fields) { /* We have only a marginally acceptable member type; it needs a warning. */ type ttl = type_points_to(marginal_field->type), ttr = type_points_to(rhstype); ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, FALSE); } if (pedantic && !(fundecl && fundecl->in_system_header)) pedwarn("ANSI C prohibits argument conversion to union type"); return TRUE; } } if (type_pointer(lhstype) && type_pointer(rhstype)) { type ttl = type_points_to(lhstype), ttr = type_points_to(rhstype); bool goodmatch = assignable_pointer_targets(ttl, ttr, pedantic); /* Any non-function converts to a [const][volatile] void * and vice versa; otherwise, targets must be the same. Meanwhile, the lhs target must have all the qualifiers of the rhs. */ if (goodmatch || (type_equal_unqualified(make_unsigned_type(ttl), make_unsigned_type(ttr)))) ptrconversion_warnings(ttl, ttr, rhs, context, funname, parmnum, pedantic); else warn_for_assignment("%s from incompatible pointer type", context, funname, parmnum); return check_conversion(lhstype, rhstype); } /* enum = ptr and ptr = enum counts as an error, so use type_integral */ else if (type_pointer(lhstype) && type_integral(rhstype)) { if (!zerorhs) warn_for_assignment("%s makes pointer from integer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } else if (type_integral(lhstype) && type_pointer(rhstype)) { warn_for_assignment("%s makes integer from pointer without a cast", context, funname, parmnum); return check_conversion(lhstype, rhstype); } if (!context) if (funname) error("incompatible type for argument %d of `%s'", parmnum, funname); else error("incompatible type for argument %d of indirect function call", parmnum); else error("incompatible types in %s", context); return FALSE; }