[flang] Adding NOTIFY specifier in image selector and add notify type checks (#148810)
This PR adds support for the NOTIFY specifier in the image selector as described in the 2023 standard, and add checks for the NOTIFY_TYPE type.
This commit is contained in:
parent
338fb02c98
commit
87fb7b002d
16 changed files with 118 additions and 6 deletions
|
|
@ -348,6 +348,7 @@ public:
|
|||
READ_FEATURE(TeamValue)
|
||||
READ_FEATURE(ImageSelector)
|
||||
READ_FEATURE(ImageSelectorSpec)
|
||||
READ_FEATURE(ImageSelectorSpec::Notify)
|
||||
READ_FEATURE(ImageSelectorSpec::Stat)
|
||||
READ_FEATURE(ImageSelectorSpec::Team_Number)
|
||||
READ_FEATURE(ImplicitPart)
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public:
|
|||
return Combine(x.base(), x.subscript());
|
||||
}
|
||||
Result operator()(const CoarrayRef &x) const {
|
||||
return Combine(x.base(), x.cosubscript(), x.stat(), x.team());
|
||||
return Combine(x.base(), x.cosubscript(), x.notify(), x.stat(), x.team());
|
||||
}
|
||||
Result operator()(const DataRef &x) const { return visitor_(x.u); }
|
||||
Result operator()(const Substring &x) const {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,9 @@ public:
|
|||
// it's TEAM=.
|
||||
std::optional<Expr<SomeType>> team() const;
|
||||
CoarrayRef &set_team(Expr<SomeType> &&);
|
||||
// When notify() is Expr<Some>, it's NOTIFY=.
|
||||
std::optional<Expr<SomeType>> notify() const;
|
||||
CoarrayRef &set_notify(Expr<SomeType> &&);
|
||||
|
||||
int Rank() const;
|
||||
int Corank() const { return 0; }
|
||||
|
|
@ -272,6 +275,7 @@ public:
|
|||
private:
|
||||
common::CopyableIndirection<DataRef> base_;
|
||||
std::vector<Expr<SubscriptInteger>> cosubscript_;
|
||||
std::optional<common::CopyableIndirection<Expr<SomeType>>> notify_;
|
||||
std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_;
|
||||
std::optional<common::CopyableIndirection<Expr<SomeType>>> team_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -387,6 +387,7 @@ public:
|
|||
NODE(parser, TeamValue)
|
||||
NODE(parser, ImageSelector)
|
||||
NODE(parser, ImageSelectorSpec)
|
||||
NODE(ImageSelectorSpec, Notify)
|
||||
NODE(ImageSelectorSpec, Stat)
|
||||
NODE(ImageSelectorSpec, Team_Number)
|
||||
NODE(parser, ImplicitPart)
|
||||
|
|
|
|||
|
|
@ -1684,13 +1684,15 @@ using Cosubscript = ScalarIntExpr;
|
|||
WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);
|
||||
|
||||
// R926 image-selector-spec ->
|
||||
// NOTIFY = notify-variable |
|
||||
// STAT = stat-variable | TEAM = team-value |
|
||||
// TEAM_NUMBER = scalar-int-expr
|
||||
struct ImageSelectorSpec {
|
||||
WRAPPER_CLASS(Stat, Scalar<Integer<common::Indirection<Variable>>>);
|
||||
WRAPPER_CLASS(Team_Number, ScalarIntExpr);
|
||||
WRAPPER_CLASS(Notify, Scalar<common::Indirection<Variable>>);
|
||||
UNION_CLASS_BOILERPLATE(ImageSelectorSpec);
|
||||
std::variant<Stat, TeamValue, Team_Number> u;
|
||||
std::variant<Notify, Stat, TeamValue, Team_Number> u;
|
||||
};
|
||||
|
||||
// R924 image-selector ->
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ bool IsBindCProcedure(const Scope &);
|
|||
// Returns a pointer to the function's symbol when true, else null
|
||||
const Symbol *IsFunctionResultWithSameNameAsFunction(const Symbol &);
|
||||
bool IsOrContainsEventOrLockComponent(const Symbol &);
|
||||
bool IsOrContainsNotifyComponent(const Symbol &);
|
||||
bool CanBeTypeBoundProc(const Symbol &);
|
||||
// Does a non-PARAMETER symbol have explicit initialization with =value or
|
||||
// =>target in its declaration (but not in a DATA statement)? (Being
|
||||
|
|
@ -652,6 +653,8 @@ using PotentialAndPointerComponentIterator =
|
|||
// dereferenced.
|
||||
PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent(
|
||||
const DerivedTypeSpec &, bool ignoreCoarrays = false);
|
||||
PotentialComponentIterator::const_iterator FindNotifyPotentialComponent(
|
||||
const DerivedTypeSpec &, bool ignoreCoarrays = false);
|
||||
PotentialComponentIterator::const_iterator FindCoarrayPotentialComponent(
|
||||
const DerivedTypeSpec &);
|
||||
PotentialAndPointerComponentIterator::const_iterator
|
||||
|
|
|
|||
|
|
@ -89,6 +89,14 @@ std::optional<Expr<SomeType>> CoarrayRef::team() const {
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<Expr<SomeType>> CoarrayRef::notify() const {
|
||||
if (notify_) {
|
||||
return notify_.value().value();
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
CoarrayRef &CoarrayRef::set_stat(Expr<SomeInteger> &&v) {
|
||||
CHECK(IsVariable(v));
|
||||
stat_.emplace(std::move(v));
|
||||
|
|
@ -100,6 +108,11 @@ CoarrayRef &CoarrayRef::set_team(Expr<SomeType> &&v) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
CoarrayRef &CoarrayRef::set_notify(Expr<SomeType> &&v) {
|
||||
notify_.emplace(std::move(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Symbol &CoarrayRef::GetFirstSymbol() const {
|
||||
return base().GetFirstSymbol();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
x.cosubscript())
|
||||
cosubs -= getHashValue(v);
|
||||
return getHashValue(x.base()) * 97u - cosubs + getHashValue(x.stat()) +
|
||||
257u + getHashValue(x.team());
|
||||
257u + getHashValue(x.team()) + getHashValue(x.notify());
|
||||
}
|
||||
static unsigned getHashValue(const Fortran::evaluate::NamedEntity &x) {
|
||||
if (x.IsSymbol())
|
||||
|
|
@ -341,7 +341,8 @@ public:
|
|||
const Fortran::evaluate::CoarrayRef &y) {
|
||||
return isEqual(x.base(), y.base()) &&
|
||||
isEqual(x.cosubscript(), y.cosubscript()) &&
|
||||
isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team());
|
||||
isEqual(x.stat(), y.stat()) && isEqual(x.team(), y.team()) &&
|
||||
isEqual(x.notify(), y.notify());
|
||||
}
|
||||
static bool isEqual(const Fortran::evaluate::NamedEntity &x,
|
||||
const Fortran::evaluate::NamedEntity &y) {
|
||||
|
|
|
|||
|
|
@ -1212,12 +1212,15 @@ TYPE_CONTEXT_PARSER("image selector"_en_US,
|
|||
|
||||
// R926 image-selector-spec ->
|
||||
// STAT = stat-variable | TEAM = team-value |
|
||||
// TEAM_NUMBER = scalar-int-expr
|
||||
// TEAM_NUMBER = scalar-int-expr |
|
||||
// NOTIFY = notify-variable
|
||||
TYPE_PARSER(construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Stat>(
|
||||
"STAT =" >> scalar(integer(indirect(variable))))) ||
|
||||
construct<ImageSelectorSpec>(construct<TeamValue>("TEAM =" >> teamValue)) ||
|
||||
construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Team_Number>(
|
||||
"TEAM_NUMBER =" >> scalarIntExpr)))
|
||||
"TEAM_NUMBER =" >> scalarIntExpr)) ||
|
||||
construct<ImageSelectorSpec>(construct<ImageSelectorSpec::Notify>(
|
||||
"NOTIFY =" >> scalar(indirect(variable)))))
|
||||
|
||||
// R927 allocate-stmt ->
|
||||
// ALLOCATE ( [type-spec ::] allocation-list [, alloc-opt-list] )
|
||||
|
|
|
|||
|
|
@ -819,6 +819,7 @@ public:
|
|||
Word("TEAM=");
|
||||
}
|
||||
}
|
||||
void Before(const ImageSelectorSpec::Notify &) { Word("NOTIFY="); }
|
||||
void Unparse(const AllocateStmt &x) { // R927
|
||||
Word("ALLOCATE(");
|
||||
Walk(std::get<std::optional<TypeSpec>>(x.t), "::");
|
||||
|
|
|
|||
|
|
@ -855,6 +855,15 @@ void CheckHelper::CheckObjectEntity(
|
|||
messages_.Say(
|
||||
"Variable '%s' with EVENT_TYPE or LOCK_TYPE potential component '%s' must be a coarray"_err_en_US,
|
||||
symbol.name(), component.BuildResultDesignatorName());
|
||||
} else if (IsNotifyType(derived)) { // C1612
|
||||
messages_.Say(
|
||||
"Variable '%s' with NOTIFY_TYPE must be a coarray"_err_en_US,
|
||||
symbol.name());
|
||||
} else if (auto component{FindNotifyPotentialComponent( // C1611
|
||||
*derived, /*ignoreCoarrays=*/true)}) {
|
||||
messages_.Say(
|
||||
"Variable '%s' with NOTIFY_TYPE potential component '%s' must be a coarray"_err_en_US,
|
||||
symbol.name(), component.BuildResultDesignatorName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -873,6 +882,10 @@ void CheckHelper::CheckObjectEntity(
|
|||
messages_.Say(
|
||||
"An INTENT(OUT) dummy argument may not be, or contain, EVENT_TYPE or LOCK_TYPE"_err_en_US);
|
||||
}
|
||||
if (IsOrContainsNotifyComponent(symbol)) { // C1613
|
||||
messages_.Say(
|
||||
"An INTENT(OUT) dummy argument may not be, or contain, NOTIFY_TYPE"_err_en_US);
|
||||
}
|
||||
if (IsAssumedSizeArray(symbol)) { // C834
|
||||
if (type && type->IsPolymorphic()) {
|
||||
messages_.Say(
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ void DumpEvaluateExpr::Show(const evaluate::CoarrayRef &x) {
|
|||
Indent("coarray ref");
|
||||
Show(x.base());
|
||||
Show(x.cosubscript());
|
||||
Show(x.notify());
|
||||
Show(x.stat());
|
||||
Show(x.team());
|
||||
Outdent();
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,19 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
|
|||
std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) {
|
||||
common::visit(
|
||||
common::visitors{
|
||||
[&](const parser::ImageSelectorSpec::Notify &x) {
|
||||
Analyze(x.v);
|
||||
if (const auto *expr{GetExpr(context_, x.v)}) {
|
||||
if (coarrayRef.notify()) {
|
||||
Say("coindexed reference has multiple NOTIFY= specifiers"_err_en_US);
|
||||
} else if (auto dyType{expr->GetType()};
|
||||
dyType && IsNotifyType(GetDerivedTypeSpec(*dyType))) {
|
||||
coarrayRef.set_notify(Expr<SomeType>{*expr});
|
||||
} else {
|
||||
Say("NOTIFY= specifier must have type NOTIFY_TYPE from ISO_FORTRAN_ENV"_err_en_US);
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const parser::ImageSelectorSpec::Stat &x) {
|
||||
Analyze(x.v);
|
||||
if (const auto *expr{GetExpr(context_, x.v)}) {
|
||||
|
|
|
|||
|
|
@ -582,6 +582,18 @@ bool IsOrContainsEventOrLockComponent(const Symbol &original) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsOrContainsNotifyComponent(const Symbol &original) {
|
||||
const Symbol &symbol{ResolveAssociations(original, /*stopAtTypeGuard=*/true)};
|
||||
if (evaluate::IsVariable(symbol)) {
|
||||
if (const DeclTypeSpec *type{symbol.GetType()}) {
|
||||
if (const DerivedTypeSpec *derived{type->AsDerived()}) {
|
||||
return IsNotifyType(derived) || FindNotifyPotentialComponent(*derived);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check this symbol suitable as a type-bound procedure - C769
|
||||
bool CanBeTypeBoundProc(const Symbol &symbol) {
|
||||
if (IsDummy(symbol) || IsProcedurePointer(symbol)) {
|
||||
|
|
@ -1489,6 +1501,32 @@ PotentialComponentIterator::const_iterator FindEventOrLockPotentialComponent(
|
|||
return iter;
|
||||
}
|
||||
|
||||
PotentialComponentIterator::const_iterator FindNotifyPotentialComponent(
|
||||
const DerivedTypeSpec &derived, bool ignoreCoarrays) {
|
||||
PotentialComponentIterator potentials{derived};
|
||||
auto iter{potentials.begin()};
|
||||
for (auto end{potentials.end()}; iter != end; ++iter) {
|
||||
const Symbol &component{*iter};
|
||||
if (const auto *object{component.detailsIf<ObjectEntityDetails>()}) {
|
||||
if (const DeclTypeSpec *type{object->type()}) {
|
||||
if (IsNotifyType(type->AsDerived())) {
|
||||
if (!ignoreCoarrays) {
|
||||
break; // found one
|
||||
}
|
||||
auto path{iter.GetComponentPath()};
|
||||
path.pop_back();
|
||||
if (std::find_if(path.begin(), path.end(), [](const Symbol &sym) {
|
||||
return evaluate::IsCoarray(sym);
|
||||
}) == path.end()) {
|
||||
break; // found one not in a coarray
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
UltimateComponentIterator::const_iterator FindAllocatableUltimateComponent(
|
||||
const DerivedTypeSpec &derived) {
|
||||
UltimateComponentIterator ultimates{derived};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ program main
|
|||
type(event_type) event
|
||||
!ERROR: Variable 'lock' with EVENT_TYPE or LOCK_TYPE must be a coarray
|
||||
type(lock_type) lock
|
||||
!ERROR: Variable 'notify' with NOTIFY_TYPE must be a coarray
|
||||
type(notify_type) notify
|
||||
integer :: local[*] ! ok in main
|
||||
end
|
||||
|
||||
|
|
@ -120,3 +122,18 @@ subroutine s4
|
|||
!ERROR: Subscripts must appear in a coindexed reference when its base is an array
|
||||
print *, ta(1)%a[1]
|
||||
end
|
||||
|
||||
subroutine s5(a, notify, res)
|
||||
use iso_fortran_env
|
||||
type t
|
||||
type(notify_type) :: a
|
||||
end type
|
||||
real, intent(in) :: a[*]
|
||||
type(event_type), intent(in) :: notify[*]
|
||||
!ERROR: An INTENT(OUT) dummy argument may not be, or contain, NOTIFY_TYPE
|
||||
type(notify_type), intent(out) :: res[*]
|
||||
!ERROR: Variable 'bad' with NOTIFY_TYPE potential component '%a' must be a coarray
|
||||
type(t) :: bad
|
||||
!ERROR: NOTIFY= specifier must have type NOTIFY_TYPE from ISO_FORTRAN_ENV
|
||||
print *, a[1, NOTIFY=notify]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ program test_notify_wait
|
|||
implicit none
|
||||
|
||||
! notify_type variables must be coarrays
|
||||
!ERROR: Variable 'non_coarray' with NOTIFY_TYPE must be a coarray
|
||||
type(notify_type) :: non_coarray
|
||||
|
||||
type(notify_type) :: notify_var[*], notify_array(2)[*]
|
||||
|
|
|
|||
Loading…
Reference in a new issue