Description
I was trying to compile and run the C code generated from integration_tests/test_builtin_str.py
(#1109 ). I found the following issue with the C codegen:
Python:
def f():
s: str
s = "abcde"
c: str
for c in s[::-1]:
print(c)
f()
The generated C code on the main branch is:
void f()
{
int32_t __explicit_iterator;
char * __tmp_assign_for_loop = (char*) malloc(40 * sizeof(char));
char * c = (char*) malloc(40 * sizeof(char));
char * s = (char*) malloc(40 * sizeof(char));
strcpy(s, "abcde");
for (__explicit_iterator=0; __explicit_iterator<=strlen(__tmp_assign_for_loop) - 1; __explicit_iterator++) {
strcpy(c, (char *)memcpy((char *)calloc(2U, sizeof(char)), __tmp_assign_for_loop + __explicit_iterator + 1 - 1, 1U));
printf("%s\n", c);
}
}
The above code is incorrect because we expect __tmp_assign_for_loop
to contain the value of s[::-1]
. This is because of this line in the ASR frontend:
The variable value is ignored in C code generation as seen in the above code __tmp_assign_for_loop
does not contain the correct value and so essentially will give segmentation fault due to memory errors.
I tried to fix that by using the following diff(changed made to wherever variables are declared):
diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h
index b696d8d1e..bed985fc9 100644
--- a/src/libasr/codegen/asr_to_c_cpp.h
+++ b/src/libasr/codegen/asr_to_c_cpp.h
@@ -520,6 +520,17 @@ R"(#include <stdio.h>
}
}
+ for (auto &item : x.m_symtab->get_scope()) {
+ if (ASR::is_a<ASR::Variable_t>(*item.second)) {
+ ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(item.second);
+ if (v->m_value) {
+ self().visit_expr(*v->m_value);
+ std::string name(v->m_name);
+ decl += name + " = " + src + ";\n";
+ }
+ }
+ }
+
And got the following C code:
void f()
{
int32_t __explicit_iterator;
char * __tmp_assign_for_loop = (char*) malloc(40 * sizeof(char));
char * c = (char*) malloc(40 * sizeof(char));
char * s = (char*) malloc(40 * sizeof(char));
__tmp_assign_for_loop = _lfortran_str_slice(s, 0, 0, -1, false, false);
strcpy(s, "abcde");
for (__explicit_iterator=0; __explicit_iterator<=strlen(__tmp_assign_for_loop) - 1; __explicit_iterator++) {
strcpy(c, (char *)memcpy((char *)calloc(2U, sizeof(char)), __tmp_assign_for_loop + __explicit_iterator + 1 - 1, 1U));
printf("%s\n", c);
}
}
That still won't work because __tmp_assign_for_loop
is assigned before s
is assigned. Any suggestions to fix it?