Skip to content

Commit 3f10091

Browse files
committed
[flang] Allow pure function references in expandable scalar
F18 disallows function references and coarray references from appearing in scalar expressions that are to be expanded into arrays to conform with other operands or actual arguments in an elemental expression. This is too strong, as pure procedures can be safely used. Differential Revision: https://reviews.llvm.org/D131096
1 parent 7602e28 commit 3f10091

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

flang/include/flang/Evaluate/call.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ struct ProcedureDesignator {
199199
std::optional<DynamicType> GetType() const;
200200
int Rank() const;
201201
bool IsElemental() const;
202+
bool IsPure() const;
202203
std::optional<Expr<SubscriptInteger>> LEN() const;
203204
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
204205

flang/include/flang/Evaluate/tools.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,17 +1007,25 @@ std::optional<std::string> FindImpureCall(
10071007
// Predicate: is a scalar expression suitable for naive scalar expansion
10081008
// in the flattening of an array expression?
10091009
// TODO: capture such scalar expansions in temporaries, flatten everything
1010-
struct UnexpandabilityFindingVisitor
1010+
class UnexpandabilityFindingVisitor
10111011
: public AnyTraverse<UnexpandabilityFindingVisitor> {
1012+
public:
10121013
using Base = AnyTraverse<UnexpandabilityFindingVisitor>;
10131014
using Base::operator();
1014-
UnexpandabilityFindingVisitor() : Base{*this} {}
1015-
template <typename T> bool operator()(const FunctionRef<T> &) { return true; }
1015+
explicit UnexpandabilityFindingVisitor(bool admitPureCall)
1016+
: Base{*this}, admitPureCall_{admitPureCall} {}
1017+
template <typename T> bool operator()(const FunctionRef<T> &procRef) {
1018+
return !admitPureCall_ || !procRef.proc().IsPure();
1019+
}
10161020
bool operator()(const CoarrayRef &) { return true; }
1021+
1022+
private:
1023+
bool admitPureCall_{false};
10171024
};
10181025

1019-
template <typename T> bool IsExpandableScalar(const Expr<T> &expr) {
1020-
return !UnexpandabilityFindingVisitor{}(expr);
1026+
template <typename T>
1027+
bool IsExpandableScalar(const Expr<T> &expr, bool admitPureCall = false) {
1028+
return !UnexpandabilityFindingVisitor{admitPureCall}(expr);
10211029
}
10221030

10231031
// Common handling for procedure pointer compatibility of left- and right-hand

flang/lib/Evaluate/call.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@ bool ProcedureDesignator::IsElemental() const {
145145
return false;
146146
}
147147

148+
bool ProcedureDesignator::IsPure() const {
149+
if (const Symbol * interface{GetInterfaceSymbol()}) {
150+
return IsPureProcedure(*interface);
151+
} else if (const Symbol * symbol{GetSymbol()}) {
152+
return IsPureProcedure(*symbol);
153+
} else if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&u)}) {
154+
return intrinsic->characteristics.value().attrs.test(
155+
characteristics::Procedure::Attr::Pure);
156+
} else {
157+
DIE("ProcedureDesignator::IsPure(): no case");
158+
}
159+
return false;
160+
}
161+
148162
const SpecificIntrinsic *ProcedureDesignator::GetSpecificIntrinsic() const {
149163
return std::get_if<SpecificIntrinsic>(&u);
150164
}

flang/lib/Semantics/expression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1833,7 +1833,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
18331833
"component", "value")};
18341834
if (checked && *checked && GetRank(*componentShape) > 0 &&
18351835
GetRank(*valueShape) == 0 &&
1836-
!IsExpandableScalar(*converted)) {
1836+
!IsExpandableScalar(*converted, true /*admit PURE call*/)) {
18371837
AttachDeclaration(
18381838
Say(expr.source,
18391839
"Scalar value cannot be expanded to shape of array component '%s'"_err_en_US,

0 commit comments

Comments
 (0)