static tree build_up_reference (tree type, tree arg, int flags, tree decl) { tree rval; tree argtype = TREE_TYPE (arg); tree target_type = TREE_TYPE (type); gcc_assert (TREE_CODE (type) == REFERENCE_TYPE); if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) { /* Create a new temporary variable. We can't just use a TARGET_EXPR here because it needs to live as long as DECL. */ tree targ = arg; arg = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (arg)); /* Process the initializer for the declaration. */ DECL_INITIAL (arg) = targ; cp_finish_decl (arg, targ, /*init_const_expr_p=*/false, NULL_TREE, LOOKUP_ONLYCONVERTING|DIRECT_BIND); } else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg)) return get_target_expr (arg); /* If we had a way to wrap this up, and say, if we ever needed its address, transform all occurrences of the register, into a memory reference we could win better. */ rval = cp_build_unary_op (ADDR_EXPR, arg, 1, tf_warning_or_error); if (rval == error_mark_node) return error_mark_node; if ((flags & LOOKUP_PROTECT) && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type) && MAYBE_CLASS_TYPE_P (argtype) && MAYBE_CLASS_TYPE_P (target_type)) { /* We go through lookup_base for the access control. */ tree binfo = lookup_base (argtype, target_type, ba_check, NULL); if (binfo == error_mark_node) return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); rval = build_base_path (PLUS_EXPR, rval, binfo, 1); } else rval = convert_to_pointer_force (build_pointer_type (target_type), rval); return build_nop (type, rval); }
static void push_eh_info () { tree decl, fn = call_eh_info (); /* Remember the pointer to the current exception info; it won't change during this catch block. */ decl = build_decl (VAR_DECL, get_identifier ("__exception_info"), TREE_TYPE (fn)); DECL_ARTIFICIAL (decl) = 1; DECL_INITIAL (decl) = fn; decl = pushdecl (decl); cp_finish_decl (decl, fn, NULL_TREE, 0); }
static void initialize_handler_parm (tree decl, tree exp) { tree init; tree init_type; /* Make sure we mark the catch param as used, otherwise we'll get a warning about an unused ((anonymous)). */ TREE_USED (decl) = 1; DECL_READ_P (decl) = 1; /* Figure out the type that the initializer is. Pointers are returned adjusted by value from __cxa_begin_catch. Others are returned by reference. */ init_type = TREE_TYPE (decl); if (!INDIRECT_TYPE_P (init_type)) init_type = build_reference_type (init_type); /* Since pointers are passed by value, initialize a reference to pointer catch parm with the address of the temporary. */ if (TYPE_REF_P (init_type) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, tf_warning_or_error); init = convert_from_reference (exp); /* If the constructor for the catch parm exits via an exception, we must call terminate. See eh23.C. */ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); init = build_must_not_throw_expr (init, NULL_TREE); } decl = pushdecl (decl); start_decl_1 (decl, true); cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE, LOOKUP_ONLYCONVERTING|DIRECT_BIND); }
static void initialize_handler_parm (tree decl, tree exp) { tree init; tree init_type; /* Make sure we mark the catch param as used, otherwise we'll get a warning about an unused ((anonymous)). */ TREE_USED (decl) = 1; /* Figure out the type that the initializer is. Pointers are returned adjusted by value from __cxa_begin_catch. Others are returned by reference. */ init_type = TREE_TYPE (decl); if (! TYPE_PTR_P (init_type) && TREE_CODE (init_type) != REFERENCE_TYPE) init_type = build_reference_type (init_type); choose_personality_routine (decl_is_java_type (init_type, 0) ? lang_java : lang_cplusplus); /* Since pointers are passed by value, initialize a reference to pointer catch parm with the address of the temporary. */ if (TREE_CODE (init_type) == REFERENCE_TYPE && TYPE_PTR_P (TREE_TYPE (init_type))) exp = build_unary_op (ADDR_EXPR, exp, 1); exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); init = convert_from_reference (exp); /* If the constructor for the catch parm exits via an exception, we must call terminate. See eh23.C. */ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init); } /* Let `cp_finish_decl' know that this initializer is ok. */ DECL_INITIAL (decl) = error_mark_node; decl = pushdecl (decl); start_decl_1 (decl); cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING|DIRECT_BIND); }
bool emit_tinfo_decl (tree decl) { tree type = TREE_TYPE (DECL_NAME (decl)); int in_library = typeinfo_in_lib_p (type); tree var_desc, var_init; gcc_assert (DECL_TINFO_P (decl)); if (in_library) { if (doing_runtime) DECL_EXTERNAL (decl) = 0; else { /* If we're not in the runtime, then DECL (which is already DECL_EXTERNAL) will not be defined here. */ DECL_INTERFACE_KNOWN (decl) = 1; return false; } } else if (involves_incomplete_p (type)) { if (!decl_needed_p (decl)) return false; /* If TYPE involves an incomplete class type, then the typeinfo object will be emitted with internal linkage. There is no way to know whether or not types are incomplete until the end of the compilation, so this determination must be deferred until this point. */ TREE_PUBLIC (decl) = 0; DECL_EXTERNAL (decl) = 0; DECL_INTERFACE_KNOWN (decl) = 1; } import_export_decl (decl); if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl)) { DECL_EXTERNAL (decl) = 0; var_desc = get_pseudo_ti_desc (type); var_init = get_pseudo_ti_init (type, var_desc); DECL_INITIAL (decl) = var_init; mark_used (decl); cp_finish_decl (decl, var_init, NULL_TREE, 0); return true; } else return false; }
tree expand_start_catch_block (tree decl) { tree exp; tree type; if (! doing_eh (1)) return NULL_TREE; /* Make sure this declaration is reasonable. */ if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE)) decl = NULL_TREE; if (decl) type = prepare_eh_type (TREE_TYPE (decl)); else type = NULL_TREE; if (decl && decl_is_java_type (type, 1)) { /* Java only passes object via pointer and doesn't require adjusting. The java object is immediately before the generic exception header. */ exp = build_exc_ptr (); exp = build1 (NOP_EXPR, build_pointer_type (type), exp); exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp, TYPE_SIZE_UNIT (TREE_TYPE (exp))); exp = build_indirect_ref (exp, NULL); initialize_handler_parm (decl, exp); return type; } /* Call __cxa_end_catch at the end of processing the exception. */ push_eh_cleanup (type); /* If there's no decl at all, then all we need to do is make sure to tell the runtime that we've begun handling the exception. */ if (decl == NULL) finish_expr_stmt (do_begin_catch ()); /* If the C++ object needs constructing, we need to do that before calling __cxa_begin_catch, so that std::uncaught_exception gets the right value during the copy constructor. */ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { exp = do_get_exception_ptr (); initialize_handler_parm (decl, exp); finish_expr_stmt (do_begin_catch ()); } /* Otherwise the type uses a bitwise copy, and we don't have to worry about the value of std::uncaught_exception and therefore can do the copy with the return value of __cxa_end_catch instead. */ else { tree init = do_begin_catch (); exp = create_temporary_var (ptr_type_node); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING); finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); initialize_handler_parm (decl, exp); } return type; }
tree expand_start_catch_block (tree decl) { tree exp; tree type, init; if (! doing_eh ()) return NULL_TREE; if (decl) { if (!is_admissible_throw_operand_or_catch_parameter (decl, false)) decl = error_mark_node; type = prepare_eh_type (TREE_TYPE (decl)); mark_used (eh_type_info (type)); } else type = NULL_TREE; /* Call __cxa_end_catch at the end of processing the exception. */ push_eh_cleanup (type); init = do_begin_catch (); /* If there's no decl at all, then all we need to do is make sure to tell the runtime that we've begun handling the exception. */ if (decl == NULL || decl == error_mark_node || init == error_mark_node) finish_expr_stmt (init); /* If the C++ object needs constructing, we need to do that before calling __cxa_begin_catch, so that std::uncaught_exception gets the right value during the copy constructor. */ else if (flag_use_cxa_get_exception_ptr && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { exp = do_get_exception_ptr (); initialize_handler_parm (decl, exp); finish_expr_stmt (init); } /* Otherwise the type uses a bitwise copy, and we don't have to worry about the value of std::uncaught_exception and therefore can do the copy with the return value of __cxa_end_catch instead. */ else { tree init_type = type; /* Pointers are passed by values, everything else by reference. */ if (!TYPE_PTR_P (type)) init_type = build_pointer_type (type); if (init_type != TREE_TYPE (init)) init = build1 (NOP_EXPR, init_type, init); exp = create_temporary_var (init_type); cp_finish_decl (exp, init, /*init_const_expr=*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); DECL_REGISTER (exp) = 1; initialize_handler_parm (decl, exp); } return type; }
tree expand_start_catch_block (tree decl) { tree exp; tree type, init; if (! doing_eh ()) return NULL_TREE; /* Make sure this declaration is reasonable. */ if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE)) decl = error_mark_node; if (decl) type = prepare_eh_type (TREE_TYPE (decl)); else type = NULL_TREE; if (decl && decl_is_java_type (type, 1)) { /* Java only passes object via pointer and doesn't require adjusting. The java object is immediately before the generic exception header. */ exp = build_exc_ptr (); exp = build1 (NOP_EXPR, build_pointer_type (type), exp); exp = fold_build_pointer_plus (exp, fold_build1_loc (input_location, NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (TREE_TYPE (exp)))); exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error); initialize_handler_parm (decl, exp); return type; } /* Call __cxa_end_catch at the end of processing the exception. */ push_eh_cleanup (type); init = do_begin_catch (); /* If there's no decl at all, then all we need to do is make sure to tell the runtime that we've begun handling the exception. */ if (decl == NULL || decl == error_mark_node || init == error_mark_node) finish_expr_stmt (init); /* If the C++ object needs constructing, we need to do that before calling __cxa_begin_catch, so that std::uncaught_exception gets the right value during the copy constructor. */ else if (flag_use_cxa_get_exception_ptr && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { exp = do_get_exception_ptr (); initialize_handler_parm (decl, exp); finish_expr_stmt (init); } /* Otherwise the type uses a bitwise copy, and we don't have to worry about the value of std::uncaught_exception and therefore can do the copy with the return value of __cxa_end_catch instead. */ else { tree init_type = type; /* Pointers are passed by values, everything else by reference. */ if (!TYPE_PTR_P (type)) init_type = build_pointer_type (type); if (init_type != TREE_TYPE (init)) init = build1 (NOP_EXPR, init_type, init); exp = create_temporary_var (init_type); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, /*init_const_expr=*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); initialize_handler_parm (decl, exp); } return type; }
tree expand_start_catch_block (tree decl) { tree exp = NULL_TREE; tree type; bool is_java; if (! doing_eh (1)) return NULL_TREE; /* Make sure this declaration is reasonable. */ if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE)) decl = NULL_TREE; if (decl) type = prepare_eh_type (TREE_TYPE (decl)); else type = NULL_TREE; is_java = false; if (decl) { tree init; if (decl_is_java_type (type, 1)) { /* Java only passes object via pointer and doesn't require adjusting. The java object is immediately before the generic exception header. */ init = build_exc_ptr (); init = build1 (NOP_EXPR, build_pointer_type (type), init); init = build (MINUS_EXPR, TREE_TYPE (init), init, TYPE_SIZE_UNIT (TREE_TYPE (init))); init = build_indirect_ref (init, NULL); is_java = true; } else { /* C++ requires that we call __cxa_begin_catch to get the pointer to the actual object. */ init = do_begin_catch (); } exp = create_temporary_var (ptr_type_node); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING); finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); } else finish_expr_stmt (do_begin_catch ()); /* C++ requires that we call __cxa_end_catch at the end of processing the exception. */ if (! is_java) push_eh_cleanup (type); if (decl) initialize_handler_parm (decl, exp); return type; }