diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -10,6 +10,7 @@ #include "flang/Common/Fortran.h" #include "flang/Common/enum-set.h" #include "flang/Common/idioms.h" +#include "flang/Evaluate/check-expression.h" #include "flang/Evaluate/common.h" #include "flang/Evaluate/expression.h" #include "flang/Evaluate/fold.h" @@ -82,6 +83,7 @@ kindArg, // this argument is KIND= effectiveKind, // for function results: "kindArg" value, possibly defaulted dimArg, // this argument is DIM= + positiveInt, // integer arguments that must be positive likeMultiply, // for DOT_PRODUCT and MATMUL subscript, // address-sized integer size, // default KIND= for SIZE(), UBOUND, &c. @@ -128,6 +130,7 @@ static constexpr TypePattern AnyIntrinsic{IntrinsicType, KindCode::any}; static constexpr TypePattern ExtensibleDerived{DerivedType, KindCode::any}; static constexpr TypePattern AnyData{AnyType, KindCode::any}; +static constexpr TypePattern PositiveInt{IntType, KindCode::positiveInt}; // Type is irrelevant, but not BOZ (for PRESENT(), OPTIONAL(), &c.) static constexpr TypePattern Addressable{AnyType, KindCode::addressable}; @@ -485,7 +488,7 @@ {"ichar", {{"c", AnyChar}, DefaultingKIND}, KINDInt}, {"ieor", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt}, {"ieor", {{"i", BOZ}, {"j", SameInt}}, SameInt}, - {"image_status", {{"image", SameInt}, OptionalTEAM}, DefaultInt}, + {"image_status", {{"image", PositiveInt}, OptionalTEAM}, DefaultInt}, {"index", {{"string", SameChar}, {"substring", SameChar}, {"back", AnyLogical, Rank::elemental, Optionality::optional}, @@ -498,7 +501,7 @@ {"ishft", {{"i", SameInt}, {"shift", AnyInt}}, SameInt}, {"ishftc", {{"i", SameInt}, {"shift", AnyInt}, - {"size", AnyInt, Rank::elemental, Optionality::optional}}, + {"size", PositiveInt, Rank::elemental, Optionality::optional}}, SameInt}, {"isnan", {{"a", AnyFloating}}, DefaultLogical}, {"is_contiguous", {{"array", Addressable, Rank::anyOrAssumedRank}}, @@ -1460,6 +1463,22 @@ "for intrinsic '%s'", d.keyword, name); break; + case KindCode::positiveInt: + CHECK(type->category() == TypeCategory::Integer); + if (const auto &expr{arg->UnwrapExpr()}) { + if (IsConstantExpr(*expr)) { + if (auto val{ToInt64(*expr)}) { + if (val <= 0) { + messages.Say(arg->sourceLocation(), + "'%s=' argument for intrinsic '%s' must be a positive value"_err_en_US, + d.keyword, name); + return std::nullopt; + } + } + } + } + argOk = true; + break; case KindCode::addressable: case KindCode::nullPointerType: argOk = true; diff --git a/flang/test/Semantics/image_status.f90 b/flang/test/Semantics/image_status.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/image_status.f90 @@ -0,0 +1,95 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Check for semantic errors in image_status(), as defined in +! section 16.9.98 of the Fortran 2018 standard + +program test_image_status + use iso_fortran_env, only : team_type, stat_failed_image, stat_stopped_image + implicit none + + type(team_type) home, league(2) + integer n, image_num, array(5), coindexed[*], non_array_result, array_2d(10, 10), not_team_type + integer, parameter :: constant_integer = 2 + integer, allocatable :: result_array(:), result_array_2d(:,:), wrong_rank_result(:) + logical wrong_arg_type_logical + real wrong_arg_type_real + character wrong_result_type + + !___ standard-conforming statements ___ + n = image_status(1) + n = image_status(constant_integer) + n = image_status(image_num) + n = image_status(array(1)) + n = image_status(coindexed[1]) + n = image_status(image=1) + result_array = image_status(array) + result_array_2d = image_status(array_2d) + + n = image_status(2, home) + n = image_status(2, league(1)) + n = image_status(image=2, team=home) + n = image_status(team=home, image=2) + + if (image_status(1) .eq. stat_failed_image .or. image_status(1) .eq. stat_stopped_image) then + error stop + else if (image_status(1) .eq. 0) then + continue + end if + + !___ non-conforming statements ___ + + !ERROR: 'image=' argument for intrinsic 'image_status' must be a positive value + n = image_status(-1) + + !ERROR: 'image=' argument for intrinsic 'image_status' must be a positive value + n = image_status(0) + + !ERROR: 'team=' argument has unacceptable rank 1 + n = image_status(1, team=league) + + !ERROR: Actual argument for 'image=' has bad type 'REAL(4)' + n = image_status(3.4) + + !ERROR: Actual argument for 'image=' has bad type 'LOGICAL(4)' + n = image_status(wrong_arg_type_logical) + + !ERROR: Actual argument for 'image=' has bad type 'REAL(4)' + n = image_status(wrong_arg_type_real) + + !ERROR: Actual argument for 'team=' has bad type 'INTEGER(4)' + n = image_status(1, not_team_type) + + !ERROR: Actual argument for 'team=' has bad type 'INTEGER(4)' + n = image_status(1, 1) + + ! keyword argument with incorrect type + !ERROR: Actual argument for 'image=' has bad type 'REAL(4)' + n = image_status(image=3.4) + + ! keyword argument with incorrect type + !ERROR: Actual argument for 'team=' has bad type 'INTEGER(4)' + n = image_status(1, team=1) + + !ERROR: too many actual arguments for intrinsic 'image_status' + n = image_status(1, home, 2) + + !ERROR: repeated keyword argument to intrinsic 'image_status' + n = image_status(image=1, image=2) + + ! incorrect keyword argument name but valid type + !ERROR: unknown keyword argument to intrinsic 'image_status' + n = image_status(images=1) + + ! incorrect keyword argument name but valid type + !ERROR: unknown keyword argument to intrinsic 'image_status' + n = image_status(1, my_team=home) + + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4) + non_array_result = image_status(image=array) + + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches rank 1 array of INTEGER(4) and rank 2 array of INTEGER(4) + wrong_rank_result = image_status(array_2d) + + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types CHARACTER(KIND=1) and INTEGER(4) + wrong_result_type = image_status(1) + +end program test_image_status diff --git a/flang/test/Semantics/ishftc.f90 b/flang/test/Semantics/ishftc.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/ishftc.f90 @@ -0,0 +1,15 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Check for semantic errors in ishftc() function calls + +program test_ishftc + implicit none + + integer :: n + + n = ishftc(3, 2, 3) + !ERROR: 'size=' argument for intrinsic 'ishftc' must be a positive value + n = ishftc(3, 2, -3) + !ERROR: 'size=' argument for intrinsic 'ishftc' must be a positive value + n = ishftc(3, 2, 0) + +end program test_ishftc