63 ENUM_CLASS(Attr, AssumedRank, AssumedShape, AssumedSize, DeferredShape)
66 explicit TypeAndShape(
DynamicType t) : type_{t}, shape_{Shape{}} {
69 TypeAndShape(
DynamicType t,
int rank) : type_{t}, shape_{Shape(rank)} {
72 TypeAndShape(
DynamicType t, Shape &&s) : type_{t}, shape_{std::move(s)} {
75 TypeAndShape(
DynamicType t, std::optional<Shape> &&s) : type_{t} {
76 shape_ = std::move(s);
79 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(TypeAndShape)
81 bool operator==(
const TypeAndShape &)
const;
82 bool operator!=(
const TypeAndShape &that)
const {
return !(*
this == that); }
84 static std::optional<TypeAndShape> Characterize(
86 static std::optional<TypeAndShape> Characterize(
88 bool invariantOnly =
true);
89 static std::optional<TypeAndShape> Characterize(
94 static std::optional<TypeAndShape> Characterize(
96 const auto *symbol{UnwrapWholeSymbolOrComponentDataRef(x)};
97 if (symbol && !symbol->owner().IsDerivedType()) {
98 if (
auto result{Characterize(*symbol, context, invariantOnly)}) {
102 if (
auto type{x.GetType()}) {
103 TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
104 result.corank_ = GetCorank(x);
105 if (type->category() == TypeCategory::Character) {
106 if (
const auto *chExpr{UnwrapExpr<Expr<SomeCharacter>>(x)}) {
107 if (
auto length{chExpr->LEN()}) {
108 result.set_LEN(std::move(*length));
113 result.AcquireAttrs(*symbol);
115 return std::move(result.Rewrite(context));
122 static std::optional<TypeAndShape> Characterize(
125 const auto *symbol{UnwrapWholeSymbolOrComponentDataRef(x)};
126 if (symbol && !symbol->owner().IsDerivedType()) {
127 if (
auto result{Characterize(*symbol, context, invariantOnly)}) {
131 if (
auto type{x.GetType()}) {
132 TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
133 if (type->category() == TypeCategory::Character) {
134 if (
auto length{x.LEN()}) {
135 result.set_LEN(std::move(*length));
139 result.AcquireAttrs(*symbol);
141 return std::move(result.Rewrite(context));
146 template <
typename A>
147 static std::optional<TypeAndShape> Characterize(
const std::optional<A> &x,
150 return Characterize(*x, context, invariantOnly);
155 template <
typename A>
156 static std::optional<TypeAndShape> Characterize(
159 return Characterize(std::as_const(*ptr), context, invariantOnly);
170 const std::optional<Expr<SubscriptInteger>> &LEN()
const {
return LEN_; }
172 LEN_ = std::move(len);
175 const std::optional<Shape> &shape()
const {
return shape_; }
176 const Attrs &attrs()
const {
return attrs_; }
177 Attrs &attrs() {
return attrs_; }
178 bool isPossibleSequenceAssociation()
const {
179 return isPossibleSequenceAssociation_;
181 TypeAndShape &set_isPossibleSequenceAssociation(
bool yes) {
182 isPossibleSequenceAssociation_ = yes;
185 int corank()
const {
return corank_; }
186 void set_corank(
int n) { corank_ = n; }
189 int Rank()
const {
return shape_ ? GetRank(*shape_) : -1; }
192 bool CanBeSequenceAssociated()
const {
193 constexpr Attrs notAssumedOrExplicitShape{~Attrs{Attr::AssumedSize}};
194 return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none();
198 const char *thisIs =
"pointer",
const char *thatIs =
"target",
199 bool omitShapeConformanceCheck =
false,
200 enum CheckConformanceFlags::Flags = CheckConformanceFlags::None)
const;
201 std::optional<Expr<SubscriptInteger>> MeasureElementSizeInBytes(
203 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
206 bool IsExplicitShape()
const {
209 return Rank() > 0 && attrs_.none();
215 std::string AsFortran()
const;
216 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
219 static std::optional<TypeAndShape> Characterize(
221 bool invariantOnly =
true);
227 std::optional<Expr<SubscriptInteger>> LEN_;
228 std::optional<Shape> shape_;
230 bool isPossibleSequenceAssociation_{
false};
235struct DummyDataObject {
236 ENUM_CLASS(Attr, Optional, Allocatable, Asynchronous, Contiguous, Value,
237 Volatile, Pointer, Target, DeducedFromActual, OnlyIntrinsicInquiry)
239 static bool IdenticalSignificantAttrs(
const Attrs &x,
const Attrs &y) {
240 return (x - Attr::DeducedFromActual) == (y - Attr::DeducedFromActual);
242 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyDataObject)
243 explicit DummyDataObject(
const TypeAndShape &t) : type{t} {}
244 explicit DummyDataObject(
TypeAndShape &&t) : type{std::move(t)} {}
245 explicit DummyDataObject(
DynamicType t) : type{t} {}
246 bool operator==(
const DummyDataObject &)
const;
247 bool operator!=(
const DummyDataObject &that)
const {
248 return !(*
this == that);
250 bool IsCompatibleWith(
const DummyDataObject &, std::string *whyNot =
nullptr,
251 std::optional<std::string> *warning =
nullptr)
const;
252 static std::optional<DummyDataObject> Characterize(
254 bool CanBePassedViaImplicitInterface(
255 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
256 bool IsPassedByDescriptor(
bool isBindC)
const;
257 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
260 std::vector<Expr<SubscriptInteger>> coshape;
261 common::Intent intent{common::Intent::Default};
263 common::IgnoreTKRSet ignoreTKR;
264 std::optional<common::CUDADataAttr> cudaDataAttr;
293struct DummyArgument {
294 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(DummyArgument)
296 : name{std::move(name)}, u{std::move(x)} {}
298 : name{std::move(name)}, u{std::move(x)} {}
301 bool operator==(
const DummyArgument &)
const;
302 bool operator!=(
const DummyArgument &that)
const {
return !(*
this == that); }
303 static std::optional<DummyArgument> FromActual(std::string &&,
305 static std::optional<DummyArgument> FromActual(std::string &&,
307 bool IsOptional()
const;
308 void SetOptional(
bool =
true);
309 common::Intent GetIntent()
const;
310 void SetIntent(common::Intent);
311 bool CanBePassedViaImplicitInterface(
312 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
313 bool IsTypelessIntrinsicDummy()
const;
314 bool IsCompatibleWith(
const DummyArgument &, std::string *whyNot =
nullptr,
315 std::optional<std::string> *warning =
nullptr)
const;
316 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
323 std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u;
329struct FunctionResult {
330 ENUM_CLASS(Attr, Allocatable, Pointer, Contiguous)
332 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(FunctionResult)
337 bool operator==(
const FunctionResult &)
const;
338 bool operator!=(
const FunctionResult &that)
const {
return !(*
this == that); }
339 static std::optional<FunctionResult> Characterize(
342 bool IsAssumedLengthCharacter()
const;
344 const Procedure *IsProcedurePointer()
const {
345 if (
const auto *pp{std::get_if<CopyableIndirection<Procedure>>(&u)}) {
352 return std::get_if<TypeAndShape>(&u);
354 void SetType(
DynamicType t) { std::get<TypeAndShape>(u).set_type(t); }
355 bool CanBeReturnedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
356 bool IsCompatibleWith(
357 const FunctionResult &, std::string *whyNot =
nullptr)
const;
359 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
362 std::variant<TypeAndShape, CopyableIndirection<Procedure>> u;
363 std::optional<common::CUDADataAttr> cudaDataAttr;
368 ENUM_CLASS(Attr, Pure, Elemental, BindC, ImplicitInterface,
NullPointer,
369 NullAllocatable, Subroutine)
373 Procedure(DummyArguments &&, Attrs);
374 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure)
376 bool operator==(
const Procedure &)
const;
377 bool operator!=(
const Procedure &that)
const {
return !(*
this == that); }
382 static std::optional<Procedure> Characterize(
384 static std::optional<Procedure> Characterize(
386 static std::optional<Procedure> Characterize(
388 static std::optional<Procedure> Characterize(
392 static std::optional<Procedure> FromActuals(
397 bool IsFunction()
const {
return functionResult.has_value(); }
398 bool IsSubroutine()
const {
return attrs.test(Attr::Subroutine); }
400 bool IsPure()
const {
return attrs.test(Attr::Pure); }
401 bool IsElemental()
const {
return attrs.test(Attr::Elemental); }
402 bool IsBindC()
const {
return attrs.test(Attr::BindC); }
403 bool HasExplicitInterface()
const {
404 return !attrs.test(Attr::ImplicitInterface);
406 std::optional<int> FindPassIndex(std::optional<parser::CharBlock>)
const;
407 bool CanBeCalledViaImplicitInterface(
408 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
409 bool CanOverride(
const Procedure &, std::optional<int> passIndex)
const;
410 bool IsCompatibleWith(
const Procedure &,
bool ignoreImplicitVsExplicit,
412 std::optional<std::string> *warning =
nullptr)
const;
414 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
416 std::optional<FunctionResult> functionResult;
417 DummyArguments dummyArguments;
419 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs;