tree maybe_resolve_dummy (tree object, bool add_capture_p) { if (!is_dummy_object (object)) return object; tree type = TYPE_MAIN_VARIANT (TREE_TYPE (object)); gcc_assert (!TYPE_PTR_P (type)); if (type != current_class_type && current_class_type && LAMBDA_TYPE_P (current_class_type) && lambda_function (current_class_type) && DERIVED_FROM_P (type, current_nonlambda_class_type ())) { /* In a lambda, need to go through 'this' capture. */ tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); tree cap = lambda_expr_this_capture (lam, add_capture_p); if (cap && cap != error_mark_node) object = build_x_indirect_ref (EXPR_LOCATION (object), cap, RO_NULL, tf_warning_or_error); } return object; }
tree cp_ubsan_maybe_instrument_downcast (location_t loc, tree type, tree op) { if (!POINTER_TYPE_P (type) || !POINTER_TYPE_P (TREE_TYPE (op)) || !CLASS_TYPE_P (TREE_TYPE (type)) || !CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (op))) || !DERIVED_FROM_P (TREE_TYPE (TREE_TYPE (op)), TREE_TYPE (type))) return NULL_TREE; return cp_ubsan_maybe_instrument_vptr (loc, op, TREE_TYPE (type), true, TREE_CODE (type) == POINTER_TYPE ? UBSAN_DOWNCAST_POINTER : UBSAN_DOWNCAST_REFERENCE); }
static bool decl_is_java_type (tree decl, int err) { bool r = (TYPE_PTR_P (decl) && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TYPE_FOR_JAVA (TREE_TYPE (decl))); if (err) { if (TREE_CODE (decl) == REFERENCE_TYPE && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TYPE_FOR_JAVA (TREE_TYPE (decl))) { /* Can't throw a reference. */ error ("type %qT is disallowed in Java %<throw%> or %<catch%>", decl); } if (r) { tree jthrow_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable")); if (jthrow_node == NULL_TREE) fatal_error (input_location, "call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined"); jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node)); if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl))) { /* Thrown object must be a Throwable. */ error ("type %qT is not derived from %<java::lang::Throwable%>", TREE_TYPE (decl)); } } } return r; }
static bool decl_is_java_type (tree decl, int err) { bool r = (TREE_CODE (decl) == POINTER_TYPE && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TYPE_FOR_JAVA (TREE_TYPE (decl))); if (err) { if (TREE_CODE (decl) == REFERENCE_TYPE && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TYPE_FOR_JAVA (TREE_TYPE (decl))) { /* Can't throw a reference. */ error ("type `%T' is disallowed in Java `throw' or `catch'", decl); } if (r) { tree jthrow_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable")); if (jthrow_node == NULL_TREE) fatal_error ("call to Java `catch' or `throw' with `jthrowable' undefined"); jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node)); if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl))) { /* Thrown object must be a Throwable. */ error ("type `%T' is not derived from `java::lang::Throwable'", TREE_TYPE (decl)); } } } return r; }
tree ocp_convert (tree type, tree expr, int convtype, int flags) { tree e = expr; enum tree_code code = TREE_CODE (type); const char *invalid_conv_diag; if (error_operand_p (e) || type == error_mark_node) return error_mark_node; complete_type (type); complete_type (TREE_TYPE (expr)); if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { error (invalid_conv_diag); return error_mark_node; } e = integral_constant_value (e); if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP)) /* We need a new temporary; don't take this shortcut. */; else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e))) { if (same_type_p (type, TREE_TYPE (e))) /* The call to fold will not always remove the NOP_EXPR as might be expected, since if one of the types is a typedef; the comparison in fold is just equality of pointers, not a call to comptypes. We don't call fold in this case because that can result in infinite recursion; fold will call convert, which will call ocp_convert, etc. */ return e; /* For complex data types, we need to perform componentwise conversion. */ else if (TREE_CODE (type) == COMPLEX_TYPE) return fold_if_not_in_template (convert_to_complex (type, e)); else if (TREE_CODE (e) == TARGET_EXPR) { /* Don't build a NOP_EXPR of class type. Instead, change the type of the temporary. */ TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type; return e; } else { /* We shouldn't be treating objects of ADDRESSABLE type as rvalues. */ gcc_assert (!TREE_ADDRESSABLE (type)); return fold_if_not_in_template (build_nop (type, e)); } } if (code == VOID_TYPE && (convtype & CONV_STATIC)) { e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error); return e; } if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); if (TREE_CODE (type) == ENUMERAL_TYPE) { /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || TREE_CODE (intype) == REAL_TYPE) && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { if (flags & LOOKUP_COMPLAIN) permerror (input_location, "conversion from %q#T to %q#T", intype, type); if (!flag_permissive) return error_mark_node; } /* [expr.static.cast] 8. A value of integral or enumeration type can be explicitly converted to an enumeration type. The value is unchanged if the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ if (TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, type)) warning (OPT_Wconversion, "the result of the conversion is unspecified because " "%qE is outside the range of type %qT", expr, type); } if (MAYBE_CLASS_TYPE_P (intype)) { tree rval; rval = build_type_conversion (type, e); if (rval) return rval; if (flags & LOOKUP_COMPLAIN) error ("%q#T used where a %qT was expected", intype, type); return error_mark_node; } if (code == BOOLEAN_TYPE) return cp_truthvalue_conversion (e); return fold_if_not_in_template (convert_to_integer (type, e)); } if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) return fold_if_not_in_template (cp_convert_to_pointer (type, e)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); if (MAYBE_CLASS_TYPE_P (in_vtype)) { tree ret_val; ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; if (flags & LOOKUP_COMPLAIN) error ("%q#T used where a %qT was expected", in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); } if (code == REAL_TYPE || code == COMPLEX_TYPE) { if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e))) { tree rval; rval = build_type_conversion (type, e); if (rval) return rval; else if (flags & LOOKUP_COMPLAIN) error ("%q#T used where a floating point value was expected", TREE_TYPE (e)); } if (code == REAL_TYPE) return fold_if_not_in_template (convert_to_real (type, e)); else if (code == COMPLEX_TYPE) return fold_if_not_in_template (convert_to_complex (type, e)); } /* New C++ semantics: since assignment is now based on memberwise copying, if the rhs type is derived from the lhs type, then we may still do a conversion. */ if (RECORD_OR_UNION_CODE_P (code)) { tree dtype = TREE_TYPE (e); tree ctor = NULL_TREE; dtype = TYPE_MAIN_VARIANT (dtype); /* Conversion between aggregate types. New C++ semantics allow objects of derived type to be cast to objects of base type. Old semantics only allowed this between pointers. There may be some ambiguity between using a constructor vs. using a type conversion operator when both apply. */ ctor = e; if (abstract_virtuals_error (NULL_TREE, type)) return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ ctor = build_user_type_conversion (type, ctor, flags); else ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, ctor), type, flags, tf_warning_or_error); if (ctor) return build_cplus_new (type, ctor); } if (flags & LOOKUP_COMPLAIN) error ("conversion from %qT to non-scalar type %qT requested", TREE_TYPE (expr), type); return error_mark_node; }
tree ocp_convert (tree type, tree expr, int convtype, int flags) { tree e = expr; enum tree_code code = TREE_CODE (type); if (error_operand_p (e) || type == error_mark_node) return error_mark_node; complete_type (type); complete_type (TREE_TYPE (expr)); e = decl_constant_value (e); if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP) /* Some internal structures (vtable_entry_type, sigtbl_ptr_type) don't go through finish_struct, so they don't have the synthesized constructors. So don't force a temporary. */ && TYPE_HAS_CONSTRUCTOR (type)) /* We need a new temporary; don't take this shortcut. */; else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) { if (same_type_p (type, TREE_TYPE (e))) /* The call to fold will not always remove the NOP_EXPR as might be expected, since if one of the types is a typedef; the comparison in fold is just equality of pointers, not a call to comptypes. We don't call fold in this case because that can result in infinite recursion; fold will call convert, which will call ocp_convert, etc. */ return e; /* For complex data types, we need to perform componentwise conversion. */ else if (TREE_CODE (type) == COMPLEX_TYPE) return fold (convert_to_complex (type, e)); else if (TREE_CODE (e) == TARGET_EXPR) { /* Don't build a NOP_EXPR of class type. Instead, change the type of the temporary. Only allow this for cv-qual changes, though. */ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)), TYPE_MAIN_VARIANT (type))) abort (); TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type; return e; } else if (TREE_ADDRESSABLE (type)) /* We shouldn't be treating objects of ADDRESSABLE type as rvalues. */ abort (); else return fold (build1 (NOP_EXPR, type, e)); } if (code == VOID_TYPE && (convtype & CONV_STATIC)) { e = convert_to_void (e, /*implicit=*/NULL); return e; } if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (TREE_CODE (type) == ENUMERAL_TYPE && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC)) || (TREE_CODE (intype) == POINTER_TYPE))) { pedwarn ("conversion from `%#T' to `%#T'", intype, type); if (flag_pedantic_errors) return error_mark_node; } if (IS_AGGR_TYPE (intype)) { tree rval; rval = build_type_conversion (type, e); if (rval) return rval; if (flags & LOOKUP_COMPLAIN) error ("`%#T' used where a `%T' was expected", intype, type); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node; } if (code == BOOLEAN_TYPE) return cp_truthvalue_conversion (e); return fold (convert_to_integer (type, e)); } if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type)) return fold (cp_convert_to_pointer (type, e, false)); if (code == VECTOR_TYPE) return fold (convert_to_vector (type, e)); if (code == REAL_TYPE || code == COMPLEX_TYPE) { if (IS_AGGR_TYPE (TREE_TYPE (e))) { tree rval; rval = build_type_conversion (type, e); if (rval) return rval; else if (flags & LOOKUP_COMPLAIN) error ("`%#T' used where a floating point value was expected", TREE_TYPE (e)); } if (code == REAL_TYPE) return fold (convert_to_real (type, e)); else if (code == COMPLEX_TYPE) return fold (convert_to_complex (type, e)); } /* New C++ semantics: since assignment is now based on memberwise copying, if the rhs type is derived from the lhs type, then we may still do a conversion. */ if (IS_AGGR_TYPE_CODE (code)) { tree dtype = TREE_TYPE (e); tree ctor = NULL_TREE; dtype = TYPE_MAIN_VARIANT (dtype); /* Conversion between aggregate types. New C++ semantics allow objects of derived type to be cast to objects of base type. Old semantics only allowed this between pointers. There may be some ambiguity between using a constructor vs. using a type conversion operator when both apply. */ ctor = e; if (abstract_virtuals_error (NULL_TREE, type)) return error_mark_node; if ((flags & LOOKUP_ONLYCONVERTING) && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ ctor = build_user_type_conversion (type, ctor, flags); else ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, ctor), TYPE_BINFO (type), flags); if (ctor) return build_cplus_new (type, ctor); } if (flags & LOOKUP_COMPLAIN) error ("conversion from `%T' to non-scalar type `%T' requested", TREE_TYPE (expr), type); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node; }