diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 64048b6c88..e88b5f52d0 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -309,6 +309,7 @@ RUN(NAME structs_07 LABELS llvm c RUN(NAME structs_08 LABELS cpython llvm c) RUN(NAME structs_09 LABELS cpython llvm c) RUN(NAME structs_10 LABELS cpython llvm c) +RUN(NAME structs_11 LABELS cpython llvm c) RUN(NAME sizeof_01 LABELS llvm c EXTRAFILES sizeof_01b.c) RUN(NAME enum_01 LABELS cpython llvm c) diff --git a/integration_tests/structs_11.py b/integration_tests/structs_11.py new file mode 100644 index 0000000000..4fc71e595e --- /dev/null +++ b/integration_tests/structs_11.py @@ -0,0 +1,18 @@ +from ltypes import i32, f64, dataclass + +@dataclass +class A: + x: i32 + y: f64 + +def f(x_: i32, y_: f64) -> A: + a_struct: A = A(x_, y_) + return a_struct + +def test_struct_return(): + b: A = f(0, 1.0) + print(b.x, b.y) + assert b.x == 0 + assert b.y == 1.0 + +test_struct_return() diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index c433ba6178..8fa1c1ac67 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -354,6 +354,9 @@ R"(#include ASR::Pointer_t* ptr_type = ASR::down_cast(return_var->m_type); std::string pointer_type_str = CUtils::get_c_type_from_ttype_t(ptr_type->m_type); sub = pointer_type_str + "*"; + } else if (ASR::is_a(*return_var->m_type)) { + std::string struct_type_str = CUtils::get_c_type_from_ttype_t(return_var->m_type); + sub = struct_type_str + " "; } else { throw CodeGenError("Return type not supported in function '" + std::string(x.m_name) + @@ -443,8 +446,15 @@ R"(#include for (auto &item : x.m_symtab->get_scope()) { if (ASR::is_a(*item.second)) { ASR::Variable_t *v = ASR::down_cast(item.second); - if (v->m_intent == LFortran::ASRUtils::intent_local || v->m_intent == LFortran::ASRUtils::intent_return_var) { - decl += indent + self().convert_variable_decl(*v); + if (v->m_intent == LFortran::ASRUtils::intent_local || + v->m_intent == LFortran::ASRUtils::intent_return_var) { + if (is_c) { + decl += indent + self().convert_variable_decl(*v, true, + !(ASR::is_a(*v->m_type) && + std::string(v->m_name) == "_lpython_return_variable"), true); + } else { + decl += indent + self().convert_variable_decl(*v); + } if( !ASR::is_a(*v->m_type) || v->m_intent == ASRUtils::intent_return_var ) { decl += ";\n"; @@ -678,6 +688,8 @@ R"(#include value = "*" + value; } else if (ASR::is_a(*x.m_value)) { value = "&" + value; + } else if (ASR::is_a(*x.m_value)) { + target = "*" + target; } } if( !from_std_vector_helper.empty() ) { diff --git a/src/libasr/codegen/asr_to_cpp.cpp b/src/libasr/codegen/asr_to_cpp.cpp index ea7a005d20..90bc9ee492 100644 --- a/src/libasr/codegen/asr_to_cpp.cpp +++ b/src/libasr/codegen/asr_to_cpp.cpp @@ -210,8 +210,11 @@ class ASRToCPPVisitor : public BaseCCPPVisitor } std::string convert_variable_decl(const ASR::Variable_t &v, bool use_static=true, - bool use_templates_for_arrays=false) + bool use_templates_for_arrays=false, bool _=false) { + if( _ ) { + + } std::string sub; bool use_ref = (v.m_intent == LFortran::ASRUtils::intent_out || diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 377185f98f..2b2a866f6c 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -3346,9 +3346,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0))->getPointerTo(); break; } - case (ASR::ttypeType::Struct) : - throw CodeGenError("Struct return type not implemented yet"); + case (ASR::ttypeType::Struct) : { + return_type = get_type_from_ttype_t_util(return_var_type0); break; + } case (ASR::ttypeType::Tuple) : { ASR::Tuple_t* asr_tuple = ASR::down_cast(return_var_type0); std::string type_code = ASRUtils::get_type_code(asr_tuple->m_type,