13#ifndef FORTRAN_EVALUATE_CHARACTERISTICS_H_
14#define FORTRAN_EVALUATE_CHARACTERISTICS_H_
17#include "expression.h"
21#include "flang/Common/Fortran-features.h"
22#include "flang/Common/Fortran.h"
23#include "flang/Common/enum-set.h"
24#include "flang/Common/idioms.h"
25#include "flang/Common/indirection.h"
26#include "flang/Parser/char-block.h"
27#include "flang/Semantics/symbol.h"
37namespace Fortran::evaluate::characteristics {
43namespace Fortran::evaluate::characteristics {
45using common::CopyableIndirection;
48std::optional<bool> Distinguishable(
const common::LanguageFeatureControl &,
49 const Procedure &,
const Procedure &);
51std::optional<bool> DistinguishableOpOrAssign(
52 const common::LanguageFeatureControl &,
const Procedure &,
58bool ShapesAreCompatible(
const std::optional<Shape> &,
59 const std::optional<Shape> &,
bool *possibleWarning =
nullptr);
64 Attr, AssumedRank, AssumedShape, AssumedSize, DeferredShape, Coarray)
77 shape_ = std::move(s);
83 bool operator!=(
const TypeAndShape &that)
const {
return !(*
this == that); }
85 static std::optional<TypeAndShape> Characterize(
87 static std::optional<TypeAndShape> Characterize(
89 bool invariantOnly =
true);
90 static std::optional<TypeAndShape> Characterize(
95 static std::optional<TypeAndShape> Characterize(
97 const auto *symbol{UnwrapWholeSymbolOrComponentDataRef(x)};
98 if (symbol && !symbol->owner().IsDerivedType()) {
99 if (
auto result{Characterize(*symbol, context, invariantOnly)}) {
103 if (
auto type{x.GetType()}) {
104 TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
105 result.corank_ = GetCorank(x);
106 if (result.corank_ > 0) {
107 result.attrs_.set(Attr::Coarray);
109 if (type->category() == TypeCategory::Character) {
110 if (
const auto *chExpr{UnwrapExpr<Expr<SomeCharacter>>(x)}) {
111 if (
auto length{chExpr->LEN()}) {
112 result.set_LEN(std::move(*length));
117 result.AcquireAttrs(*symbol);
119 return std::move(result.Rewrite(context));
126 static std::optional<TypeAndShape> Characterize(
129 const auto *symbol{UnwrapWholeSymbolOrComponentDataRef(x)};
130 if (symbol && !symbol->owner().IsDerivedType()) {
131 if (
auto result{Characterize(*symbol, context, invariantOnly)}) {
135 if (
auto type{x.GetType()}) {
136 TypeAndShape result{*type, GetShape(context, x, invariantOnly)};
137 if (type->category() == TypeCategory::Character) {
138 if (
auto length{x.LEN()}) {
139 result.set_LEN(std::move(*length));
143 result.AcquireAttrs(*symbol);
145 return std::move(result.Rewrite(context));
150 template <
typename A>
151 static std::optional<TypeAndShape> Characterize(
const std::optional<A> &x,
154 return Characterize(*x, context, invariantOnly);
159 template <
typename A>
160 static std::optional<TypeAndShape> Characterize(
163 return Characterize(std::as_const(*ptr), context, invariantOnly);
174 const std::optional<Expr<SubscriptInteger>> &LEN()
const {
return LEN_; }
176 LEN_ = std::move(len);
179 const std::optional<Shape> &shape()
const {
return shape_; }
180 const Attrs &attrs()
const {
return attrs_; }
181 int corank()
const {
return corank_; }
184 int Rank()
const {
return shape_ ? GetRank(*shape_) : -1; }
187 bool CanBeSequenceAssociated()
const {
188 constexpr Attrs notAssumedOrExplicitShape{
189 ~Attrs{Attr::AssumedSize, Attr::Coarray}};
190 return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none();
194 const char *thisIs =
"pointer",
const char *thatIs =
"target",
195 bool omitShapeConformanceCheck =
false,
196 enum CheckConformanceFlags::Flags = CheckConformanceFlags::None)
const;
197 std::optional<Expr<SubscriptInteger>> MeasureElementSizeInBytes(
199 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
205 std::string AsFortran()
const;
206 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
209 static std::optional<TypeAndShape> Characterize(
211 bool invariantOnly =
true);
218 std::optional<Expr<SubscriptInteger>> LEN_;
219 std::optional<Shape> shape_;
226 ENUM_CLASS(Attr, Optional, Allocatable, Asynchronous, Contiguous, Value,
227 Volatile, Pointer, Target, DeducedFromActual)
229 static bool IdenticalSignificantAttrs(
const Attrs &x,
const Attrs &y) {
230 return (x - Attr::DeducedFromActual) == (y - Attr::DeducedFromActual);
238 return !(*
this == that);
240 bool IsCompatibleWith(
const DummyDataObject &, std::string *whyNot =
nullptr,
241 std::optional<std::string> *warning =
nullptr)
const;
242 static std::optional<DummyDataObject> Characterize(
244 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
245 bool IsPassedByDescriptor(
bool isBindC)
const;
246 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
249 std::vector<Expr<SubscriptInteger>> coshape;
250 common::Intent intent{common::Intent::Default};
252 common::IgnoreTKRSet ignoreTKR;
253 std::optional<common::CUDADataAttr> cudaDataAttr;
258 ENUM_CLASS(Attr, Pointer, Optional)
263 bool operator!=(
const DummyProcedure &that)
const {
return !(*
this == that); }
264 bool IsCompatibleWith(
266 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
267 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
269 CopyableIndirection<Procedure> procedure;
270 common::Intent intent{common::Intent::Default};
278 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
285 : name{std::move(name)}, u{std::move(x)} {}
287 : name{std::move(name)}, u{std::move(x)} {}
291 bool operator!=(
const DummyArgument &that)
const {
return !(*
this == that); }
292 static std::optional<DummyArgument> FromActual(std::string &&,
294 static std::optional<DummyArgument> FromActual(std::string &&,
296 bool IsOptional()
const;
297 void SetOptional(
bool =
true);
298 common::Intent GetIntent()
const;
299 void SetIntent(common::Intent);
300 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
301 bool IsTypelessIntrinsicDummy()
const;
302 bool IsCompatibleWith(
const DummyArgument &, std::string *whyNot =
nullptr,
303 std::optional<std::string> *warning =
nullptr)
const;
304 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
311 std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u;
314using DummyArguments = std::vector<DummyArgument>;
318 ENUM_CLASS(Attr, Allocatable, Pointer, Contiguous)
326 bool operator!=(
const FunctionResult &that)
const {
return !(*
this == that); }
327 static std::optional<FunctionResult> Characterize(
330 bool IsAssumedLengthCharacter()
const;
332 const Procedure *IsProcedurePointer()
const {
333 if (
const auto *pp{std::get_if<CopyableIndirection<Procedure>>(&u)}) {
340 return std::get_if<TypeAndShape>(&u);
342 void SetType(
DynamicType t) { std::get<TypeAndShape>(u).set_type(t); }
343 bool CanBeReturnedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
344 bool IsCompatibleWith(
347 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
350 std::variant<TypeAndShape, CopyableIndirection<Procedure>> u;
351 std::optional<common::CUDADataAttr> cudaDataAttr;
357 Attr, Pure, Elemental, BindC, ImplicitInterface,
NullPointer, Subroutine)
362 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(
Procedure)
364 bool operator==(
const Procedure &)
const;
365 bool operator!=(
const Procedure &that)
const {
return !(*
this == that); }
370 static std::optional<Procedure> Characterize(
372 static std::optional<Procedure> Characterize(
374 static std::optional<Procedure> Characterize(
376 static std::optional<Procedure> Characterize(
380 static std::optional<Procedure> FromActuals(
385 bool IsFunction()
const {
return functionResult.has_value(); }
386 bool IsSubroutine()
const {
return attrs.test(Attr::Subroutine); }
388 bool IsPure()
const {
return attrs.test(Attr::Pure); }
389 bool IsElemental()
const {
return attrs.test(Attr::Elemental); }
390 bool IsBindC()
const {
return attrs.test(Attr::BindC); }
391 bool HasExplicitInterface()
const {
392 return !attrs.test(Attr::ImplicitInterface);
394 std::optional<int> FindPassIndex(std::optional<parser::CharBlock>)
const;
395 bool CanBeCalledViaImplicitInterface(std::string *whyNot =
nullptr)
const;
396 bool CanOverride(
const Procedure &, std::optional<int> passIndex)
const;
397 bool IsCompatibleWith(
const Procedure &,
bool ignoreImplicitVsExplicit,
399 std::optional<std::string> *warning =
nullptr)
const;
401 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
403 std::optional<FunctionResult> functionResult;
404 DummyArguments dummyArguments;
406 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs;
Definition: enum-set.h:28
Definition: indirection.h:31
Definition: variable.h:393
Definition: characteristics.h:61
Definition: message.h:363
Definition: expression.h:827
Definition: characteristics.h:275
Definition: characteristics.h:282
Definition: characteristics.h:225
Definition: characteristics.h:257
Definition: characteristics.h:317
Definition: characteristics.h:355