File tree Expand file tree Collapse file tree 4 files changed +29
-6
lines changed Expand file tree Collapse file tree 4 files changed +29
-6
lines changed Original file line number Diff line number Diff line change @@ -199,6 +199,7 @@ struct ProcedureDesignator {
199
199
std::optional<DynamicType> GetType () const ;
200
200
int Rank () const ;
201
201
bool IsElemental () const ;
202
+ bool IsPure () const ;
202
203
std::optional<Expr<SubscriptInteger>> LEN () const ;
203
204
llvm::raw_ostream &AsFortran (llvm::raw_ostream &) const ;
204
205
Original file line number Diff line number Diff line change @@ -1007,17 +1007,25 @@ std::optional<std::string> FindImpureCall(
1007
1007
// Predicate: is a scalar expression suitable for naive scalar expansion
1008
1008
// in the flattening of an array expression?
1009
1009
// TODO: capture such scalar expansions in temporaries, flatten everything
1010
- struct UnexpandabilityFindingVisitor
1010
+ class UnexpandabilityFindingVisitor
1011
1011
: public AnyTraverse<UnexpandabilityFindingVisitor> {
1012
+ public:
1012
1013
using Base = AnyTraverse<UnexpandabilityFindingVisitor>;
1013
1014
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
+ }
1016
1020
bool operator ()(const CoarrayRef &) { return true ; }
1021
+
1022
+ private:
1023
+ bool admitPureCall_{false };
1017
1024
};
1018
1025
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);
1021
1029
}
1022
1030
1023
1031
// Common handling for procedure pointer compatibility of left- and right-hand
Original file line number Diff line number Diff line change @@ -145,6 +145,20 @@ bool ProcedureDesignator::IsElemental() const {
145
145
return false ;
146
146
}
147
147
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
+
148
162
const SpecificIntrinsic *ProcedureDesignator::GetSpecificIntrinsic () const {
149
163
return std::get_if<SpecificIntrinsic>(&u);
150
164
}
Original file line number Diff line number Diff line change @@ -1833,7 +1833,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(
1833
1833
" component" , " value" )};
1834
1834
if (checked && *checked && GetRank (*componentShape) > 0 &&
1835
1835
GetRank (*valueShape) == 0 &&
1836
- !IsExpandableScalar (*converted)) {
1836
+ !IsExpandableScalar (*converted, true /* admit PURE call */ )) {
1837
1837
AttachDeclaration (
1838
1838
Say (expr.source ,
1839
1839
" Scalar value cannot be expanded to shape of array component '%s'" _err_en_US,
You can’t perform that action at this time.
0 commit comments