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)} {
73 CHECK(IsSubscriptIntegerKind(*shape_));
76 TypeAndShape(
DynamicType t, std::optional<Shape> &&s) : type_{t} {
77 shape_ = std::move(s);
78 CHECK(!shape_ || IsSubscriptIntegerKind(*shape_));
81 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(TypeAndShape)
83 bool operator==(
const TypeAndShape &)
const;
84 bool operator!=(
const TypeAndShape &that)
const {
return !(*
this == that); }
86 static std::optional<TypeAndShape> Characterize(
88 static std::optional<TypeAndShape> Characterize(
90 bool invariantOnly =
true);
91 static std::optional<TypeAndShape> Characterize(
96 static std::optional<TypeAndShape> Characterize(
98 const auto *symbol{UnwrapWholeSymbolOrComponentDataRef(x)};
99 if (symbol && !symbol->owner().IsDerivedType()) {
100 if (
auto result{Characterize(*symbol, context, invariantOnly)}) {
104 if (
auto type{x.GetType()}) {
105 TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
106 result.corank_ = GetCorank(x);
107 if (type->category() == TypeCategory::Character) {
108 if (
const auto *chExpr{
109 UnwrapExpr<Expr<Type<TypeCategory::Character>>>(x)}) {
110 if (
auto length{chExpr->LEN()}) {
111 result.set_LEN(std::move(*length));
116 result.AcquireAttrs(*symbol);
118 return std::move(result.Rewrite(context));
124 static std::optional<TypeAndShape> Characterize(
128 template <
typename A>
129 static std::optional<TypeAndShape> Characterize(
const std::optional<A> &x,
132 return Characterize(*x, context, invariantOnly);
137 template <
typename A>
138 static std::optional<TypeAndShape> Characterize(
141 return Characterize(std::as_const(*ptr), context, invariantOnly);
152 const std::optional<Expr<SubscriptInteger>> &LEN()
const {
return LEN_; }
154 CHECK(IsSubscriptIntegerKind(len));
155 LEN_ = std::move(len);
158 const std::optional<Shape> &shape()
const {
return shape_; }
159 const Attrs &attrs()
const {
return attrs_; }
160 Attrs &attrs() {
return attrs_; }
161 bool isPossibleSequenceAssociation()
const {
162 return isPossibleSequenceAssociation_;
164 TypeAndShape &set_isPossibleSequenceAssociation(
bool yes) {
165 isPossibleSequenceAssociation_ = yes;
168 int corank()
const {
return corank_; }
169 void set_corank(
int n) { corank_ = n; }
172 int Rank()
const {
return shape_ ? GetRank(*shape_) : -1; }
175 bool CanBeSequenceAssociated()
const {
176 constexpr Attrs notAssumedOrExplicitShape{~Attrs{Attr::AssumedSize}};
177 return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none();
181 const char *thisIs =
"pointer",
const char *thatIs =
"target",
182 bool omitShapeConformanceCheck =
false,
183 enum CheckConformanceFlags::Flags = CheckConformanceFlags::None)
const;
184 std::optional<Expr<SubscriptInteger>> MeasureElementSizeInBytes(
186 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
189 bool IsExplicitShape()
const {
192 return Rank() > 0 && attrs_.none();
198 std::string AsFortran()
const;
199 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
202 static std::optional<TypeAndShape> Characterize(
204 bool invariantOnly =
true);
210 std::optional<Expr<SubscriptInteger>> LEN_;
211 std::optional<Shape> shape_;
213 bool isPossibleSequenceAssociation_{
false};
218struct DummyDataObject {
219 ENUM_CLASS(Attr, Optional, Allocatable, Asynchronous, Contiguous, Value,
220 Volatile, Pointer, Target, DeducedFromActual, OnlyIntrinsicInquiry)
222 static bool IdenticalSignificantAttrs(
const Attrs &x,
const Attrs &y) {
223 return (x - Attr::DeducedFromActual) == (y - Attr::DeducedFromActual);
225 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(DummyDataObject)
226 explicit DummyDataObject(
const TypeAndShape &t) : type{t} {}
227 explicit DummyDataObject(
TypeAndShape &&t) : type{std::move(t)} {}
228 explicit DummyDataObject(
DynamicType t) : type{t} {}
229 bool operator==(
const DummyDataObject &)
const;
230 bool operator!=(
const DummyDataObject &that)
const {
231 return !(*
this == that);
233 bool IsCompatibleWith(
const DummyDataObject &, std::string *whyNot =
nullptr,
234 std::optional<std::string> *warning =
nullptr)
const;
235 static std::optional<DummyDataObject> Characterize(
237 bool CanBePassedViaImplicitInterface(
238 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
239 bool IsPassedByDescriptor(
bool isBindC)
const;
240 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
243 std::vector<Expr<SubscriptInteger>> coshape;
244 common::Intent intent{common::Intent::Default};
246 common::IgnoreTKRSet ignoreTKR;
247 std::optional<common::CUDADataAttr> cudaDataAttr;
251struct DummyProcedure {
252 ENUM_CLASS(Attr, Pointer, Optional)
254 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(DummyProcedure)
256 bool operator==(
const DummyProcedure &)
const;
257 bool operator!=(
const DummyProcedure &that)
const {
return !(*
this == that); }
258 bool IsCompatibleWith(
259 const DummyProcedure &, std::string *whyNot =
nullptr)
const;
260 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
261 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
263 CopyableIndirection<Procedure> procedure;
264 common::Intent intent{common::Intent::Default};
276struct DummyArgument {
277 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(DummyArgument)
279 : name{std::move(name)}, u{std::move(x)} {}
281 : name{std::move(name)}, u{std::move(x)} {}
284 bool operator==(
const DummyArgument &)
const;
285 bool operator!=(
const DummyArgument &that)
const {
return !(*
this == that); }
286 static std::optional<DummyArgument> FromActual(std::string &&,
288 static std::optional<DummyArgument> FromActual(std::string &&,
290 bool IsOptional()
const;
291 void SetOptional(
bool =
true);
292 common::Intent GetIntent()
const;
293 void SetIntent(common::Intent);
294 bool CanBePassedViaImplicitInterface(
295 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
296 bool IsTypelessIntrinsicDummy()
const;
297 bool IsCompatibleWith(
const DummyArgument &, std::string *whyNot =
nullptr,
298 std::optional<std::string> *warning =
nullptr)
const;
299 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
306 std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u;
312struct FunctionResult {
313 ENUM_CLASS(Attr, Allocatable, Pointer, Contiguous)
315 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(FunctionResult)
320 bool operator==(
const FunctionResult &)
const;
321 bool operator!=(
const FunctionResult &that)
const {
return !(*
this == that); }
322 static std::optional<FunctionResult> Characterize(
325 bool IsAssumedLengthCharacter()
const;
327 const Procedure *IsProcedurePointer()
const {
328 if (
const auto *pp{std::get_if<CopyableIndirection<Procedure>>(&u)}) {
335 return std::get_if<TypeAndShape>(&u);
337 void SetType(
DynamicType t) { std::get<TypeAndShape>(u).set_type(t); }
338 bool CanBeReturnedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
339 bool IsCompatibleWith(
340 const FunctionResult &, std::string *whyNot =
nullptr)
const;
342 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
345 std::variant<TypeAndShape, CopyableIndirection<Procedure>> u;
346 std::optional<common::CUDADataAttr> cudaDataAttr;
351 ENUM_CLASS(Attr, Pure, Simple, Elemental, BindC, ImplicitInterface,
356 Procedure(DummyArguments &&, Attrs);
357 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(Procedure)
359 bool operator==(
const Procedure &)
const;
360 bool operator!=(
const Procedure &that)
const {
return !(*
this == that); }
365 static std::optional<Procedure> Characterize(
367 static std::optional<Procedure> Characterize(
369 static std::optional<Procedure> Characterize(
371 static std::optional<Procedure> Characterize(
375 static std::optional<Procedure> FromActuals(
380 bool IsFunction()
const {
return functionResult.has_value(); }
381 bool IsSubroutine()
const {
return attrs.test(Attr::Subroutine); }
383 bool IsPure()
const {
return attrs.test(Attr::Pure); }
384 bool IsSimple()
const {
return attrs.test(Attr::Simple); }
385 bool IsElemental()
const {
return attrs.test(Attr::Elemental); }
386 bool IsBindC()
const {
return attrs.test(Attr::BindC); }
387 bool HasExplicitInterface()
const {
388 return !attrs.test(Attr::ImplicitInterface);
390 std::optional<int> FindPassIndex(std::optional<parser::CharBlock>)
const;
391 bool CanBeCalledViaImplicitInterface(
392 std::string *whyNot =
nullptr,
bool checkCUDA =
true)
const;
393 bool CanOverride(
const Procedure &, std::optional<int> passIndex)
const;
394 bool IsCompatibleWith(
const Procedure &,
bool ignoreImplicitVsExplicit,
396 std::optional<std::string> *warning =
nullptr)
const;
398 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
400 std::optional<FunctionResult> functionResult;
401 DummyArguments dummyArguments;
403 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs;
405 bool hasOpenACCRoutine{
false};
408 bool isStmtFunction{
false};