static void set_type_package_list (tree type) { int i; const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); const char *ptr; int qualifications; tree list = NULL_TREE, elt; for (ptr = type_string, qualifications = 0; *ptr; ptr++) if (*ptr == '.') qualifications += 1; for (ptr = type_string, i = 0; i < qualifications; ptr++) { if (ptr [0] == '.') { tree const identifier = get_identifier_with_length (type_string, ptr - type_string); elt = build_tree_list (identifier, identifier); TREE_CHAIN (elt) = list; list = elt; type_string = ptr+1; i += 1; } } elt = build_tree_list (type, get_identifier (type_string)); TREE_CHAIN (elt) = list; list = elt; TYPE_PACKAGE_LIST (type) = nreverse (list); }
static void change_size_overflow_asm_input(gasm *stmt, tree new_input) { tree list; gcc_assert(is_size_overflow_insert_check_asm(stmt)); list = build_tree_list(NULL_TREE, build_string(3, "rm")); list = chainon(NULL_TREE, build_tree_list(list, new_input)); gimple_asm_set_input_op(stmt, 0, list); }
static tree start_cdtor (int method_type) { tree fnname = get_file_function_name (method_type); tree void_list_node_1 = build_tree_list (NULL_TREE, void_type_node); tree body; start_function (void_list_node_1, build_nt (CALL_EXPR, fnname, tree_cons (NULL_TREE, NULL_TREE, void_list_node_1), NULL_TREE), NULL_TREE); store_parm_decls (); current_function_cannot_inline = "static constructors and destructors cannot be inlined"; body = c_begin_compound_stmt (); pushlevel (0); clear_last_expr (); add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); return body; }
static bool go_langhook_init (void) { build_common_tree_nodes (false, false); /* I don't know why this has to be done explicitly. */ void_list_node = build_tree_list (NULL_TREE, void_type_node); /* We must create the gogo IR after calling build_common_tree_nodes (because Gogo::define_builtin_function_trees refers indirectly to, e.g., unsigned_char_type_node) but before calling build_common_builtin_nodes (because it calls, indirectly, go_type_for_size). */ go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix, go_relative_import_path); build_common_builtin_nodes (); /* The default precision for floating point numbers. This is used for floating point constants with abstract type. This may eventually be controllable by a command line option. */ mpfr_set_default_prec (256); /* Go uses exceptions. */ using_eh_for_cleanups (); return true; }
edge ssa_redirect_edge (edge e, basic_block dest) { tree phi; tree list = NULL, *last = &list; tree src, dst, node; /* Remove the appropriate PHI arguments in E's destination block. */ for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi)) { if (PHI_ARG_DEF (phi, e->dest_idx) == NULL_TREE) continue; src = PHI_ARG_DEF (phi, e->dest_idx); dst = PHI_RESULT (phi); node = build_tree_list (dst, src); *last = node; last = &TREE_CHAIN (node); } e = redirect_edge_succ_nodup (e, dest); PENDING_STMT (e) = list; return e; }
static bool jit_langhook_init (void) { gcc_assert (gcc::jit::active_playback_ctxt); JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ()); static bool registered_root_tab = false; if (!registered_root_tab) { ggc_register_root_tab (jit_root_tab); registered_root_tab = true; } build_common_tree_nodes (false, false); /* I don't know why this has to be done explicitly. */ void_list_node = build_tree_list (NULL_TREE, void_type_node); build_common_builtin_nodes (); /* The default precision for floating point numbers. This is used for floating point constants with abstract type. This may eventually be controllable by a command line option. */ mpfr_set_default_prec (256); return true; }
void java_init_lex (FILE *finput, const char *encoding) { #ifndef JC1_LITE int java_lang_imported = 0; if (!java_lang_id) java_lang_id = get_identifier ("java.lang"); if (!inst_id) inst_id = get_identifier ("inst$"); if (!wpv_id) wpv_id = get_identifier ("write_parm_value$"); if (!java_lang_imported) { tree node = build_tree_list (build_unknown_wfl (java_lang_id), NULL_TREE); read_import_dir (TREE_PURPOSE (node)); TREE_CHAIN (node) = ctxp->import_demand_list; ctxp->import_demand_list = node; java_lang_imported = 1; } if (!wfl_operator) { #ifndef JC1_LITE #ifdef USE_MAPPED_LOCATION wfl_operator = build_expr_wfl (NULL_TREE, input_location); #else wfl_operator = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0); #endif #endif } if (!label_id) label_id = get_identifier ("$L"); if (!wfl_append) wfl_append = build_unknown_wfl (get_identifier ("append")); if (!wfl_string_buffer) wfl_string_buffer = build_unknown_wfl (get_identifier (flag_emit_class_files ? "java.lang.StringBuffer" : "gnu.gcj.runtime.StringBuffer")); if (!wfl_to_string) wfl_to_string = build_unknown_wfl (get_identifier ("toString")); CPC_INITIALIZER_LIST (ctxp) = CPC_STATIC_INITIALIZER_LIST (ctxp) = CPC_INSTANCE_INITIALIZER_LIST (ctxp) = NULL_TREE; memset (ctxp->modifier_ctx, 0, sizeof (ctxp->modifier_ctx)); ctxp->current_parsed_class = NULL; ctxp->package = NULL_TREE; #endif #ifndef JC1_LITE ctxp->save_location = input_location; #endif ctxp->java_error_flag = 0; ctxp->lexer = java_new_lexer (finput, encoding); }
void mchp_init_cci_builtins(void) { #define CCI(TARGET, CCI_KIND, CCI_KEYWORD, TGT_FN, N) \ if (TARGET && CCI_KIND == CCI_pragma) \ c_register_pragma(0, CCI_KEYWORD, TGT_FN); #include CCI_H /* * Special case mapping * */ if (IMPORT_MCHP("iar")) { /* define builtins for the functions that we don't define * and mark them as unsupported */ tree attrib, args; tree fn_type; # define MESSAGE "Intrinsic function is unsupported for this target" args = build_tree_list(NULL_TREE, build_string(strlen(MESSAGE), MESSAGE)); attrib = build_tree_list(get_identifier("target_error"), args); # undef MESSAGE fn_type = build_function_type_list(void_type_node, void_type_node,NULL_TREE); add_builtin_function("__disable_fiq", fn_type, 0, BUILT_IN_MD, NULL, attrib); /* ^ this should be okay * because we are going to generate an error for it... */ add_builtin_function("__disable_irq", fn_type, 0, BUILT_IN_MD, NULL, attrib); /* ^ this should be okay * because we are going to generate an error for it... */ add_builtin_function("__enable_fiq", fn_type, 0, BUILT_IN_MD, NULL, attrib); /* ^ this should be okay * because we are going to generate an error for it... */ add_builtin_function("__enable_irq", fn_type, 0, BUILT_IN_MD, NULL, attrib); /* ^ this should be okay * because we are going to generate an error for it... */ } }
void add_friend (tree type, tree decl, bool complain) { tree typedecl; tree list; tree name; tree ctx; if (decl == error_mark_node) return; typedecl = TYPE_MAIN_DECL (type); list = DECL_FRIENDLIST (typedecl); name = DECL_NAME (decl); type = TREE_TYPE (typedecl); while (list) { if (name == FRIEND_NAME (list)) { tree friends = FRIEND_DECLS (list); for (; friends ; friends = TREE_CHAIN (friends)) { if (decl == TREE_VALUE (friends)) { if (complain) warning (OPT_Wredundant_decls, "%qD is already a friend of class %qT", decl, type); return; } } maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); TREE_VALUE (list) = tree_cons (NULL_TREE, decl, TREE_VALUE (list)); return; } list = TREE_CHAIN (list); } ctx = DECL_CONTEXT (decl); if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx)) perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl, tf_warning_or_error); maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); DECL_FRIENDLIST (typedecl) = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl), DECL_FRIENDLIST (typedecl)); if (!uses_template_parms (type)) DECL_BEFRIENDING_CLASSES (decl) = tree_cons (NULL_TREE, type, DECL_BEFRIENDING_CLASSES (decl)); }
static void kernexec_instrument_fptr_or(gimple_stmt_iterator *gsi) { gimple asm_or_stmt, call_stmt; tree old_fptr, new_fptr, input, output; #if BUILDING_GCC_VERSION <= 4007 VEC(tree, gc) *inputs = NULL; VEC(tree, gc) *outputs = NULL; #else vec<tree, va_gc> *inputs = NULL; vec<tree, va_gc> *outputs = NULL; #endif call_stmt = gsi_stmt(*gsi); old_fptr = gimple_call_fn(call_stmt); // create temporary fptr variable new_fptr = create_tmp_var(TREE_TYPE(old_fptr), "kernexec_or"); #if BUILDING_GCC_VERSION <= 4007 add_referenced_var(new_fptr); #endif new_fptr = make_ssa_name(new_fptr, NULL); // build asm volatile("orq %%r10, %0\n\t" : "=r"(new_fptr) : "0"(old_fptr)); input = build_tree_list(NULL_TREE, build_string(2, "0")); input = chainon(NULL_TREE, build_tree_list(input, old_fptr)); output = build_tree_list(NULL_TREE, build_string(3, "=r")); output = chainon(NULL_TREE, build_tree_list(output, new_fptr)); #if BUILDING_GCC_VERSION <= 4007 VEC_safe_push(tree, gc, inputs, input); VEC_safe_push(tree, gc, outputs, output); #else vec_safe_push(inputs, input); vec_safe_push(outputs, output); #endif asm_or_stmt = gimple_build_asm_vec("orq %%r10, %0\n\t", inputs, outputs, NULL, NULL); SSA_NAME_DEF_STMT(new_fptr) = asm_or_stmt; gimple_asm_set_volatile(asm_or_stmt, true); gsi_insert_before(gsi, asm_or_stmt, GSI_SAME_STMT); update_stmt(asm_or_stmt); // replace call stmt fn with the new fptr gimple_call_set_fn(call_stmt, new_fptr); update_stmt(call_stmt); }
static void split_range (struct eh_range *range, int pc) { struct eh_range *ptr; struct eh_range **first_child, **second_child; struct eh_range *h; /* First, split all the sub-ranges. */ for (ptr = range->first_child; ptr; ptr = ptr->next_sibling) { if (pc > ptr->start_pc && pc < ptr->end_pc) { split_range (ptr, pc); } } /* Create a new range. */ h = XNEW (struct eh_range); h->start_pc = pc; h->end_pc = range->end_pc; h->next_sibling = range->next_sibling; range->next_sibling = h; range->end_pc = pc; h->handlers = build_tree_list (TREE_PURPOSE (range->handlers), TREE_VALUE (range->handlers)); h->next_sibling = NULL; h->expanded = 0; h->stmt = NULL; h->outer = range->outer; h->first_child = NULL; ptr = range->first_child; first_child = &range->first_child; second_child = &h->first_child; /* Distribute the sub-ranges between the two new ranges. */ for (ptr = range->first_child; ptr; ptr = ptr->next_sibling) { if (ptr->start_pc < pc) { *first_child = ptr; ptr->outer = range; first_child = &ptr->next_sibling; } else { *second_child = ptr; ptr->outer = h; second_child = &ptr->next_sibling; } } *first_child = NULL; *second_child = NULL; }
void java_init_lex () { #ifndef JC1_LITE int java_lang_imported = 0; if (!java_lang_id) java_lang_id = get_identifier ("java.lang"); if (!java_lang_cloneable) java_lang_cloneable = get_identifier ("java.lang.Cloneable"); if (!java_lang_imported) { tree node = build_tree_list (build_expr_wfl (java_lang_id, NULL, 0, 0), NULL_TREE); read_import_dir (TREE_PURPOSE (node)); TREE_CHAIN (node) = ctxp->import_demand_list; ctxp->import_demand_list = node; java_lang_imported = 1; } if (!wfl_operator) wfl_operator = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0); if (!label_id) label_id = get_identifier ("$L"); if (!wfl_append) wfl_append = build_expr_wfl (get_identifier ("append"), NULL, 0, 0); if (!wfl_string_buffer) wfl_string_buffer = build_expr_wfl (get_identifier ("java.lang.StringBuffer"), NULL, 0, 0); if (!wfl_to_string) wfl_to_string = build_expr_wfl (get_identifier ("toString"), NULL, 0, 0); ctxp->static_initialized = ctxp->non_static_initialized = ctxp->incomplete_class = NULL_TREE; bzero ((PTR) ctxp->modifier_ctx, 11*sizeof (ctxp->modifier_ctx[0])); bzero ((PTR) current_jcf, sizeof (JCF)); ctxp->current_parsed_class = NULL; ctxp->package = NULL_TREE; #endif ctxp->filename = input_filename; ctxp->lineno = lineno = 0; ctxp->p_line = NULL; ctxp->c_line = NULL; ctxp->unget_utf8_value = 0; ctxp->minus_seen = 0; ctxp->java_error_flag = 0; }
void cp_ubsan_maybe_initialize_vtbl_ptrs (tree addr) { if (!cp_ubsan_instrument_vptr_p (NULL_TREE)) return; tree type = TREE_TYPE (TREE_TYPE (addr)); tree list = build_tree_list (type, addr); /* Walk through the hierarchy, initializing the vptr in each base class to NULL. */ dfs_walk_once (TYPE_BINFO (type), cp_ubsan_dfs_initialize_vtbl_ptrs, NULL, list); }
void cp_ubsan_maybe_initialize_vtbl_ptrs (tree addr) { if (!cp_ubsan_instrument_vptr_p (NULL_TREE)) return; tree type = TREE_TYPE (TREE_TYPE (addr)); tree list = build_tree_list (type, addr); /* We cannot rely on the vtable being set up. We have to indirect via the vtt_parm. */ int save_in_base_initializer = in_base_initializer; in_base_initializer = 1; /* Walk through the hierarchy, initializing the vptr in each base class to NULL. */ dfs_walk_once (TYPE_BINFO (type), cp_ubsan_dfs_initialize_vtbl_ptrs, NULL, list); in_base_initializer = save_in_base_initializer; }
/* Language hooks. */ static bool gpy_langhook_init (void) { build_common_tree_nodes (false, false); // build_common_builtin_nodes (); // shouldnt have to do this... void_list_node = build_tree_list (NULL_TREE, void_type_node); // init some internal gccpy types gpy_dot_types_init (); /* The default precision for floating point numbers. This is used for floating point constants with abstract type. This may eventually be controllable by a command line option. */ mpfr_set_default_prec (128); // for exceptions using_eh_for_cleanups (); return true; }
/* Create tree nodes for the basic scalar types of Fortran 95, and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. Make definitions for built-in primitive functions. */ static void gfc_init_decl_processing (void) { current_function_decl = NULL; current_binding_level = NULL_BINDING_LEVEL; free_binding_level = NULL_BINDING_LEVEL; /* Make the binding_level structure for global names. We move all variables that are in a COMMON block to this binding level. */ pushlevel (); global_binding_level = current_binding_level; /* Build common tree nodes. char_type_node is unsigned because we only use it for actual characters, not for INTEGER(1). */ build_common_tree_nodes (false); void_list_node = build_tree_list (NULL_TREE, void_type_node); /* Set up F95 type nodes. */ gfc_init_kinds (); gfc_init_types (); gfc_init_c_interop_kinds (); }
static void finish_handler_array () { tree decl = current_handler->handler_array_decl; tree t; tree handler_array_init = NULL_TREE; int handlers_count = 1; int nelts; /* Build the table mapping exceptions to handler(-number)s. This is done in reverse order. */ /* First push the end of the list. This is either the ELSE handler (current_handler->else_handler>0) or NULL handler to indicate the end of the list (if current_handler->else-handler == 0). The following works either way. */ handler_array_init = build_tree_list (NULL_TREE, chill_expand_tuple (handler_element_type, build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, null_pointer_node, build_tree_list (NULL_TREE, build_int_2 (current_handler->else_handler, 0)))))); for (t = current_handler->on_alt_list; t != NULL_TREE; t = TREE_CHAIN (t)) { tree handler_number = TREE_PURPOSE(t); tree elist = TREE_VALUE (t); for ( ; elist != NULL_TREE; elist = TREE_CHAIN (elist)) { tree ex_decl = build_chill_exception_decl (IDENTIFIER_POINTER(TREE_VALUE(elist))); tree ex_addr = build1 (ADDR_EXPR, char_pointer_type_for_handler, ex_decl); tree el = build_nt (CONSTRUCTOR, NULL_TREE, tree_cons (NULL_TREE, ex_addr, build_tree_list (NULL_TREE, handler_number))); mark_addressable (ex_decl); TREE_CONSTANT (ex_addr) = 1; handler_array_init = tree_cons (NULL_TREE, chill_expand_tuple (handler_element_type, el), handler_array_init); handlers_count++; } } #if 1 nelts = list_length (handler_array_init); TYPE_DOMAIN (TREE_TYPE (decl)) = build_index_type (build_int_2 (nelts - 1, - (nelts == 0))); layout_type (TREE_TYPE (decl)); DECL_INITIAL (decl) = convert (TREE_TYPE (decl), build_nt (CONSTRUCTOR, NULL_TREE, handler_array_init)); /* Pop back to the obstack that is current for this binding level. This is because MAXINDEX, rtl, etc. to be made below must go in the permanent obstack. But don't discard the temporary data yet. */ pop_obstacks (); layout_decl (decl, 0); /* To prevent make_decl_rtl (called indiectly by rest_of_decl_compilation) throwing the existing RTL (which has already been used). */ PUT_MODE (DECL_RTL (decl), DECL_MODE (decl)); rest_of_decl_compilation (decl, (char*)0, 0, 0); expand_decl_init (decl); #else /* To prevent make_decl_rtl (called indirectly by finish_decl) altering the existing RTL. */ GET_MODE (DECL_RTL (current_handler->handler_array_decl)) = DECL_MODE (current_handler->handler_array_decl); finish_decl (current_handler->handler_array_decl, build_nt (CONSTRUCTOR, NULL_TREE, handler_array_init), NULL_TREE); #endif }
static void do_build_copy_constructor (tree fndecl) { tree parm = FUNCTION_FIRST_USER_PARM (fndecl); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) && is_empty_class (current_class_type)) /* Don't copy the padding byte; it might not have been allocated if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); tree member_init_list = NULL_TREE; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; tree binfo, base_binfo; VEC(tree,gc) *vbases; /* Initialize all the base-classes with the parameter converted to their type so that we get their copy constructor and not another constructor that takes current_class_type. We must deal with the binfo's directly as a direct base might be inaccessible due to ambiguity. */ for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; VEC_iterate (tree, vbases, i, binfo); i++) { member_init_list = tree_cons (binfo, build_tree_list (NULL_TREE, build_base_path (PLUS_EXPR, parm, binfo, 1)), member_init_list); } for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { if (BINFO_VIRTUAL_P (base_binfo)) continue; member_init_list = tree_cons (base_binfo, build_tree_list (NULL_TREE, build_base_path (PLUS_EXPR, parm, base_binfo, 1)), member_init_list); } for (; fields; fields = TREE_CHAIN (fields)) { tree init = parm; tree field = fields; tree expr_type; if (TREE_CODE (field) != FIELD_DECL) continue; expr_type = TREE_TYPE (field); if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; /* Compute the type of "init->field". If the copy-constructor parameter is, for example, "const S&", and the type of the field is "T", then the type will usually be "const T". (There are no cv-qualified variants of reference types.) */ if (TREE_CODE (expr_type) != REFERENCE_TYPE) { int quals = cvquals; if (DECL_MUTABLE_P (field)) quals &= ~TYPE_QUAL_CONST; expr_type = cp_build_qualified_type (expr_type, quals); } init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); init = build_tree_list (NULL_TREE, init); member_init_list = tree_cons (field, init, member_init_list); } finish_mem_initializers (member_init_list); } }
static void do_build_assign_ref (tree fndecl) { tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree compound_stmt; compound_stmt = begin_compound_stmt (0); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) && is_empty_class (current_class_type)) /* Don't copy the padding byte; it might not have been allocated if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else { tree fields; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; tree binfo, base_binfo; /* Assign to each of the direct base classes. */ for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree converted_parm; /* We must convert PARM directly to the base class explicitly since the base class may be ambiguous. */ converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); /* Call the base class assignment operator. */ finish_expr_stmt (build_special_member_call (current_class_ref, ansi_assopname (NOP_EXPR), build_tree_list (NULL_TREE, converted_parm), base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); } /* Assign to each of the non-static data members. */ for (fields = TYPE_FIELDS (current_class_type); fields; fields = TREE_CHAIN (fields)) { tree comp = current_class_ref; tree init = parm; tree field = fields; tree expr_type; int quals; if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; expr_type = TREE_TYPE (field); if (CP_TYPE_CONST_P (expr_type)) { error ("non-static const member %q#D, can't use default " "assignment operator", field); continue; } else if (TREE_CODE (expr_type) == REFERENCE_TYPE) { error ("non-static reference member %q#D, can't use " "default assignment operator", field); continue; } if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type) != NULL_TREE) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); /* Compute the type of init->field */ quals = cvquals; if (DECL_MUTABLE_P (field)) quals &= ~TYPE_QUAL_CONST; expr_type = cp_build_qualified_type (expr_type, quals); init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); if (DECL_NAME (field)) init = build_modify_expr (comp, NOP_EXPR, init); else init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); finish_expr_stmt (init); } } finish_return_stmt (current_class_ref); finish_compound_stmt (compound_stmt); }
void maybe_add_lambda_conv_op (tree type) { bool nested = (cfun != NULL); bool nested_def = decl_function_context (TYPE_MAIN_DECL (type)); tree callop = lambda_function (type); if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE) return; if (processing_template_decl) return; bool const generic_lambda_p = (DECL_TEMPLATE_INFO (callop) && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop); if (!generic_lambda_p && DECL_INITIAL (callop) == NULL_TREE) { /* If the op() wasn't instantiated due to errors, give up. */ gcc_assert (errorcount || sorrycount); return; } /* Non-template conversion operators are defined directly with build_call_a and using DIRECT_ARGVEC for arguments (including 'this'). Templates are deferred and the CALL is built in-place. In the case of a deduced return call op, the decltype expression, DECLTYPE_CALL, used as a substitute for the return type is also built in-place. The arguments of DECLTYPE_CALL in the return expression may differ in flags from those in the body CALL. In particular, parameter pack expansions are marked PACK_EXPANSION_LOCAL_P in the body CALL, but not in DECLTYPE_CALL. */ vec<tree, va_gc> *direct_argvec = 0; tree decltype_call = 0, call = 0; tree fn_result = TREE_TYPE (TREE_TYPE (callop)); if (generic_lambda_p) { /* Prepare the dependent member call for the static member function '_FUN' and, potentially, prepare another call to be used in a decltype return expression for a deduced return call op to allow for simple implementation of the conversion operator. */ tree instance = build_nop (type, null_pointer_node); tree objfn = build_min (COMPONENT_REF, NULL_TREE, instance, DECL_NAME (callop), NULL_TREE); int nargs = list_length (DECL_ARGUMENTS (callop)) - 1; call = prepare_op_call (objfn, nargs); if (type_uses_auto (fn_result)) decltype_call = prepare_op_call (objfn, nargs); } else { direct_argvec = make_tree_vector (); direct_argvec->quick_push (build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), null_pointer_node)); } /* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to declare the static member function "_FUN" below. For each arg append to DIRECT_ARGVEC (for the non-template case) or populate the pre-allocated call args (for the template case). If a parameter pack is found, expand it, flagging it as PACK_EXPANSION_LOCAL_P for the body call. */ tree fn_args = NULL_TREE; { int ix = 0; tree src = DECL_CHAIN (DECL_ARGUMENTS (callop)); tree tgt; while (src) { tree new_node = copy_node (src); if (!fn_args) fn_args = tgt = new_node; else { TREE_CHAIN (tgt) = new_node; tgt = new_node; } mark_exp_read (tgt); if (generic_lambda_p) { if (DECL_PACK_P (tgt)) { tree a = make_pack_expansion (tgt); if (decltype_call) CALL_EXPR_ARG (decltype_call, ix) = copy_node (a); PACK_EXPANSION_LOCAL_P (a) = true; CALL_EXPR_ARG (call, ix) = a; } else { tree a = convert_from_reference (tgt); CALL_EXPR_ARG (call, ix) = a; if (decltype_call) CALL_EXPR_ARG (decltype_call, ix) = copy_node (a); } ++ix; } else vec_safe_push (direct_argvec, tgt); src = TREE_CHAIN (src); } } if (generic_lambda_p) { if (decltype_call) { ++processing_template_decl; fn_result = finish_decltype_type (decltype_call, /*id_expression_or_member_access_p=*/false, tf_warning_or_error); --processing_template_decl; } } else call = build_call_a (callop, direct_argvec->length (), direct_argvec->address ()); CALL_FROM_THUNK_P (call) = 1; tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop)); /* First build up the conversion op. */ tree rettype = build_pointer_type (stattype); tree name = mangle_conv_op_name_for_type (rettype); tree thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST); tree fntype = build_method_type_directly (thistype, rettype, void_list_node); tree convfn = build_lang_decl (FUNCTION_DECL, name, fntype); tree fn = convfn; DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; SET_OVERLOADED_OPERATOR_CODE (fn, TYPE_EXPR); grokclassfn (type, fn, NO_SPECIAL); set_linkage_according_to_type (type, fn); rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST); if (nested_def) DECL_INTERFACE_KNOWN (fn) = 1; if (generic_lambda_p) fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); add_method (type, fn, NULL_TREE); /* Generic thunk code fails for varargs; we'll complain in mark_used if the conversion op is used. */ if (varargs_function_p (callop)) { DECL_DELETED_FN (fn) = 1; return; } /* Now build up the thunk to be returned. */ name = get_identifier ("_FUN"); tree statfn = build_lang_decl (FUNCTION_DECL, name, stattype); fn = statfn; DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop); if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT) DECL_ALIGN (fn) = 2 * BITS_PER_UNIT; grokclassfn (type, fn, NO_SPECIAL); set_linkage_according_to_type (type, fn); rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); DECL_IN_AGGR_P (fn) = 1; DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; DECL_STATIC_FUNCTION_P (fn) = 1; DECL_ARGUMENTS (fn) = fn_args; for (tree arg = fn_args; arg; arg = DECL_CHAIN (arg)) { /* Avoid duplicate -Wshadow warnings. */ DECL_NAME (arg) = NULL_TREE; DECL_CONTEXT (arg) = fn; } if (nested_def) DECL_INTERFACE_KNOWN (fn) = 1; if (generic_lambda_p) fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop)); /* Don't UBsan this function; we're deliberately calling op() with a null object argument. */ tree attrs = build_tree_list (get_identifier ("no_sanitize_undefined"), NULL_TREE); cplus_decl_attributes (&fn, attrs, 0); add_method (type, fn, NULL_TREE); if (nested) push_function_context (); else /* Still increment function_depth so that we don't GC in the middle of an expression. */ ++function_depth; /* Generate the body of the thunk. */ start_preparsed_function (statfn, NULL_TREE, SF_PRE_PARSED | SF_INCLASS_INLINE); if (DECL_ONE_ONLY (statfn)) { /* Put the thunk in the same comdat group as the call op. */ cgraph_node::get_create (statfn)->add_to_same_comdat_group (cgraph_node::get_create (callop)); } tree body = begin_function_body (); tree compound_stmt = begin_compound_stmt (0); if (!generic_lambda_p) { set_flags_from_callee (call); if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error); } call = convert_from_reference (call); finish_return_stmt (call); finish_compound_stmt (compound_stmt); finish_function_body (body); fn = finish_function (/*inline*/2); if (!generic_lambda_p) expand_or_defer_fn (fn); /* Generate the body of the conversion op. */ start_preparsed_function (convfn, NULL_TREE, SF_PRE_PARSED | SF_INCLASS_INLINE); body = begin_function_body (); compound_stmt = begin_compound_stmt (0); /* decl_needed_p needs to see that it's used. */ TREE_USED (statfn) = 1; finish_return_stmt (decay_conversion (statfn, tf_warning_or_error)); finish_compound_stmt (compound_stmt); finish_function_body (body); fn = finish_function (/*inline*/2); if (!generic_lambda_p) expand_or_defer_fn (fn); if (nested) pop_function_context (); else --function_depth; }
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; }
void add_handler (int start_pc, int end_pc, tree handler, tree type) { struct eh_range *ptr, *h; struct eh_range **first_child, **prev; /* First, split all the existing ranges that we need to enclose. */ for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling) { if (start_pc > ptr->start_pc && start_pc < ptr->end_pc) { split_range (ptr, start_pc); } if (end_pc > ptr->start_pc && end_pc < ptr->end_pc) { split_range (ptr, end_pc); } if (ptr->start_pc >= end_pc) break; } /* Create the new range. */ h = XNEW (struct eh_range); first_child = &h->first_child; h->start_pc = start_pc; h->end_pc = end_pc; h->first_child = NULL; h->outer = NULL_EH_RANGE; h->handlers = build_tree_list (type, handler); h->next_sibling = NULL; h->expanded = 0; h->stmt = NULL; /* Find every range at the top level that will be a sub-range of the range we're inserting and make it so. */ { struct eh_range **prev = &whole_range.first_child; for (ptr = *prev; ptr;) { struct eh_range *next = ptr->next_sibling; if (ptr->start_pc >= end_pc) break; if (ptr->start_pc < start_pc) { prev = &ptr->next_sibling; } else if (ptr->start_pc >= start_pc && ptr->start_pc < end_pc) { *prev = next; *first_child = ptr; first_child = &ptr->next_sibling; ptr->outer = h; ptr->next_sibling = NULL; } ptr = next; } } /* Find the right place to insert the new range. */ prev = &whole_range.first_child; for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling) { gcc_assert (ptr->outer == NULL_EH_RANGE); if (ptr->start_pc >= start_pc) break; } /* And insert it there. */ *prev = h; if (ptr) { h->next_sibling = ptr; h->outer = ptr->outer; } }
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; }