Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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