tree get_typeid (tree type) { if (type == error_mark_node || !typeid_ok_p ()) return error_mark_node; if (processing_template_decl) return build_min (TYPEID_EXPR, const_type_info_type_node, type); /* If the type of the type-id is a reference type, the result of the typeid expression refers to a type_info object representing the referenced type. */ type = non_reference (type); /* The top-level cv-qualifiers of the lvalue expression or the type-id that is the operand of typeid are always ignored. */ type = TYPE_MAIN_VARIANT (type); if (!VOID_TYPE_P (type)) type = complete_type_or_else (type, NULL_TREE); if (!type) return error_mark_node; return build_indirect_ref (get_tinfo_ptr (type), NULL); }
static int complete_ptr_ref_or_void_ptr_p (tree type, tree from) { int is_ptr; /* Check complete. */ type = complete_type_or_else (type, from); if (!type) return 0; /* Or a pointer or ref to one, or cv void *. */ is_ptr = TYPE_PTR_P (type); if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE) { tree core = TREE_TYPE (type); if (is_ptr && VOID_TYPE_P (core)) /* OK */; else if (!complete_type_or_else (core, from)) return 0; } return 1; }
static tree get_tinfo_decl_dynamic (tree exp) { tree type; tree t; if (exp == error_mark_node) return error_mark_node; /* peel back references, so they match. */ type = non_reference (TREE_TYPE (exp)); /* Peel off cv qualifiers. */ type = TYPE_MAIN_VARIANT (type); if (!VOID_TYPE_P (type)) type = complete_type_or_else (type, exp); if (!type) return error_mark_node; /* If exp is a reference to polymorphic type, get the real type_info. */ if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0)) { /* build reference to type_info from vtable. */ tree index; /* The RTTI information is at index -1. */ index = build_int_cst (NULL_TREE, -1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); t = build_vtbl_ref (exp, index); t = convert (type_info_ptr_type, t); } else /* Otherwise return the type_info for the static type of the expr. */ t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type)); return build_indirect_ref (t, NULL); }
tree build_expr_type_conversion (int desires, tree expr, bool complain) { tree basetype = TREE_TYPE (expr); tree conv = NULL_TREE; tree winner = NULL_TREE; if (expr == null_node && (desires & WANT_INT) && !(desires & WANT_NULL)) warning (OPT_Wconversion, "converting NULL to non-pointer type"); basetype = TREE_TYPE (expr); if (basetype == error_mark_node) return error_mark_node; if (! MAYBE_CLASS_TYPE_P (basetype)) switch (TREE_CODE (basetype)) { case INTEGER_TYPE: if ((desires & WANT_NULL) && null_ptr_cst_p (expr)) return expr; /* else fall through... */ case BOOLEAN_TYPE: return (desires & WANT_INT) ? expr : NULL_TREE; case ENUMERAL_TYPE: return (desires & WANT_ENUM) ? expr : NULL_TREE; case REAL_TYPE: return (desires & WANT_FLOAT) ? expr : NULL_TREE; case POINTER_TYPE: return (desires & WANT_POINTER) ? expr : NULL_TREE; case FUNCTION_TYPE: case ARRAY_TYPE: return (desires & WANT_POINTER) ? decay_conversion (expr) : NULL_TREE; case VECTOR_TYPE: if ((desires & WANT_VECTOR) == 0) return NULL_TREE; switch (TREE_CODE (TREE_TYPE (basetype))) { case INTEGER_TYPE: case BOOLEAN_TYPE: return (desires & WANT_INT) ? expr : NULL_TREE; case ENUMERAL_TYPE: return (desires & WANT_ENUM) ? expr : NULL_TREE; case REAL_TYPE: return (desires & WANT_FLOAT) ? expr : NULL_TREE; default: return NULL_TREE; } default: return NULL_TREE; } /* The code for conversions from class type is currently only used for delete expressions. Other expressions are handled by build_new_op. */ if (!complete_type_or_else (basetype, expr)) return error_mark_node; if (!TYPE_HAS_CONVERSION (basetype)) return NULL_TREE; for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) { int win = 0; tree candidate; tree cand = TREE_VALUE (conv); if (winner && winner == cand) continue; candidate = non_reference (TREE_TYPE (TREE_TYPE (cand))); switch (TREE_CODE (candidate)) { case BOOLEAN_TYPE: case INTEGER_TYPE: win = (desires & WANT_INT); break; case ENUMERAL_TYPE: win = (desires & WANT_ENUM); break; case REAL_TYPE: win = (desires & WANT_FLOAT); break; case POINTER_TYPE: win = (desires & WANT_POINTER); break; case VECTOR_TYPE: if ((desires & WANT_VECTOR) == 0) break; switch (TREE_CODE (TREE_TYPE (candidate))) { case BOOLEAN_TYPE: case INTEGER_TYPE: win = (desires & WANT_INT); break; case ENUMERAL_TYPE: win = (desires & WANT_ENUM); break; case REAL_TYPE: win = (desires & WANT_FLOAT); break; default: break; } break; default: break; } if (win) { if (winner) { if (complain) { error ("ambiguous default type conversion from %qT", basetype); error (" candidate conversions include %qD and %qD", winner, cand); } return error_mark_node; } else winner = cand; } } if (winner) { tree type = non_reference (TREE_TYPE (TREE_TYPE (winner))); return build_user_type_conversion (type, expr, LOOKUP_NORMAL); } return NULL_TREE; }