static tree ptm_initializer (tree desc, tree target) { tree init = tinfo_base_init (desc, target); tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target); tree klass = TYPE_PTRMEM_CLASS_TYPE (target); int flags = qualifier_flags (to); bool incomplete = target_incomplete_p (to); if (incomplete) flags |= 0x8; if (!COMPLETE_TYPE_P (klass)) flags |= 0x10; init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (klass), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
static tree vxworks_emutls_var_init (tree var, tree decl, tree tmpl_addr) { VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 3); constructor_elt *elt; tree type = TREE_TYPE (var); tree field = TYPE_FIELDS (type); elt = VEC_quick_push (constructor_elt, v, NULL); elt->index = field; elt->value = fold_convert (TREE_TYPE (field), tmpl_addr); elt = VEC_quick_push (constructor_elt, v, NULL); field = DECL_CHAIN (field); elt->index = field; elt->value = build_int_cst (TREE_TYPE (field), 0); elt = VEC_quick_push (constructor_elt, v, NULL); field = DECL_CHAIN (field); elt->index = field; elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); return build_constructor (type, v); }
static tree generic_initializer (tree desc, tree target) { tree init = tinfo_base_init (desc, target); init = build_constructor (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
static tree class_initializer (tree desc, tree target, tree trail) { tree init = tinfo_base_init (desc, target); TREE_CHAIN (init) = trail; init = build_constructor (NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
static void build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, tree tidx) { tree array_type, ctor, decl, value_type, name, fetch; gimple load; gimple_stmt_iterator gsi; gcc_assert (info.default_values[num]); value_type = TREE_TYPE (info.default_values[num]); array_type = build_array_type (value_type, arr_index_type); ctor = build_constructor (array_type, info.constructors[num]); TREE_CONSTANT (ctor) = true; decl = build_decl (VAR_DECL, NULL_TREE, array_type); TREE_STATIC (decl) = 1; DECL_INITIAL (decl) = ctor; DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); DECL_ARTIFICIAL (decl) = 1; TREE_CONSTANT (decl) = 1; add_referenced_var (decl); varpool_mark_needed_node (varpool_node (decl)); varpool_finalize_decl (decl); mark_sym_for_renaming (decl); name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL); info.target_inbound_names[num] = name; fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, NULL_TREE); load = gimple_build_assign (name, fetch); SSA_NAME_DEF_STMT (name) = load; gsi = gsi_for_stmt (swtch); gsi_insert_before (&gsi, load, GSI_SAME_STMT); mark_symbols_for_renaming (load); info.arr_ref_last = load; }
static tree ptr_initializer (tree desc, tree target) { tree init = tinfo_base_init (desc, target); tree to = TREE_TYPE (target); int flags = qualifier_flags (to); bool incomplete = target_incomplete_p (to); if (incomplete) flags |= 8; init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
static tree vxworks_emutls_var_init (tree var, tree decl, tree tmpl_addr) { vec<constructor_elt, va_gc> *v; vec_alloc (v, 3); tree type = TREE_TYPE (var); tree field = TYPE_FIELDS (type); constructor_elt elt = {field, fold_convert (TREE_TYPE (field), tmpl_addr)}; v->quick_push (elt); field = DECL_CHAIN (field); elt.index = field; elt.value = build_int_cst (TREE_TYPE (field), 0); v->quick_push (elt); field = DECL_CHAIN (field); elt.index = field; elt.value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); v->quick_push (elt); return build_constructor (type, v); }
static tree get_pseudo_ti_init (tree type, tree var_desc) { gcc_assert (at_eof); switch (TREE_CODE (type)) { case OFFSET_TYPE: return ptm_initializer (var_desc, type); case POINTER_TYPE: return ptr_initializer (var_desc, type); case ENUMERAL_TYPE: return generic_initializer (var_desc, type); break; case FUNCTION_TYPE: return generic_initializer (var_desc, type); break; case ARRAY_TYPE: return generic_initializer (var_desc, type); break; case UNION_TYPE: case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (type)) return ptm_initializer (var_desc, type); else if (var_desc == class_desc_type_node) return class_initializer (var_desc, type, NULL_TREE); else if (var_desc == si_class_desc_type_node) { tree base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), 0); tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo)); tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE); return class_initializer (var_desc, type, base_inits); } else { int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0) | (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1)); tree binfo = TYPE_BINFO (type); int nbases = BINFO_N_BASE_BINFOS (binfo); VEC (tree) *base_accesses = BINFO_BASE_ACCESSES (binfo); tree base_inits = NULL_TREE; int ix; /* Generate the base information initializer. */ for (ix = nbases; ix--;) { tree base_binfo = BINFO_BASE_BINFO (binfo, ix); tree base_init = NULL_TREE; int flags = 0; tree tinfo; tree offset; if (VEC_index (tree, base_accesses, ix) == access_public_node) flags |= 2; tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo)); if (BINFO_VIRTUAL_P (base_binfo)) { /* We store the vtable offset at which the virtual base offset can be found. */ offset = BINFO_VPTR_FIELD (base_binfo); offset = convert (sizetype, offset); flags |= 1; } else offset = BINFO_OFFSET (base_binfo); /* Combine offset and flags into one field. */ offset = cp_build_binary_op (LSHIFT_EXPR, offset, build_int_cst (NULL_TREE, 8)); offset = cp_build_binary_op (BIT_IOR_EXPR, offset, build_int_cst (NULL_TREE, flags)); base_init = tree_cons (NULL_TREE, offset, base_init); base_init = tree_cons (NULL_TREE, tinfo, base_init); base_init = build_constructor (NULL_TREE, base_init); base_inits = tree_cons (NULL_TREE, base_init, base_inits); } base_inits = build_constructor (NULL_TREE, base_inits); base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); /* Prepend the number of bases. */ base_inits = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, nbases), base_inits); /* Prepend the hint flags. */ base_inits = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, hint), base_inits); return class_initializer (var_desc, type, base_inits); } break; default: return generic_initializer (var_desc, type); } }
int cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case VEC_INIT_EXPR: { location_t loc = input_location; tree init = VEC_INIT_EXPR_INIT (*expr_p); int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE); gcc_assert (EXPR_HAS_LOCATION (*expr_p)); input_location = EXPR_LOCATION (*expr_p); *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, init, VEC_INIT_EXPR_VALUE_INIT (*expr_p), from_array, tf_warning_or_error); cp_genericize_tree (expr_p); ret = GS_OK; input_location = loc; } break; case THROW_EXPR: /* FIXME communicate throw type to back end, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: ret = gimplify_must_not_throw_expr (expr_p, pre_p); break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); cp_gimplify_init_expr (expr_p); if (TREE_CODE (*expr_p) != INIT_EXPR) return GS_OK; /* Otherwise fall through. */ case MODIFY_EXPR: { if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); /* If the back end isn't clever enough to know that the lhs and rhs types are the same, add an explicit conversion. */ tree op0 = TREE_OPERAND (*expr_p, 0); tree op1 = TREE_OPERAND (*expr_p, 1); if (!error_operand_p (op0) && !error_operand_p (op1) && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0)) || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1))) && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op0), op1); else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1) || (TREE_CODE (op1) == CONSTRUCTOR && CONSTRUCTOR_NELTS (op1) == 0 && !TREE_CLOBBER_P (op1)) || (TREE_CODE (op1) == CALL_EXPR && !CALL_EXPR_RETURN_SLOT_OPT (op1))) && is_really_empty_class (TREE_TYPE (op0))) { /* Remove any copies of empty classes. We check that the RHS has a simple form so that TARGET_EXPRs and non-empty CONSTRUCTORs get reduced properly, and we leave the return slot optimization alone because it isn't a copy (FIXME so it shouldn't be represented as one). Also drop volatile variables on the RHS to avoid infinite recursion from gimplify_expr trying to load the value. */ if (!TREE_SIDE_EFFECTS (op1) || (DECL_P (op1) && TREE_THIS_VOLATILE (op1))) *expr_p = op0; else if (TREE_CODE (op1) == MEM_REF && TREE_THIS_VOLATILE (op1)) { /* Similarly for volatile MEM_REFs on the RHS. */ if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0))) *expr_p = op0; else *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), TREE_OPERAND (op1, 0), op0); } else *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), op0, op1); } } ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: gcc_unreachable (); case FOR_STMT: case WHILE_STMT: case DO_STMT: case SWITCH_STMT: case CONTINUE_STMT: case BREAK_STMT: gcc_unreachable (); case OMP_FOR: case OMP_SIMD: case OMP_DISTRIBUTE: ret = cp_gimplify_omp_for (expr_p, pre_p); break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; case CILK_SPAWN_STMT: gcc_assert (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p)); /* If errors are seen, then just process it as a CALL_EXPR. */ if (!seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); case CALL_EXPR: if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); default: ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
static tree get_init_field (segment_info *head, tree union_type, tree *field_init, record_layout_info rli) { segment_info *s; HOST_WIDE_INT length = 0; HOST_WIDE_INT offset = 0; unsigned HOST_WIDE_INT known_align, desired_align; bool overlap = false; tree tmp, field; tree init; unsigned char *data, *chk; VEC(constructor_elt,gc) *v = NULL; tree type = unsigned_char_type_node; int i; /* Obtain the size of the union and check if there are any overlapping initializers. */ for (s = head; s; s = s->next) { HOST_WIDE_INT slen = s->offset + s->length; if (s->sym->value) { if (s->offset < offset) overlap = true; offset = slen; } length = length < slen ? slen : length; } if (!overlap) return NULL_TREE; /* Now absorb all the initializer data into a single vector, whilst checking for overlapping, unequal values. */ data = XCNEWVEC (unsigned char, (size_t)length); chk = XCNEWVEC (unsigned char, (size_t)length); /* TODO - change this when default initialization is implemented. */ memset (data, '\0', (size_t)length); memset (chk, '\0', (size_t)length); for (s = head; s; s = s->next) if (s->sym->value) gfc_merge_initializers (s->sym->ts, s->sym->value, &data[s->offset], &chk[s->offset], (size_t)s->length); for (i = 0; i < length; i++) CONSTRUCTOR_APPEND_ELT (v, NULL, build_int_cst (type, data[i])); free (data); free (chk); /* Build a char[length] array to hold the initializers. Much of what follows is borrowed from build_field, above. */ tmp = build_int_cst (gfc_array_index_type, length - 1); tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp); tmp = build_array_type (type, tmp); field = build_decl (gfc_current_locus.lb->location, FIELD_DECL, NULL_TREE, tmp); known_align = BIGGEST_ALIGNMENT; desired_align = update_alignment_for_field (rli, field, known_align); if (desired_align > known_align) DECL_PACKED (field) = 1; DECL_FIELD_CONTEXT (field) = union_type; DECL_FIELD_OFFSET (field) = size_int (0); DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node; SET_DECL_OFFSET_ALIGN (field, known_align); rli->offset = size_binop (MAX_EXPR, rli->offset, size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), DECL_SIZE_UNIT (field))); init = build_constructor (TREE_TYPE (field), v); TREE_CONSTANT (init) = 1; *field_init = init; for (s = head; s; s = s->next) { if (s->sym->value == NULL) continue; gfc_free_expr (s->sym->value); s->sym->value = NULL; } return field; }
tree ubsan_create_data (const char *name, const location_t *ploc, const struct ubsan_mismatch_data *mismatch, ...) { va_list args; tree ret, t; tree fields[5]; vec<tree, va_gc> *saved_args = NULL; size_t i = 0; location_t loc = UNKNOWN_LOCATION; /* Firstly, create a pointer to type descriptor type. */ tree td_type = ubsan_type_descriptor_type (); TYPE_READONLY (td_type) = 1; td_type = build_pointer_type (td_type); /* Create the structure type. */ ret = make_node (RECORD_TYPE); if (ploc != NULL) { loc = LOCATION_LOCUS (*ploc); fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, ubsan_source_location_type ()); DECL_CONTEXT (fields[i]) = ret; i++; } va_start (args, mismatch); for (t = va_arg (args, tree); t != NULL_TREE; i++, t = va_arg (args, tree)) { gcc_checking_assert (i < 3); /* Save the tree arguments for later use. */ vec_safe_push (saved_args, t); fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, td_type); DECL_CONTEXT (fields[i]) = ret; if (i) DECL_CHAIN (fields[i - 1]) = fields[i]; } va_end (args); if (mismatch != NULL) { /* We have to add two more decls. */ fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, pointer_sized_int_node); DECL_CONTEXT (fields[i]) = ret; DECL_CHAIN (fields[i - 1]) = fields[i]; i++; fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, unsigned_char_type_node); DECL_CONTEXT (fields[i]) = ret; DECL_CHAIN (fields[i - 1]) = fields[i]; i++; } TYPE_FIELDS (ret) = fields[0]; TYPE_NAME (ret) = get_identifier (name); layout_type (ret); /* Now, fill in the type. */ char tmp_name[32]; static unsigned int ubsan_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++); tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), ret); TREE_STATIC (var) = 1; TREE_PUBLIC (var) = 0; DECL_ARTIFICIAL (var) = 1; DECL_IGNORED_P (var) = 1; DECL_EXTERNAL (var) = 0; vec<constructor_elt, va_gc> *v; vec_alloc (v, i); tree ctor = build_constructor (ret, v); /* If desirable, set the __ubsan_source_location element. */ if (ploc != NULL) CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc)); size_t nelts = vec_safe_length (saved_args); for (i = 0; i < nelts; i++) { t = (*saved_args)[i]; CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t); } if (mismatch != NULL) { /* Append the pointer data. */ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->align); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->ckind); } TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (var) = ctor; varpool_finalize_decl (var); return var; }
int cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case THROW_EXPR: /* FIXME communicate throw type to backend, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: gimplify_must_not_throw_expr (expr_p, pre_p); ret = GS_OK; break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: /* Just ignore for now. Eventually we will want to pass this on to the debugger. */ *expr_p = build_empty_stmt (); ret = GS_ALL_DONE; break; case IF_STMT: gimplify_if_stmt (expr_p); ret = GS_OK; break; case FOR_STMT: gimplify_for_stmt (expr_p, pre_p); ret = GS_ALL_DONE; break; case WHILE_STMT: gimplify_while_stmt (expr_p); ret = GS_ALL_DONE; break; case DO_STMT: gimplify_do_stmt (expr_p); ret = GS_ALL_DONE; break; case SWITCH_STMT: gimplify_switch_stmt (expr_p); ret = GS_ALL_DONE; break; case CONTINUE_STMT: *expr_p = build_bc_goto (bc_continue); ret = GS_ALL_DONE; break; case BREAK_STMT: *expr_p = build_bc_goto (bc_break); ret = GS_ALL_DONE; break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
int cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; tree block = NULL; VEC(gimple, heap) *bind_expr_stack = NULL; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case THROW_EXPR: /* FIXME communicate throw type to back end, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: ret = gimplify_must_not_throw_expr (expr_p, pre_p); break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: /* Get the innermost inclosing GIMPLE_BIND that has a non NULL BLOCK, and append an IMPORTED_DECL to its BLOCK_VARS chained list. */ bind_expr_stack = gimple_bind_expr_stack (); if (bind_expr_stack) { int i; for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--) if ((block = gimple_bind_block (VEC_index (gimple, bind_expr_stack, i)))) break; } if (block) { tree using_directive; gcc_assert (TREE_OPERAND (*expr_p, 0)); using_directive = make_node (IMPORTED_DECL); TREE_TYPE (using_directive) = void_type_node; IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = TREE_OPERAND (*expr_p, 0); TREE_CHAIN (using_directive) = BLOCK_VARS (block); BLOCK_VARS (block) = using_directive; } /* The USING_STMT won't appear in GIMPLE. */ *expr_p = NULL; ret = GS_ALL_DONE; break; case FOR_STMT: gimplify_for_stmt (expr_p, pre_p); ret = GS_OK; break; case WHILE_STMT: gimplify_while_stmt (expr_p, pre_p); ret = GS_OK; break; case DO_STMT: gimplify_do_stmt (expr_p, pre_p); ret = GS_OK; break; case SWITCH_STMT: gimplify_switch_stmt (expr_p, pre_p); ret = GS_OK; break; case OMP_FOR: ret = cp_gimplify_omp_for (expr_p, pre_p); break; case CONTINUE_STMT: gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN)); gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue))); *expr_p = NULL_TREE; ret = GS_ALL_DONE; break; case BREAK_STMT: gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break))); *expr_p = NULL_TREE; ret = GS_ALL_DONE; break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
static tree handle_latent_entropy_attribute(tree *node, tree name, tree args __unused, int flags __unused, bool *no_add_attrs) { tree type; #if BUILDING_GCC_VERSION <= 4007 VEC(constructor_elt, gc) *vals; #else vec<constructor_elt, va_gc> *vals; #endif switch (TREE_CODE(*node)) { default: *no_add_attrs = true; error("%qE attribute only applies to functions and variables", name); break; case VAR_DECL: if (DECL_INITIAL(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be initialized", *node, name); break; } if (!TREE_STATIC(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be local", *node, name); break; } type = TREE_TYPE(*node); switch (TREE_CODE(type)) { default: *no_add_attrs = true; error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", *node, name); break; case RECORD_TYPE: { tree fld, lst = TYPE_FIELDS(type); unsigned int nelt = 0; for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) { tree fieldtype; fieldtype = TREE_TYPE(fld); if (TREE_CODE(fieldtype) == INTEGER_TYPE) continue; *no_add_attrs = true; error("structure variable %qD with %qE attribute has a non-integer field %qE", *node, name, fld); break; } if (fld) break; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (fld = lst; fld; fld = TREE_CHAIN(fld)) { tree random_const, fld_t = TREE_TYPE(fld); random_const = tree_get_random_const(fld_t); CONSTRUCTOR_APPEND_ELT(vals, fld, random_const); } /* Initialize the fields with random constants */ DECL_INITIAL(*node) = build_constructor(type, vals); break; } /* Initialize the variable with a random constant */ case INTEGER_TYPE: DECL_INITIAL(*node) = tree_get_random_const(type); break; case ARRAY_TYPE: { tree elt_type, array_size, elt_size; unsigned int i, nelt; HOST_WIDE_INT array_size_int, elt_size_int; elt_type = TREE_TYPE(type); elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); array_size = TYPE_SIZE_UNIT(type); if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size || TREE_CODE(array_size) != INTEGER_CST) { *no_add_attrs = true; error("array variable %qD with %qE attribute must be a fixed length integer array type", *node, name); break; } array_size_int = TREE_INT_CST_LOW(array_size); elt_size_int = TREE_INT_CST_LOW(elt_size); nelt = array_size_int / elt_size_int; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (i = 0; i < nelt; i++) { tree cst = size_int(i); tree rand_cst = tree_get_random_const(elt_type); CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst); } /* * Initialize the elements of the array with random * constants */ DECL_INITIAL(*node) = build_constructor(type, vals); break; } } break; case FUNCTION_DECL: break; } return NULL_TREE; }
tree ubsan_create_data (const char *name, location_t loc, ...) { va_list args; tree ret, t; tree fields[3]; VEC(tree, gc) *saved_args = NULL; size_t i = 0; /* Firstly, create a pointer to type descriptor type. */ tree td_type = ubsan_type_descriptor_type (); TYPE_READONLY (td_type) = 1; td_type = build_pointer_type (td_type); /* Create the structure type. */ ret = make_node (RECORD_TYPE); if (loc != UNKNOWN_LOCATION) { fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, ubsan_source_location_type ()); DECL_CONTEXT (fields[i]) = ret; i++; } va_start (args, loc); for (t = va_arg (args, tree); t != NULL_TREE; i++, t = va_arg (args, tree)) { gcc_checking_assert (i < 3); /* Save the tree argument for later use. */ VEC_safe_push (tree, gc, saved_args, t); fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, td_type); DECL_CONTEXT (fields[i]) = ret; if (i) DECL_CHAIN (fields[i - 1]) = fields[i]; } TYPE_FIELDS (ret) = fields[0]; TYPE_NAME (ret) = get_identifier (name); layout_type (ret); va_end (args); /* Now, fill in the type. */ char tmp_name[32]; static unsigned int ubsan_var_id_num; ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++); tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name), ret); TREE_STATIC (var) = 1; TREE_PUBLIC (var) = 0; DECL_ARTIFICIAL (var) = 1; DECL_IGNORED_P (var) = 1; DECL_EXTERNAL (var) = 0; VEC(constructor_elt, gc) *v; v = VEC_alloc (constructor_elt, gc, i); tree ctor = build_constructor (ret, v); /* If desirable, set the __ubsan_source_location element. */ if (loc != UNKNOWN_LOCATION) CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc)); size_t nelts = VEC_length (tree, saved_args); for (i = 0; i < nelts; i++) { t = VEC_index (tree, saved_args, i); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t); } TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (var) = ctor; rest_of_decl_compilation (var, 1, 0); return var; }
tree build_lambda_object (tree lambda_expr) { /* Build aggregate constructor call. - cp_parser_braced_list - cp_parser_functional_cast */ vec<constructor_elt, va_gc> *elts = NULL; tree node, expr, type; location_t saved_loc; if (processing_template_decl) return lambda_expr; /* Make sure any error messages refer to the lambda-introducer. */ saved_loc = input_location; input_location = LAMBDA_EXPR_LOCATION (lambda_expr); for (node = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); node; node = TREE_CHAIN (node)) { tree field = TREE_PURPOSE (node); tree val = TREE_VALUE (node); if (field == error_mark_node) { expr = error_mark_node; goto out; } if (DECL_P (val)) mark_used (val); /* Mere mortals can't copy arrays with aggregate initialization, so do some magic to make it work here. */ if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) val = build_array_copy (val); else if (DECL_NORMAL_CAPTURE_P (field) && !DECL_VLA_CAPTURE_P (field) && TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE) { /* "the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object." There's normally no way to express direct-initialization from an element of a CONSTRUCTOR, so we build up a special TARGET_EXPR to bypass the usual copy-initialization. */ val = force_rvalue (val, tf_warning_or_error); if (TREE_CODE (val) == TARGET_EXPR) TARGET_EXPR_DIRECT_INIT_P (val) = true; } CONSTRUCTOR_APPEND_ELT (elts, DECL_NAME (field), val); } expr = build_constructor (init_list_type_node, elts); CONSTRUCTOR_IS_DIRECT_INIT (expr) = 1; /* N2927: "[The closure] class type is not an aggregate." But we briefly treat it as an aggregate to make this simpler. */ type = LAMBDA_EXPR_CLOSURE (lambda_expr); CLASSTYPE_NON_AGGREGATE (type) = 0; expr = finish_compound_literal (type, expr, tf_warning_or_error); CLASSTYPE_NON_AGGREGATE (type) = 1; out: input_location = saved_loc; return expr; }
static tree tinfo_base_init (tree desc, tree target) { tree init = NULL_TREE; tree name_decl; tree vtable_ptr; { tree name_name; /* Generate the NTBS array variable. */ tree name_type = build_cplus_array_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST), NULL_TREE); tree name_string = tinfo_name (target); /* Determine the name of the variable -- and remember with which type it is associated. */ name_name = mangle_typeinfo_string_for_type (target); TREE_TYPE (name_name) = target; name_decl = build_lang_decl (VAR_DECL, name_name, name_type); SET_DECL_ASSEMBLER_NAME (name_decl, name_name); DECL_ARTIFICIAL (name_decl) = 1; DECL_IGNORED_P (name_decl) = 1; TREE_READONLY (name_decl) = 1; TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; DECL_TINFO_P (name_decl) = 1; if (involves_incomplete_p (target)) { TREE_PUBLIC (name_decl) = 0; DECL_INTERFACE_KNOWN (name_decl) = 1; } else set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); } vtable_ptr = TINFO_VTABLE_DECL (desc); if (!vtable_ptr) { tree real_type; push_nested_namespace (abi_node); real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), /* APPLE LOCAL 4184203 */ /*tag_scope=*/ts_global, false); pop_nested_namespace (abi_node); if (!COMPLETE_TYPE_P (real_type)) { /* We never saw a definition of this type, so we need to tell the compiler that this is an exported class, as indeed all of the __*_type_info classes are. */ SET_CLASSTYPE_INTERFACE_KNOWN (real_type); CLASSTYPE_INTERFACE_ONLY (real_type) = 1; } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, size_binop (MULT_EXPR, size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), TYPE_SIZE_UNIT (vtable_entry_type))); TINFO_VTABLE_DECL (desc) = vtable_ptr; } init = tree_cons (NULL_TREE, vtable_ptr, init); init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); return init; }
static void create_common (gfc_common_head *com, segment_info *head, bool saw_equiv) { segment_info *s, *next_s; tree union_type; tree *field_link; tree field; tree field_init = NULL_TREE; record_layout_info rli; tree decl; bool is_init = false; bool is_saved = false; /* Declare the variables inside the common block. If the current common block contains any equivalence object, then make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the alias analyzer work well when there is no address overlapping for common variables in the current common block. */ if (saw_equiv) union_type = make_node (UNION_TYPE); else union_type = make_node (RECORD_TYPE); rli = start_record_layout (union_type); field_link = &TYPE_FIELDS (union_type); /* Check for overlapping initializers and replace them with a single, artificial field that contains all the data. */ if (saw_equiv) field = get_init_field (head, union_type, &field_init, rli); else field = NULL_TREE; if (field != NULL_TREE) { is_init = true; *field_link = field; field_link = &DECL_CHAIN (field); } for (s = head; s; s = s->next) { build_field (s, union_type, rli); /* Link the field into the type. */ *field_link = s->field; field_link = &DECL_CHAIN (s->field); /* Has initial value. */ if (s->sym->value) is_init = true; /* Has SAVE attribute. */ if (s->sym->attr.save) is_saved = true; } finish_record_layout (rli, true); if (com) decl = build_common_decl (com, union_type, is_init); else decl = build_equiv_decl (union_type, is_init, is_saved); if (is_init) { tree ctor, tmp; VEC(constructor_elt,gc) *v = NULL; if (field != NULL_TREE && field_init != NULL_TREE) CONSTRUCTOR_APPEND_ELT (v, field, field_init); else for (s = head; s; s = s->next) { if (s->sym->value) { /* Add the initializer for this field. */ tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts, TREE_TYPE (s->field), s->sym->attr.dimension, s->sym->attr.pointer || s->sym->attr.allocatable, false); CONSTRUCTOR_APPEND_ELT (v, s->field, tmp); } } gcc_assert (!VEC_empty (constructor_elt, v)); ctor = build_constructor (union_type, v); TREE_CONSTANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; #ifdef ENABLE_CHECKING { tree field, value; unsigned HOST_WIDE_INT idx; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value) gcc_assert (TREE_CODE (field) == FIELD_DECL); } #endif } /* Build component reference for each variable. */ for (s = head; s; s = next_s) { tree var_decl; var_decl = build_decl (s->sym->declared_at.lb->location, VAR_DECL, DECL_NAME (s->field), TREE_TYPE (s->field)); TREE_STATIC (var_decl) = TREE_STATIC (decl); /* Mark the variable as used in order to avoid warnings about unused variables. */ TREE_USED (var_decl) = 1; if (s->sym->attr.use_assoc) DECL_IGNORED_P (var_decl) = 1; if (s->sym->attr.target) TREE_ADDRESSABLE (var_decl) = 1; /* Fake variables are not visible from other translation units. */ TREE_PUBLIC (var_decl) = 0; /* To preserve identifier names in COMMON, chain to procedure scope unless at top level in a module definition. */ if (com && s->sym->ns->proc_name && s->sym->ns->proc_name->attr.flavor == FL_MODULE) var_decl = pushdecl_top_level (var_decl); else gfc_add_decl_to_function (var_decl); SET_DECL_VALUE_EXPR (var_decl, fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (s->field), decl, s->field, NULL_TREE)); DECL_HAS_VALUE_EXPR_P (var_decl) = 1; GFC_DECL_COMMON_OR_EQUIV (var_decl) = 1; if (s->sym->attr.assign) { gfc_allocate_lang_decl (var_decl); GFC_DECL_ASSIGN (var_decl) = 1; GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field); GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field); } s->sym->backend_decl = var_decl; next_s = s->next; free (s); } }
static tree handle_latent_entropy_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs) { tree type; unsigned long long mask; #if BUILDING_GCC_VERSION <= 4007 VEC(constructor_elt, gc) *vals; #else vec<constructor_elt, va_gc> *vals; #endif switch (TREE_CODE(*node)) { default: *no_add_attrs = true; error("%qE attribute only applies to functions and variables", name); break; case VAR_DECL: if (DECL_INITIAL(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be initialized", *node, name); break; } if (!TREE_STATIC(*node)) { *no_add_attrs = true; error("variable %qD with %qE attribute must not be local", *node, name); break; } type = TREE_TYPE(*node); switch (TREE_CODE(type)) { default: *no_add_attrs = true; error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", *node, name); break; case RECORD_TYPE: { tree field; unsigned int nelt = 0; for (field = TYPE_FIELDS(type); field; nelt++, field = TREE_CHAIN(field)) { tree fieldtype; fieldtype = TREE_TYPE(field); if (TREE_CODE(fieldtype) != INTEGER_TYPE) { *no_add_attrs = true; error("structure variable %qD with %qE attribute has a non-integer field %qE", *node, name, field); break; } } if (field) break; #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) { tree fieldtype; fieldtype = TREE_TYPE(field); mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(fieldtype)) - 1); mask = 2 * (mask - 1) + 1; if (TYPE_UNSIGNED(fieldtype)) CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cstu(fieldtype, mask & get_random_const())); else CONSTRUCTOR_APPEND_ELT(vals, field, build_int_cst(fieldtype, mask & get_random_const())); } DECL_INITIAL(*node) = build_constructor(type, vals); //debug_tree(DECL_INITIAL(*node)); break; } case INTEGER_TYPE: mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); mask = 2 * (mask - 1) + 1; if (TYPE_UNSIGNED(type)) DECL_INITIAL(*node) = build_int_cstu(type, mask & get_random_const()); else DECL_INITIAL(*node) = build_int_cst(type, mask & get_random_const()); break; case ARRAY_TYPE: { tree elt_type, array_size, elt_size; unsigned int i, nelt; elt_type = TREE_TYPE(type); elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); array_size = TYPE_SIZE_UNIT(type); if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size || TREE_CODE(array_size) != INTEGER_CST) { *no_add_attrs = true; error("array variable %qD with %qE attribute must be a fixed length integer array type", *node, name); break; } nelt = TREE_INT_CST_LOW(array_size) / TREE_INT_CST_LOW(elt_size); #if BUILDING_GCC_VERSION <= 4007 vals = VEC_alloc(constructor_elt, gc, nelt); #else vec_alloc(vals, nelt); #endif mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(elt_type)) - 1); mask = 2 * (mask - 1) + 1; for (i = 0; i < nelt; i++) if (TYPE_UNSIGNED(elt_type)) CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cstu(elt_type, mask & get_random_const())); else CONSTRUCTOR_APPEND_ELT(vals, size_int(i), build_int_cst(elt_type, mask & get_random_const())); DECL_INITIAL(*node) = build_constructor(type, vals); //debug_tree(DECL_INITIAL(*node)); break; } } break; case FUNCTION_DECL: break; } return NULL_TREE; }