diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index cc1cb5d..52113fa 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -213,4 +213,6 @@ RUN(NAME struct_02.cpp LABELS gcc llvm NOFAST) RUN(NAME struct_03.cpp LABELS gcc llvm NOFAST) RUN(NAME struct_04.cpp LABELS gcc llvm NOFAST) +RUN(NAME pointer_01.cpp LABELS gcc llvm NOFAST) + RUN(NAME function_01.cpp LABELS gcc llvm NOFAST) diff --git a/integration_tests/pointer_01.cpp b/integration_tests/pointer_01.cpp new file mode 100644 index 0000000..2363704 --- /dev/null +++ b/integration_tests/pointer_01.cpp @@ -0,0 +1,49 @@ +#include +#include + +using namespace std::complex_literals; + +#define check(p, t, v) if( *p != v ) { \ + exit(2); \ + } \ + if( t != v ) { \ + exit(2); \ + } \ + +int main() { + + int* p1; + double* p2; + int t1 = 2; + double t2 = 2.0; + std::complex* p3; + std::complex t3 = 2.0 + 1i*3.0; + + p1 = &t1; + p2 = &t2; + p3 = &t3; + *p1 = 1; + *p2 = 4.0; + + std::cout << *p1 << std::endl; + std::cout << t1 << std::endl; + check(p1, t1, 1) + + t1 = *p2 + *p1; + + std::cout << *p1 << std::endl; + std::cout << t1 << std::endl; + check(p1, t1, 5); + + t1 = 8; + + std::cout << *p1 << std::endl; + std::cout << t1 << std::endl; + check(p1, t1, 8); + + *p3 = 2.0 * (*p3); + std::cout << *p3 << std::endl; + std::cout << t3 << std::endl; + check(p3, t3, 4.0 + 1i*6.0); + +} diff --git a/src/lc/clang_ast_to_asr.cpp b/src/lc/clang_ast_to_asr.cpp index 14749e0..ae72ae9 100644 --- a/src/lc/clang_ast_to_asr.cpp +++ b/src/lc/clang_ast_to_asr.cpp @@ -210,6 +210,17 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor(*a_value) ) { + a_value = ASRUtils::EXPR(ASR::make_Var_t(al, a_value->base.loc, + ASR::down_cast(a_value)->m_v)); + return ASR::make_Associate_t(al, a_loc, a_target, a_value); + } + + return ASR::make_Assignment_t(al, a_loc, a_target, a_value, a_overloaded); + } + void construct_program() { // Convert the main function into a program ASR::TranslationUnit_t* tu = (ASR::TranslationUnit_t*)this->tu; @@ -236,7 +247,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor(*ASRUtils::expr_type(left)) && - ASR::is_a(*left)) || - (ASR::is_a(*ASRUtils::expr_type(right)) && - ASR::is_a(*right))); ASR::ttype_t *right_type = ASRUtils::expr_type(right); ASR::ttype_t *left_type = ASRUtils::expr_type(left); left_type = ASRUtils::extract_type(left_type); right_type = ASRUtils::extract_type(right_type); - if( no_cast ) { - int lkind = ASRUtils::extract_kind_from_ttype_t(left_type); - int rkind = ASRUtils::extract_kind_from_ttype_t(right_type); - if( left_type->type != right_type->type || lkind != rkind ) { - throw SemanticError("Casting for mismatching pointer types not supported yet.", - right_type->base.loc); - } - } // Handle presence of logical types in binary operations // by converting them into 32-bit integers. @@ -1886,7 +1885,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorresolve_symbol("__return_var"); ASR::expr_t* return_var = ASRUtils::EXPR(ASR::make_Var_t(al, Lloc(x), return_sym)); TraverseStmt(x->getRetValue()); - tmp = ASR::make_Assignment_t(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr); + tmp = make_Assignment_t_util(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr); current_body->push_back(al, ASRUtils::STMT(tmp.get())); tmp = ASR::make_Return_t(al, Lloc(x)); is_stmt_created = true; @@ -1939,7 +1938,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor(*var) ) { + throw std::runtime_error("Address of operator is only supported for symbols."); + } + + ASR::Var_t* var_t = ASR::down_cast(var); + tmp = ASR::make_AddressOf_t(al, Lloc(x), var_t->m_v, ASRUtils::TYPE( + ASR::make_Pointer_t(al, Lloc(x), ASRUtils::expr_type(var)))); + is_stmt_created = false; + break; + } + case clang::UnaryOperatorKind::UO_Deref: { + if( !ASR::is_a(*var) ) { + throw std::runtime_error("Dereference operator is only supported for symbols."); + } + + ASR::Var_t* var_t = ASR::down_cast(var); + tmp = ASR::make_DereferencePointer_t(al, Lloc(x), var_t->m_v, + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(var))); + is_stmt_created = false; + break; + } default: { - throw std::runtime_error("Only postfix increment and minus are supported so far."); + throw std::runtime_error("Only postfix increment, minus and " + "address of operators are supported so far."); } } return true; diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index f2183e2..9b4e93d 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -311,6 +311,8 @@ expr | DictLen(expr arg, ttype type, expr? value) | Var(symbol v) + | AddressOf(symbol v, ttype type) + | DereferencePointer(symbol v, ttype type) | FunctionParam(int param_number, ttype type, expr? value) --- used in types | ArrayConstant(expr* args, ttype type, arraystorage storage_format) diff --git a/src/libasr/asdl_cpp.py b/src/libasr/asdl_cpp.py index 06b0647..43934f2 100644 --- a/src/libasr/asdl_cpp.py +++ b/src/libasr/asdl_cpp.py @@ -2603,6 +2603,9 @@ def make_visitor(self, name, fields): elif name.endswith("Constant") or name == "IntegerBOZ": self.emit("case ASR::exprType::%s: { return f; }"\ % (name), 2, new_line=False) + elif name == "AddressOf" or name == "DereferencePointer": + self.emit("case ASR::exprType::%s: { return nullptr; }"\ + % (name), 2, new_line=False) else: self.emit("case ASR::exprType::%s: { return ((ASR::%s_t*)f)->m_value; }"\ % (name, name), 2, new_line=False) diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index b4e832f..4219f55 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -210,8 +210,14 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) { static inline ASR::Variable_t* EXPR2VAR(const ASR::expr_t *f) { - return ASR::down_cast(symbol_get_past_external( - ASR::down_cast(f)->m_v)); + if( ASR::is_a(*f) ) { + return ASR::down_cast(symbol_get_past_external( + ASR::down_cast(f)->m_v)); + } else if( ASR::is_a(*f) ) { + return ASR::down_cast(symbol_get_past_external( + ASR::down_cast(f)->m_v)); + } + return nullptr; } static inline ASR::Function_t* EXPR2FUN(const ASR::expr_t *f) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 2803d60..9cee1f9 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -6520,12 +6520,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - void visit_Var(const ASR::Var_t &x) { + template + void visit_SymbolContainingExpr(const T& x) { ASR::Variable_t *v = ASR::down_cast( symbol_get_past_external(x.m_v)); fetch_var(v); } + void visit_Var(const ASR::Var_t& x) { + visit_SymbolContainingExpr(x); + } + + void visit_DereferencePointer(const ASR::DereferencePointer_t& x) { + visit_SymbolContainingExpr(x); + } + inline ASR::ttype_t* extract_ttype_t_from_expr(ASR::expr_t* expr) { return ASRUtils::expr_type(expr); }