diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 3d58ab8a1e..0e85f2d872 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -605,6 +605,7 @@ RUN(NAME structs_29 LABELS cpython llvm) RUN(NAME structs_30 LABELS cpython llvm c) RUN(NAME structs_31 LABELS cpython llvm c) RUN(NAME structs_32 LABELS cpython llvm c) +RUN(NAME structs_33 LABELS cpython llvm c) RUN(NAME symbolics_01 LABELS cpython_sym c_sym) RUN(NAME symbolics_02 LABELS cpython_sym c_sym) diff --git a/integration_tests/structs_33.py b/integration_tests/structs_33.py new file mode 100644 index 0000000000..c8f02cb8e6 --- /dev/null +++ b/integration_tests/structs_33.py @@ -0,0 +1,24 @@ +from lpython import packed, dataclass, i32, ccallback, CPtr, ccall + +# test issue 2125 + +@packed +@dataclass +class inner_struct: + inner_field: i32 = 0 + + +@packed +@dataclass +class outer_struct: + inner_s : inner_struct = inner_struct() + + +def check() -> None: + outer_struct_instance : outer_struct = outer_struct(inner_struct(5)) + outer_struct_instance2 : outer_struct = outer_struct_instance + inner_struct_instance : inner_struct = outer_struct_instance2.inner_s + assert inner_struct_instance.inner_field == 5 + + +check() diff --git a/src/libasr/codegen/c_utils.h b/src/libasr/codegen/c_utils.h index 84dbed81e2..4ac7fb7e94 100644 --- a/src/libasr/codegen/c_utils.h +++ b/src/libasr/codegen/c_utils.h @@ -842,14 +842,14 @@ class CCPPDSUtils { + struct_type_str + "* src, " + struct_type_str + "* dest)"; func_decls += "inline " + signature + ";\n"; - generated_code += indent + signature + " {\n"; + std::string tmp_generated = indent + signature + " {\n"; for(size_t i=0; i < struct_type_t->n_members; i++) { std::string mem_name = std::string(struct_type_t->m_members[i]); ASR::symbol_t* member = struct_type_t->m_symtab->get_symbol(mem_name); ASR::ttype_t* member_type_asr = ASRUtils::symbol_type(member); if( CUtils::is_non_primitive_DT(member_type_asr) || ASR::is_a(*member_type_asr) ) { - generated_code += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")", + tmp_generated += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")", "&(dest->" + mem_name + ")") + ";\n"; } else if( ASRUtils::is_array(member_type_asr) ) { ASR::dimension_t* m_dims = nullptr; @@ -857,17 +857,18 @@ class CCPPDSUtils { if( ASRUtils::is_fixed_size_array(m_dims, n_dims) ) { std::string array_size = std::to_string(ASRUtils::get_fixed_size_of_array(m_dims, n_dims)); array_size += "*sizeof(" + CUtils::get_c_type_from_ttype_t(member_type_asr) + ")"; - generated_code += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name + + tmp_generated += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name + ", " + array_size + ");\n"; } else { - generated_code += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name, + tmp_generated += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name, "dest->" + mem_name) + ";\n"; } } else { - generated_code += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n"; + tmp_generated += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n"; } } - generated_code += indent + "}\n\n"; + tmp_generated += indent + "}\n\n"; + generated_code += tmp_generated; } void list_deepcopy(std::string list_struct_type, diff --git a/tests/reference/c-structs_33-4a3339f.json b/tests/reference/c-structs_33-4a3339f.json new file mode 100644 index 0000000000..73a432ee7b --- /dev/null +++ b/tests/reference/c-structs_33-4a3339f.json @@ -0,0 +1,13 @@ +{ + "basename": "c-structs_33-4a3339f", + "cmd": "lpython --no-color --show-c {infile}", + "infile": "tests/../integration_tests/structs_33.py", + "infile_hash": "15fdcb483c864b6322ebcf6c495e635bbe917f1d8b407ccf4dc3e2ee", + "outfile": null, + "outfile_hash": null, + "stdout": "c-structs_33-4a3339f.stdout", + "stdout_hash": "425a22068f547e15ba187e2974220f28f0af3a70305b67cfd4a6a655", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/c-structs_33-4a3339f.stdout b/tests/reference/c-structs_33-4a3339f.stdout new file mode 100644 index 0000000000..5aaf931d35 --- /dev/null +++ b/tests/reference/c-structs_33-4a3339f.stdout @@ -0,0 +1,61 @@ +#include + +#include +#include +#include +#include +#include + +struct dimension_descriptor +{ + int32_t lower_bound, length; +}; +struct __attribute__((packed)) inner_struct { + int32_t inner_field; +}; + +struct __attribute__((packed)) outer_struct { + struct inner_struct inner_s; +}; + + +inline void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest); +inline void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest); + + +// Implementations +void check() +{ + struct inner_struct inner_struct_instance_value; + struct inner_struct* inner_struct_instance = &inner_struct_instance_value; + struct outer_struct outer_struct_instance_value; + struct outer_struct* outer_struct_instance = &outer_struct_instance_value; + struct outer_struct outer_struct_instance2_value; + struct outer_struct* outer_struct_instance2 = &outer_struct_instance2_value; + outer_struct_instance->inner_s.inner_field = 5; + struct_deepcopy_outer_struct(outer_struct_instance, outer_struct_instance2); + struct_deepcopy_inner_struct(&outer_struct_instance2->inner_s, inner_struct_instance); + ASSERT(inner_struct_instance->inner_field == 5); +} + +void _lpython_main_program() +{ + check(); +} + +int main(int argc, char* argv[]) +{ + _lpython_set_argv(argc, argv); + _lpython_main_program(); + return 0; +} + +void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest) { + dest->inner_field = src->inner_field; +} + +void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest) { + struct_deepcopy_inner_struct(&(src->inner_s), &(dest->inner_s));; +} + + diff --git a/tests/tests.toml b/tests/tests.toml index 05734f688c..13ac8257cd 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -337,6 +337,10 @@ asr = true filename = "../integration_tests/structs_05.py" asr = true +[[test]] +filename = "../integration_tests/structs_33.py" +c = true + [[test]] filename = "../integration_tests/callback_01.py" asr = true