Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: error resilient errors #5354

Merged
merged 4 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions src/lfortran/semantics/ast_body_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
const std::unordered_set<std::string> unsupported_args {"iostat", "iomsg", "err", "blank", "access", \
"recl", "fileopt", "action", "position", "pad"};
if (unsupported_args.find(m_arg_str) == unsupported_args.end()) {
throw SemanticError("Invalid argument `" + m_arg_str + "` supplied", x.base.base.loc);
diag.add(diag::Diagnostic("Invalid argument `" + m_arg_str + "` supplied",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
} else {
diag.semantic_warning_label(
"Argument `" + m_arg_str + "` isn't supported yet",
Expand Down Expand Up @@ -412,7 +415,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
this->visit_expr(*kwarg.m_value);
a_err = ASRUtils::EXPR(tmp);
} else {
throw SemanticError("Invalid argument `" + m_arg_str + "` supplied", x.base.base.loc);
diag.add(diag::Diagnostic("Invalid argument `" + m_arg_str + "` supplied",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
}
}
if( a_unit == nullptr ) {
Expand Down Expand Up @@ -476,7 +482,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
this->visit_expr(*kwarg.m_value);
a_err = ASRUtils::EXPR(tmp);
} else {
throw SemanticError("Invalid argument `" + m_arg_str + "` supplied", x.base.base.loc);
diag.add(diag::Diagnostic("Invalid argument `" + m_arg_str + "` supplied",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
}
}
if( a_unit == nullptr ) {
Expand Down Expand Up @@ -810,7 +819,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
if( x.m_kwargs[i].m_value ) {
std::string m_arg_str = to_lower(std::string(x.m_kwargs[i].m_arg));
if (argname2idx.find(m_arg_str) == argname2idx.end()) {
throw SemanticError("Invalid argument `" + m_arg_str + "` supplied", x.base.base.loc);
diag.add(diag::Diagnostic("Invalid argument `" + m_arg_str + "` supplied",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
} else if (args[argname2idx[m_arg_str]]) {
throw SemanticError(m_arg_str + " has already been specified.", x.base.base.loc);
}
Expand Down Expand Up @@ -2684,9 +2696,12 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
throw SemanticError("fptr is not a pointer.", fptr->base.loc);
}
if(!is_fptr_array && shape) {
throw SemanticError("shape argument specified in c_f_pointer "
diag.add(diag::Diagnostic(
"shape argument specified in c_f_pointer "
"even though fptr is not an array.",
shape->base.loc);
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {shape->base.loc})}));
throw SemanticAbort();
}
if(is_fptr_array && !shape) {
throw SemanticError("shape argument not specified in c_f_pointer "
Expand All @@ -2700,10 +2715,13 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
ASRUtils::expr_type(shape),
shape_dims);
if( shape_rank != 1 ) {
throw SemanticError("shape array passed to c_f_pointer "
"must be of rank 1 but given rank is " +
std::to_string(shape_rank),
shape->base.loc);
diag.add(diag::Diagnostic(
"shape array passed to c_f_pointer "
"must be of rank 1 but given rank is " +
std::to_string(shape_rank),
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {shape->base.loc})}));
throw SemanticAbort();
}

ASR::dimension_t* target_dims;
Expand Down Expand Up @@ -3217,7 +3235,11 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
const int offset { (v_expr == nullptr || nopass) ? 0 : 1 };
if (args.size() + offset > f->n_args) {
const Location args_loc { ASRUtils::get_vec_loc(args) };
throw SemanticError("More actual than formal arguments in procedure call", args_loc);
diag.add(diag::Diagnostic(
"More actual than formal arguments in procedure call",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {args_loc})}));
throw SemanticAbort();
}
ASRUtils::set_absent_optional_arguments_to_null(args, f, al, v_expr, nopass);
}
Expand Down
34 changes: 24 additions & 10 deletions src/lfortran/semantics/ast_common_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -5028,7 +5028,11 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
ASRUtils::insert_module_dependency(v, al, current_module_dependencies);
if (args.size() > func->n_args) {
const Location args_loc { ASRUtils::get_vec_loc(args) };
throw SemanticError("More actual than formal arguments in procedure call", args_loc);
diag.add(diag::Diagnostic(
"More actual than formal arguments in procedure call",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {args_loc})}));
throw SemanticAbort();
}
ASRUtils::set_absent_optional_arguments_to_null(args, func, al);
legacy_array_sections_helper(v, args, loc);
Expand Down Expand Up @@ -5710,26 +5714,36 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
handle_intrinsic_node_args(x, args, kwarg_names, 1, 3, "cmplx");
ASR::expr_t *x_ = args[0], *y_ = args[1], *kind = args[2];
if (x_ == nullptr) {
throw SemanticError("The first argument of `cmplx` intrinsic"
" must be present",
x.base.base.loc);
diag.add(diag::Diagnostic("The first argument of `cmplx` intrinsic"
" must be present",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
}
if( ASR::is_a<ASR::Complex_t>(*ASRUtils::expr_type(x_)) ) {
if( y_ != nullptr ) {
throw SemanticError("The first argument of `cmplx` intrinsic"
" is of complex type, the second argument "
"in this case must be absent",
x.base.base.loc);
diag.add(diag::Diagnostic("The first argument of `cmplx` intrinsic"
" is of complex type, the second argument "
"in this case must be absent",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
}
if (!ASR::is_a<ASR::Var_t>(*x_)) {
const ASR::ComplexConstructor_t* complex_expr = ASR::down_cast<ASR::ComplexConstructor_t>(x_);
const ASR::expr_t* real_part_expr = complex_expr->m_re;
const ASR::expr_t* imag_part_expr = complex_expr->m_im;

if (!ASR::is_a<ASR::RealConstant_t>(*real_part_expr)) {
throw SemanticError("Expected a real constant for the real part", x.base.base.loc);
diag.add(diag::Diagnostic("Expected a real constant for the real part",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
} else if (!ASR::is_a<ASR::RealConstant_t>(*imag_part_expr)) {
throw SemanticError("Expected a real constant for the imaginary part", x.base.base.loc);
diag.add(diag::Diagnostic("Expected a real constant for the imaginary part",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("", {x.base.base.loc})}));
throw SemanticAbort();
}
}
return (ASR::asr_t*) x_;
Expand Down
81 changes: 81 additions & 0 deletions tests/errors/continue_compilation_2.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
module Geometry
implicit none

type :: Circle
real :: radius
contains
procedure :: calculateArea
end type Circle

contains

! Type-bound subroutine to calculate the area of a circle
subroutine calculateArea(self, area)
class(Circle), intent(in) :: self
real, intent(out) :: area
area = 3.14 * self%radius**2
end subroutine calculateArea
end module Geometry

program continue_compilation_2
use iso_c_binding, only: c_ptr, c_f_pointer
use Geometry
implicit none


! Variable declarations
type(c_ptr) :: queries_1
integer, pointer :: y_1
type(c_ptr) :: queries_2
integer(2), pointer :: y_2(:)
integer :: shape(2, 2)
integer, parameter :: x = 2
type(Circle) :: myCircle
real :: circleArea
complex :: a


! c_f_pointer_01
call c_f_pointer(queries_1, y_1, [2])
print *, "First error skipped"


! c_f_pointer_02
call c_f_pointer(queries_2, y_2, shape)
print *, "Second error skipped"


! assign_01
x = 1
print *, x
print *, "Third error skipped"


! class_procedure_extra_args
myCircle%radius = 5.0
call myCircle%calculateArea(circleArea, 12)
print *, "Fourth error skipped"


! close_invalid_kwarg1
CLOSE(end=200)
print *, "Fifth error skipped"


! cmplx_01
a = cmplx(y = 2)
print *, a
print *, "Sixth error skipped"


! cmplx_02
print*, cmplx((real(1, kind=4), 0.00000000), kind=8)
print *, "Seventh error skipped"


! cmplx_03
print*, cmplx((1.00000000, real(0, kind=4)), kind=8)
print *, "Eighth error skipped"
Comment on lines +60 to +78
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's shorten these to just:

    CLOSE(end=200)
    a = cmplx(y = 2)
    print*, cmplx((real(1, kind=4), 0.00000000), kind=8)
    print*, cmplx((1.00000000, real(0, kind=4)), kind=8)

Seems a lot shorter and removes noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will apply this changes here : #5374



end program
13 changes: 13 additions & 0 deletions tests/reference/run-continue_compilation_2-3499257.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"basename": "run-continue_compilation_2-3499257",
"cmd": "lfortran --continue-compilation --no-color {infile}",
"infile": "tests/errors/continue_compilation_2.f90",
"infile_hash": "b71a5a257c1ab04d40c581edd5f801a9e20f7f2e42d57a6330ef8692",
"outfile": null,
"outfile_hash": null,
"stdout": "run-continue_compilation_2-3499257.stdout",
"stdout_hash": "cee82c23e3fc58c9e6573690402e361306f64bbb9d297e25e6143900",
"stderr": "run-continue_compilation_2-3499257.stderr",
"stderr_hash": "e60cbe29bc8eba0880d486d80cb97f8d7bafc6bbb5379f5234453cca",
"returncode": 1
}
38 changes: 38 additions & 0 deletions tests/reference/run-continue_compilation_2-3499257.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
semantic error: shape argument specified in c_f_pointer even though fptr is not an array.
--> tests/errors/continue_compilation_2.f90:39:38
|
39 | call c_f_pointer(queries_1, y_1, [2])
| ^^^

semantic error: shape array passed to c_f_pointer must be of rank 1 but given rank is 2
--> tests/errors/continue_compilation_2.f90:44:38
|
44 | call c_f_pointer(queries_2, y_2, shape)
| ^^^^^

semantic error: Cannot assign to a constant variable
--> tests/errors/continue_compilation_2.f90:49:5
|
49 | x = 1
| ^^^^^ assignment here
|
32 | integer, parameter :: x = 2
| ~~~~~ declared as constant

semantic error: More actual than formal arguments in procedure call
--> tests/errors/continue_compilation_2.f90:56:33
|
56 | call myCircle%calculateArea(circleArea, 12)
| ^^^^^^^^^^^^^^

semantic error: Invalid argument `end` supplied
--> tests/errors/continue_compilation_2.f90:61:5
|
61 | CLOSE(end=200)
| ^^^^^^^^^^^^^^

semantic error: The first argument of `cmplx` intrinsic must be present
--> tests/errors/continue_compilation_2.f90:66:9
|
66 | a = cmplx(y = 2)
| ^^^^^^^^^^^^
10 changes: 10 additions & 0 deletions tests/reference/run-continue_compilation_2-3499257.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
First error skipped
Second error skipped
2
Third error skipped
Fourth error skipped
Fifth error skipped
2.00000000e+00 0.00000000e+00
Sixth error skipped
Seventh error skipped
Eighth error skipped
4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3004,6 +3004,10 @@ asr = true
filename = "errors/c_f_pointer_02.f90"
asr = true

[[test]]
filename = "errors/continue_compilation_2.f90"
continue_compilation = true

[[test]]
filename = "../integration_tests/rewind_inquire_flush.f90"
asr = true
Expand Down
Loading