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

[flang] Do not traverse selectors in FindImpureCall and HasVectorSubscript #84041

Merged
merged 1 commit into from
Mar 6, 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
24 changes: 15 additions & 9 deletions flang/include/flang/Evaluate/traverse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
#include <type_traits>

namespace Fortran::evaluate {
template <typename Visitor, typename Result> class Traverse {
template <typename Visitor, typename Result,
bool TraverseAssocEntityDetails = true>
class Traverse {
public:
explicit Traverse(Visitor &v) : visitor_{v} {}

Expand Down Expand Up @@ -108,12 +110,13 @@ template <typename Visitor, typename Result> class Traverse {
}
Result operator()(const Symbol &symbol) const {
const Symbol &ultimate{symbol.GetUltimate()};
if (const auto *assoc{
ultimate.detailsIf<semantics::AssocEntityDetails>()}) {
return visitor_(assoc->expr());
} else {
return visitor_.Default();
if constexpr (TraverseAssocEntityDetails) {
if (const auto *assoc{
ultimate.detailsIf<semantics::AssocEntityDetails>()}) {
return visitor_(assoc->expr());
}
}
return visitor_.Default();
}
Result operator()(const StaticDataObject &) const {
return visitor_.Default();
Expand Down Expand Up @@ -284,7 +287,8 @@ template <typename Visitor, typename Result> class Traverse {
// For validity checks across an expression: if any operator() result is
// false, so is the overall result.
template <typename Visitor, bool DefaultValue,
typename Base = Traverse<Visitor, bool>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, bool, TraverseAssocEntityDetails>>
struct AllTraverse : public Base {
explicit AllTraverse(Visitor &v) : Base{v} {}
using Base::operator();
Expand All @@ -296,7 +300,8 @@ struct AllTraverse : public Base {
// is truthful is the final result. Works for Booleans, pointers,
// and std::optional<>.
template <typename Visitor, typename Result = bool,
typename Base = Traverse<Visitor, Result>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, Result, TraverseAssocEntityDetails>>
class AnyTraverse : public Base {
public:
explicit AnyTraverse(Visitor &v) : Base{v} {}
Expand All @@ -315,7 +320,8 @@ class AnyTraverse : public Base {
};

template <typename Visitor, typename Set,
typename Base = Traverse<Visitor, Set>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, Set, TraverseAssocEntityDetails>>
struct SetTraverse : public Base {
explicit SetTraverse(Visitor &v) : Base{v} {}
using Base::operator();
Expand Down
11 changes: 7 additions & 4 deletions flang/lib/Evaluate/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,10 @@ template semantics::UnorderedSymbolSet CollectSymbols(
const Expr<SubscriptInteger> &);

// HasVectorSubscript()
struct HasVectorSubscriptHelper : public AnyTraverse<HasVectorSubscriptHelper> {
using Base = AnyTraverse<HasVectorSubscriptHelper>;
struct HasVectorSubscriptHelper
: public AnyTraverse<HasVectorSubscriptHelper, bool,
/*TraverseAssocEntityDetails=*/false> {
using Base = AnyTraverse<HasVectorSubscriptHelper, bool, false>;
HasVectorSubscriptHelper() : Base{*this} {}
using Base::operator();
bool operator()(const Subscript &ss) const {
Expand Down Expand Up @@ -1045,9 +1047,10 @@ parser::Message *AttachDeclaration(
}

class FindImpureCallHelper
: public AnyTraverse<FindImpureCallHelper, std::optional<std::string>> {
: public AnyTraverse<FindImpureCallHelper, std::optional<std::string>,
/*TraverseAssocEntityDetails=*/false> {
using Result = std::optional<std::string>;
using Base = AnyTraverse<FindImpureCallHelper, Result>;
using Base = AnyTraverse<FindImpureCallHelper, Result, false>;

public:
explicit FindImpureCallHelper(FoldingContext &c) : Base{*this}, context_{c} {}
Expand Down
11 changes: 11 additions & 0 deletions flang/test/Semantics/forall01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,14 @@ subroutine forall7(x)
end forall
end select
end subroutine

subroutine forall8(x)
real :: x(10)
real, external :: foo
!ERROR: Impure procedure 'foo' may not be referenced in a FORALL
forall(i=1:10) x(i) = foo() + i
!OK
associate(y => foo())
forall (i=1:10) x(i) = y + i
end associate
end subroutine
2 changes: 1 addition & 1 deletion flang/test/Semantics/selecttype03.f90
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
b%i = 1 !VDC
type is (t2)
!ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'z=' is not definable
!BECAUSE: Variable 'b' has a vector subscript
!BECAUSE: Construct association 'b' has a vector subscript
call sub_with_in_and_inout_param_vector(b,b) !VDC
end select
select type(b => foo(1) )
Expand Down
Loading