static tree cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, void *data) { if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) return dfs_skip_bases; if (!BINFO_PRIMARY_P (binfo)) { tree base_ptr = TREE_VALUE ((tree) data); base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1, tf_warning_or_error); /* Compute the location of the vtpr. */ tree vtbl_ptr = build_vfield_ref (cp_build_fold_indirect_ref (base_ptr), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); /* Assign NULL to the vptr. */ tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr)); tree stmt = cp_build_modify_expr (input_location, vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error); if (vptr_via_virtual_p (binfo)) /* If this vptr comes from a virtual base of the complete object, only clear it if we're in charge of virtual bases. */ stmt = build_if_in_charge (stmt); finish_expr_stmt (stmt); } return NULL_TREE; }
static tree cp_ubsan_dfs_initialize_vtbl_ptrs (tree binfo, void *data) { if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))) return dfs_skip_bases; if (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo)) { tree base_ptr = TREE_VALUE ((tree) data); base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1, tf_warning_or_error); /* Compute the location of the vtpr. */ tree vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (base_ptr, RO_NULL, tf_warning_or_error), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); /* Assign NULL to the vptr. */ tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr)); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } return NULL_TREE; }
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; VEC(tree,gc) *parmvec; /* 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. */ parmvec = make_tree_vector_single (converted_parm); finish_expr_stmt (build_special_member_call (current_class_ref, ansi_assopname (NOP_EXPR), &parmvec, base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error)); release_tree_vector (parmvec); } /* 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 = cp_build_modify_expr (comp, NOP_EXPR, init, tf_warning_or_error); 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); }