@@ -54,9 +54,14 @@ inline int GetRank(const Shape &s) { return static_cast<int>(s.size()); }
5454Shape Fold (FoldingContext &, Shape &&);
5555std::optional<Shape> Fold (FoldingContext &, std::optional<Shape> &&);
5656
57+ // Computes shapes in terms of expressions that are scope-invariant, by
58+ // default, which is nearly always what one wants outside of procedure
59+ // characterization.
5760template <typename A>
58- std::optional<Shape> GetShape (FoldingContext &, const A &);
59- template <typename A> std::optional<Shape> GetShape (const A &);
61+ std::optional<Shape> GetShape (
62+ FoldingContext &, const A &, bool invariantOnly = true );
63+ template <typename A>
64+ std::optional<Shape> GetShape (const A &, bool invariantOnly = true );
6065
6166// The dimension argument to these inquiries is zero-based,
6267// unlike the DIM= arguments to many intrinsics.
@@ -68,31 +73,42 @@ template <typename A> std::optional<Shape> GetShape(const A &);
6873// in those circumstances.
6974// Similarly, GetUBOUND result will be forced to 0 on an empty dimension,
7075// but will fail if the extent is not a compile time constant.
71- ExtentExpr GetRawLowerBound (const NamedEntity &, int dimension);
7276ExtentExpr GetRawLowerBound (
73- FoldingContext &, const NamedEntity &, int dimension);
74- MaybeExtentExpr GetLBOUND (const NamedEntity &, int dimension);
75- MaybeExtentExpr GetLBOUND (FoldingContext &, const NamedEntity &, int dimension);
76- MaybeExtentExpr GetRawUpperBound (const NamedEntity &, int dimension);
77+ const NamedEntity &, int dimension, bool invariantOnly = true );
78+ ExtentExpr GetRawLowerBound (FoldingContext &, const NamedEntity &,
79+ int dimension, bool invariantOnly = true );
80+ MaybeExtentExpr GetLBOUND (
81+ const NamedEntity &, int dimension, bool invariantOnly = true );
82+ MaybeExtentExpr GetLBOUND (FoldingContext &, const NamedEntity &, int dimension,
83+ bool invariantOnly = true );
7784MaybeExtentExpr GetRawUpperBound (
78- FoldingContext &, const NamedEntity &, int dimension);
79- MaybeExtentExpr GetUBOUND (const NamedEntity &, int dimension);
80- MaybeExtentExpr GetUBOUND (FoldingContext &, const NamedEntity &, int dimension);
85+ const NamedEntity &, int dimension, bool invariantOnly = true );
86+ MaybeExtentExpr GetRawUpperBound (FoldingContext &, const NamedEntity &,
87+ int dimension, bool invariantOnly = true );
88+ MaybeExtentExpr GetUBOUND (
89+ const NamedEntity &, int dimension, bool invariantOnly = true );
90+ MaybeExtentExpr GetUBOUND (FoldingContext &, const NamedEntity &, int dimension,
91+ bool invariantOnly = true );
8192MaybeExtentExpr ComputeUpperBound (ExtentExpr &&lower, MaybeExtentExpr &&extent);
8293MaybeExtentExpr ComputeUpperBound (
8394 FoldingContext &, ExtentExpr &&lower, MaybeExtentExpr &&extent);
84- Shape GetRawLowerBounds (const NamedEntity &);
85- Shape GetRawLowerBounds (FoldingContext &, const NamedEntity &);
86- Shape GetLBOUNDs (const NamedEntity &);
87- Shape GetLBOUNDs (FoldingContext &, const NamedEntity &);
88- Shape GetUBOUNDs (const NamedEntity &);
89- Shape GetUBOUNDs (FoldingContext &, const NamedEntity &);
90- MaybeExtentExpr GetExtent (const NamedEntity &, int dimension);
91- MaybeExtentExpr GetExtent (FoldingContext &, const NamedEntity &, int dimension);
92- MaybeExtentExpr GetExtent (
93- const Subscript &, const NamedEntity &, int dimension);
95+ Shape GetRawLowerBounds (const NamedEntity &, bool invariantOnly = true );
96+ Shape GetRawLowerBounds (
97+ FoldingContext &, const NamedEntity &, bool invariantOnly = true );
98+ Shape GetLBOUNDs (const NamedEntity &, bool invariantOnly = true );
99+ Shape GetLBOUNDs (
100+ FoldingContext &, const NamedEntity &, bool invariantOnly = true );
101+ Shape GetUBOUNDs (const NamedEntity &, bool invariantOnly = true );
102+ Shape GetUBOUNDs (
103+ FoldingContext &, const NamedEntity &, bool invariantOnly = true );
94104MaybeExtentExpr GetExtent (
95- FoldingContext &, const Subscript &, const NamedEntity &, int dimension);
105+ const NamedEntity &, int dimension, bool invariantOnly = true );
106+ MaybeExtentExpr GetExtent (FoldingContext &, const NamedEntity &, int dimension,
107+ bool invariantOnly = true );
108+ MaybeExtentExpr GetExtent (const Subscript &, const NamedEntity &, int dimension,
109+ bool invariantOnly = true );
110+ MaybeExtentExpr GetExtent (FoldingContext &, const Subscript &,
111+ const NamedEntity &, int dimension, bool invariantOnly = true );
96112
97113// Compute an element count for a triplet or trip count for a DO.
98114ExtentExpr CountTrips (
@@ -115,11 +131,14 @@ class GetShapeHelper
115131 using Result = std::optional<Shape>;
116132 using Base = AnyTraverse<GetShapeHelper, Result>;
117133 using Base::operator ();
118- GetShapeHelper () : Base{*this } {}
119- explicit GetShapeHelper (FoldingContext &c) : Base{*this }, context_{&c} {}
120- explicit GetShapeHelper (FoldingContext &c, bool useResultSymbolShape)
121- : Base{*this }, context_{&c}, useResultSymbolShape_{useResultSymbolShape} {
122- }
134+ explicit GetShapeHelper (bool invariantOnly)
135+ : Base{*this }, invariantOnly_{invariantOnly} {}
136+ explicit GetShapeHelper (FoldingContext &c, bool invariantOnly)
137+ : Base{*this }, context_{&c}, invariantOnly_{invariantOnly} {}
138+ explicit GetShapeHelper (
139+ FoldingContext &c, bool useResultSymbolShape, bool invariantOnly)
140+ : Base{*this }, context_{&c}, useResultSymbolShape_{useResultSymbolShape},
141+ invariantOnly_{invariantOnly} {}
123142
124143 Result operator ()(const ImpliedDoIndex &) const { return ScalarShape (); }
125144 Result operator ()(const DescriptorInquiry &) const { return ScalarShape (); }
@@ -160,7 +179,7 @@ class GetShapeHelper
160179 static Result ScalarShape () { return Shape{}; }
161180 static Shape ConstantShape (const Constant<ExtentType> &);
162181 Result AsShapeResult (ExtentExpr &&) const ;
163- static Shape CreateShape (int rank, NamedEntity &);
182+ Shape CreateShape (int rank, NamedEntity &) const ;
164183
165184 template <typename T>
166185 MaybeExtentExpr GetArrayConstructorValueExtent (
@@ -215,34 +234,40 @@ class GetShapeHelper
215234
216235 FoldingContext *context_{nullptr };
217236 bool useResultSymbolShape_{true };
237+ // When invariantOnly=false, the returned shape need not be invariant
238+ // in its scope; in particular, it may contain references to dummy arguments.
239+ bool invariantOnly_{true };
218240};
219241
220242template <typename A>
221- std::optional<Shape> GetShape (FoldingContext &context, const A &x) {
222- if (auto shape{GetShapeHelper{context}(x)}) {
243+ std::optional<Shape> GetShape (
244+ FoldingContext &context, const A &x, bool invariantOnly) {
245+ if (auto shape{GetShapeHelper{context, invariantOnly}(x)}) {
223246 return Fold (context, std::move (shape));
224247 } else {
225248 return std::nullopt ;
226249 }
227250}
228251
229- template <typename A> std::optional<Shape> GetShape (const A &x) {
230- return GetShapeHelper{}(x);
252+ template <typename A>
253+ std::optional<Shape> GetShape (const A &x, bool invariantOnly) {
254+ return GetShapeHelper{invariantOnly}(x);
231255}
232256
233257template <typename A>
234- std::optional<Shape> GetShape (FoldingContext *context, const A &x) {
258+ std::optional<Shape> GetShape (
259+ FoldingContext *context, const A &x, bool invariantOnly = true ) {
235260 if (context) {
236- return GetShape (*context, x);
261+ return GetShape (*context, x, invariantOnly );
237262 } else {
238- return GetShapeHelper{}(x);
263+ return GetShapeHelper{invariantOnly }(x);
239264 }
240265}
241266
242267template <typename A>
243268std::optional<Constant<ExtentType>> GetConstantShape (
244269 FoldingContext &context, const A &x) {
245- if (auto shape{GetShape (context, x)}) {
270+ if (auto shape{GetShape (context, x, /* invariantonly= */ true )}) {
246271 return AsConstantShape (context, *shape);
247272 } else {
248273 return std::nullopt ;
@@ -252,7 +277,7 @@ std::optional<Constant<ExtentType>> GetConstantShape(
252277template <typename A>
253278std::optional<ConstantSubscripts> GetConstantExtents (
254279 FoldingContext &context, const A &x) {
255- if (auto shape{GetShape (context, x)}) {
280+ if (auto shape{GetShape (context, x, /* invariantOnly= */ true )}) {
256281 return AsConstantExtents (context, *shape);
257282 } else {
258283 return std::nullopt ;
@@ -265,7 +290,8 @@ std::optional<ConstantSubscripts> GetConstantExtents(
265290// arguments).
266291template <typename A>
267292std::optional<Shape> GetContextFreeShape (FoldingContext &context, const A &x) {
268- return GetShapeHelper{context, false }(x);
293+ return GetShapeHelper{
294+ context, /* useResultSymbolShape=*/ false , /* invariantOnly=*/ true }(x);
269295}
270296
271297// Compilation-time shape conformance checking, when corresponding extents
0 commit comments