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);
63 ENUM_CLASS(Attr, AssumedRank, AssumedShape, AssumedSize, DeferredShape)
76 shape_ = std::move(s);
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 int corank()
const {
return corank_; }
178 void set_corank(
int n) { corank_ = n; }
181 int Rank()
const {
return shape_ ? GetRank(*shape_) : -1; }
184 bool CanBeSequenceAssociated()
const {
185 constexpr Attrs notAssumedOrExplicitShape{
~Attrs{Attr::AssumedSize}};
186 return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none();
190 const char *thisIs =
"pointer",
const char *thatIs =
"target",
191 bool omitShapeConformanceCheck =
false,
192 enum CheckConformanceFlags::Flags = CheckConformanceFlags::None)
const;
193 std::optional<Expr<SubscriptInteger>> MeasureElementSizeInBytes(
195 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
201 std::string AsFortran()
const;
202 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
205 static std::optional<TypeAndShape> Characterize(
207 bool invariantOnly =
true);
214 std::optional<Expr<SubscriptInteger>> LEN_;
215 std::optional<Shape> shape_;
222 ENUM_CLASS(Attr, Optional, Allocatable, Asynchronous, Contiguous, Value,
223 Volatile, Pointer, Target, DeducedFromActual)
225 static bool IdenticalSignificantAttrs(
const Attrs &x,
const Attrs &y) {
226 return (x - Attr::DeducedFromActual) == (y - Attr::DeducedFromActual);
234 return !(*
this == that);
236 bool IsCompatibleWith(
const DummyDataObject &, std::string *whyNot =
nullptr,
237 std::optional<std::string> *warning =
nullptr)
const;
238 static std::optional<DummyDataObject> Characterize(
240 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
241 bool IsPassedByDescriptor(
bool isBindC)
const;
242 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
245 std::vector<Expr<SubscriptInteger>> coshape;
246 common::Intent intent{common::Intent::Default};
248 common::IgnoreTKRSet ignoreTKR;
249 std::optional<common::CUDADataAttr> cudaDataAttr;
254 ENUM_CLASS(Attr, Pointer, Optional)
259 bool operator!=(
const DummyProcedure &that)
const {
return !(*
this == that); }
260 bool IsCompatibleWith(
262 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
263 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
265 CopyableIndirection<Procedure> procedure;
266 common::Intent intent{common::Intent::Default};
274 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
281 : name{std::move(name)}, u{std::move(x)} {}
283 : name{std::move(name)}, u{std::move(x)} {}
287 bool operator!=(
const DummyArgument &that)
const {
return !(*
this == that); }
288 static std::optional<DummyArgument> FromActual(std::string &&,
290 static std::optional<DummyArgument> FromActual(std::string &&,
292 bool IsOptional()
const;
293 void SetOptional(
bool =
true);
294 common::Intent GetIntent()
const;
295 void SetIntent(common::Intent);
296 bool CanBePassedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
297 bool IsTypelessIntrinsicDummy()
const;
298 bool IsCompatibleWith(
const DummyArgument &, std::string *whyNot =
nullptr,
299 std::optional<std::string> *warning =
nullptr)
const;
300 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
307 std::variant<DummyDataObject, DummyProcedure, AlternateReturn> u;
310using DummyArguments = std::vector<DummyArgument>;
314 ENUM_CLASS(Attr, Allocatable, Pointer, Contiguous)
322 bool operator!=(
const FunctionResult &that)
const {
return !(*
this == that); }
323 static std::optional<FunctionResult> Characterize(
326 bool IsAssumedLengthCharacter()
const;
328 const Procedure *IsProcedurePointer()
const {
329 if (
const auto *pp{std::get_if<CopyableIndirection<Procedure>>(&u)}) {
336 return std::get_if<TypeAndShape>(&u);
338 void SetType(
DynamicType t) { std::get<TypeAndShape>(u).set_type(t); }
339 bool CanBeReturnedViaImplicitInterface(std::string *whyNot =
nullptr)
const;
340 bool IsCompatibleWith(
343 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
346 std::variant<TypeAndShape, CopyableIndirection<Procedure>> u;
347 std::optional<common::CUDADataAttr> cudaDataAttr;
353 Attr, Pure, Elemental, BindC, ImplicitInterface,
NullPointer, Subroutine)
358 DECLARE_CONSTRUCTORS_AND_ASSIGNMENTS(
Procedure)
360 bool operator==(
const Procedure &)
const;
361 bool operator!=(
const Procedure &that)
const {
return !(*
this == that); }
366 static std::optional<Procedure> Characterize(
368 static std::optional<Procedure> Characterize(
370 static std::optional<Procedure> Characterize(
372 static std::optional<Procedure> Characterize(
376 static std::optional<Procedure> FromActuals(
381 bool IsFunction()
const {
return functionResult.has_value(); }
382 bool IsSubroutine()
const {
return attrs.test(Attr::Subroutine); }
384 bool IsPure()
const {
return attrs.test(Attr::Pure); }
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(std::string *whyNot =
nullptr)
const;
392 bool CanOverride(
const Procedure &, std::optional<int> passIndex)
const;
393 bool IsCompatibleWith(
const Procedure &,
bool ignoreImplicitVsExplicit,
395 std::optional<std::string> *warning =
nullptr)
const;
397 llvm::raw_ostream &Dump(llvm::raw_ostream &)
const;
399 std::optional<FunctionResult> functionResult;
400 DummyArguments dummyArguments;
402 std::optional<common::CUDASubprogramAttrs> cudaSubprogramAttrs;
Definition: indirection.h:31
Definition: variable.h:393
Definition: characteristics.h:61
Definition: message.h:363
Definition: expression.h:827
Definition: characteristics.h:271
Definition: characteristics.h:278
Definition: characteristics.h:221
Definition: characteristics.h:253
Definition: characteristics.h:313
Definition: characteristics.h:351