Skip to content

[flang] Adding NOTIFY specifier in image selector and add notify type checks #148810

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions flang/examples/FeatureList/FeatureList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ struct NodeVisitor {
READ_FEATURE(ImageSelectorSpec)
READ_FEATURE(ImageSelectorSpec::Stat)
READ_FEATURE(ImageSelectorSpec::Team_Number)
READ_FEATURE(ImageSelectorSpec::Notify)
READ_FEATURE(ImplicitPart)
READ_FEATURE(ImplicitPartStmt)
READ_FEATURE(ImplicitSpec)
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Evaluate/traverse.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class Traverse {
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.stat(), x.team(), x.notify());
}
Result operator()(const DataRef &x) const { return visitor_(x.u); }
Result operator()(const Substring &x) const {
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Evaluate/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ class CoarrayRef {
// 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; }
Expand All @@ -274,6 +277,7 @@ class CoarrayRef {
std::vector<Expr<SubscriptInteger>> cosubscript_;
std::optional<common::CopyableIndirection<Expr<SomeInteger>>> stat_;
std::optional<common::CopyableIndirection<Expr<SomeType>>> team_;
std::optional<common::CopyableIndirection<Expr<SomeType>>> notify_;
};

// R911 data-ref is defined syntactically as a series of part-refs, which
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ class ParseTreeDumper {
NODE(parser, ImageSelectorSpec)
NODE(ImageSelectorSpec, Stat)
NODE(ImageSelectorSpec, Team_Number)
NODE(ImageSelectorSpec, Notify)
NODE(parser, ImplicitPart)
NODE(parser, ImplicitPartStmt)
NODE(parser, ImplicitSpec)
Expand Down
6 changes: 4 additions & 2 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1682,12 +1682,14 @@ WRAPPER_CLASS(TeamValue, Scalar<common::Indirection<Expr>>);

// R926 image-selector-spec ->
// STAT = stat-variable | TEAM = team-value |
// TEAM_NUMBER = scalar-int-expr
// TEAM_NUMBER = scalar-int-expr |
// NOTIFY = notify-variable
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<Stat, TeamValue, Team_Number, Notify> u;
};

// R924 image-selector ->
Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Semantics/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -642,6 +643,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
Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Evaluate/variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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();
}
Expand Down
5 changes: 3 additions & 2 deletions flang/lib/Lower/Support/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class HashEvaluateExpr {
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())
Expand Down Expand Up @@ -341,7 +341,8 @@ class IsEqualEvaluateExpr {
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) {
Expand Down
7 changes: 5 additions & 2 deletions flang/lib/Parser/Fortran-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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] )
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ class UnparseVisitor {
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), "::");
Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,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());
}
}
}
Expand All @@ -780,6 +789,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(
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Semantics/dump-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void DumpEvaluateExpr::Show(const evaluate::CoarrayRef &x) {
Show(x.cosubscript());
Show(x.stat());
Show(x.team());
Show(x.notify());
Outdent();
}

Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Semantics/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,19 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
coarrayRef.set_team(Expr<SomeType>{*expr});
}
}
},
[&](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);
}
}
}},
imageSelSpec.u);
}
Expand Down
38 changes: 38 additions & 0 deletions flang/lib/Semantics/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -1464,6 +1476,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};
Expand Down
17 changes: 17 additions & 0 deletions flang/test/Semantics/coarrays02.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
1 change: 1 addition & 0 deletions flang/test/Semantics/notifywait03.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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)[*]
Expand Down
Loading