Skip to content

Commit c6628be

Browse files
authored
Merge pull request #2137 from Smit-create/i-2125
C: Fix struct deepcopy
2 parents 230c97f + 054b93f commit c6628be

File tree

6 files changed

+110
-6
lines changed

6 files changed

+110
-6
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ RUN(NAME structs_29 LABELS cpython llvm)
605605
RUN(NAME structs_30 LABELS cpython llvm c)
606606
RUN(NAME structs_31 LABELS cpython llvm c)
607607
RUN(NAME structs_32 LABELS cpython llvm c)
608+
RUN(NAME structs_33 LABELS cpython llvm c)
608609

609610
RUN(NAME symbolics_01 LABELS cpython_sym c_sym)
610611
RUN(NAME symbolics_02 LABELS cpython_sym c_sym)

integration_tests/structs_33.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from lpython import packed, dataclass, i32, ccallback, CPtr, ccall
2+
3+
# test issue 2125
4+
5+
@packed
6+
@dataclass
7+
class inner_struct:
8+
inner_field: i32 = 0
9+
10+
11+
@packed
12+
@dataclass
13+
class outer_struct:
14+
inner_s : inner_struct = inner_struct()
15+
16+
17+
def check() -> None:
18+
outer_struct_instance : outer_struct = outer_struct(inner_struct(5))
19+
outer_struct_instance2 : outer_struct = outer_struct_instance
20+
inner_struct_instance : inner_struct = outer_struct_instance2.inner_s
21+
assert inner_struct_instance.inner_field == 5
22+
23+
24+
check()

src/libasr/codegen/c_utils.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -842,32 +842,33 @@ class CCPPDSUtils {
842842
+ struct_type_str + "* src, "
843843
+ struct_type_str + "* dest)";
844844
func_decls += "inline " + signature + ";\n";
845-
generated_code += indent + signature + " {\n";
845+
std::string tmp_generated = indent + signature + " {\n";
846846
for(size_t i=0; i < struct_type_t->n_members; i++) {
847847
std::string mem_name = std::string(struct_type_t->m_members[i]);
848848
ASR::symbol_t* member = struct_type_t->m_symtab->get_symbol(mem_name);
849849
ASR::ttype_t* member_type_asr = ASRUtils::symbol_type(member);
850850
if( CUtils::is_non_primitive_DT(member_type_asr) ||
851851
ASR::is_a<ASR::Character_t>(*member_type_asr) ) {
852-
generated_code += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")",
852+
tmp_generated += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")",
853853
"&(dest->" + mem_name + ")") + ";\n";
854854
} else if( ASRUtils::is_array(member_type_asr) ) {
855855
ASR::dimension_t* m_dims = nullptr;
856856
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(member_type_asr, m_dims);
857857
if( ASRUtils::is_fixed_size_array(m_dims, n_dims) ) {
858858
std::string array_size = std::to_string(ASRUtils::get_fixed_size_of_array(m_dims, n_dims));
859859
array_size += "*sizeof(" + CUtils::get_c_type_from_ttype_t(member_type_asr) + ")";
860-
generated_code += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name +
860+
tmp_generated += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name +
861861
", " + array_size + ");\n";
862862
} else {
863-
generated_code += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name,
863+
tmp_generated += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name,
864864
"dest->" + mem_name) + ";\n";
865865
}
866866
} else {
867-
generated_code += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n";
867+
tmp_generated += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n";
868868
}
869869
}
870-
generated_code += indent + "}\n\n";
870+
tmp_generated += indent + "}\n\n";
871+
generated_code += tmp_generated;
871872
}
872873

873874
void list_deepcopy(std::string list_struct_type,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "c-structs_33-4a3339f",
3+
"cmd": "lpython --no-color --show-c {infile}",
4+
"infile": "tests/../integration_tests/structs_33.py",
5+
"infile_hash": "15fdcb483c864b6322ebcf6c495e635bbe917f1d8b407ccf4dc3e2ee",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": "c-structs_33-4a3339f.stdout",
9+
"stdout_hash": "425a22068f547e15ba187e2974220f28f0af3a70305b67cfd4a6a655",
10+
"stderr": null,
11+
"stderr_hash": null,
12+
"returncode": 0
13+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <inttypes.h>
2+
3+
#include <stdlib.h>
4+
#include <stdbool.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
#include <lfortran_intrinsics.h>
8+
9+
struct dimension_descriptor
10+
{
11+
int32_t lower_bound, length;
12+
};
13+
struct __attribute__((packed)) inner_struct {
14+
int32_t inner_field;
15+
};
16+
17+
struct __attribute__((packed)) outer_struct {
18+
struct inner_struct inner_s;
19+
};
20+
21+
22+
inline void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest);
23+
inline void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest);
24+
25+
26+
// Implementations
27+
void check()
28+
{
29+
struct inner_struct inner_struct_instance_value;
30+
struct inner_struct* inner_struct_instance = &inner_struct_instance_value;
31+
struct outer_struct outer_struct_instance_value;
32+
struct outer_struct* outer_struct_instance = &outer_struct_instance_value;
33+
struct outer_struct outer_struct_instance2_value;
34+
struct outer_struct* outer_struct_instance2 = &outer_struct_instance2_value;
35+
outer_struct_instance->inner_s.inner_field = 5;
36+
struct_deepcopy_outer_struct(outer_struct_instance, outer_struct_instance2);
37+
struct_deepcopy_inner_struct(&outer_struct_instance2->inner_s, inner_struct_instance);
38+
ASSERT(inner_struct_instance->inner_field == 5);
39+
}
40+
41+
void _lpython_main_program()
42+
{
43+
check();
44+
}
45+
46+
int main(int argc, char* argv[])
47+
{
48+
_lpython_set_argv(argc, argv);
49+
_lpython_main_program();
50+
return 0;
51+
}
52+
53+
void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest) {
54+
dest->inner_field = src->inner_field;
55+
}
56+
57+
void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest) {
58+
struct_deepcopy_inner_struct(&(src->inner_s), &(dest->inner_s));;
59+
}
60+
61+

tests/tests.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,10 @@ asr = true
337337
filename = "../integration_tests/structs_05.py"
338338
asr = true
339339

340+
[[test]]
341+
filename = "../integration_tests/structs_33.py"
342+
c = true
343+
340344
[[test]]
341345
filename = "../integration_tests/callback_01.py"
342346
asr = true

0 commit comments

Comments
 (0)