9#ifndef FORTRAN_SEMANTICS_TYPE_H_
10#define FORTRAN_SEMANTICS_TYPE_H_
12#include "flang/Common/Fortran.h"
13#include "flang/Common/idioms.h"
14#include "flang/Evaluate/expression.h"
15#include "flang/Parser/char-block.h"
34std::optional<bool> AreEquivalentInInterface(
const Expr<T> &,
const Expr<T> &);
35extern template std::optional<bool> AreEquivalentInInterface<SomeInteger>(
36 const Expr<SomeInteger> &,
const Expr<SomeInteger> &);
39namespace Fortran::semantics {
42class SemanticsContext;
47using SourceName = parser::CharBlock;
48using TypeCategory = common::TypeCategory;
49using SomeExpr = evaluate::Expr<evaluate::SomeType>;
50using MaybeExpr = std::optional<SomeExpr>;
51using SomeIntExpr = evaluate::Expr<evaluate::SomeInteger>;
52using MaybeIntExpr = std::optional<SomeIntExpr>;
53using SubscriptIntExpr = evaluate::Expr<evaluate::SubscriptInteger>;
54using MaybeSubscriptIntExpr = std::optional<SubscriptIntExpr>;
55using KindExpr = SubscriptIntExpr;
66 static Bound Star() {
return Bound(Category::Star); }
67 static Bound Colon() {
return Bound(Category::Colon); }
68 explicit Bound(MaybeSubscriptIntExpr &&expr) : expr_{std::move(expr)} {}
69 explicit Bound(common::ConstantSubscript bound);
74 bool isExplicit()
const {
return category_ == Category::Explicit; }
75 bool isStar()
const {
return category_ == Category::Star; }
76 bool isColon()
const {
return category_ == Category::Colon; }
77 MaybeSubscriptIntExpr &GetExplicit() {
return expr_; }
78 const MaybeSubscriptIntExpr &GetExplicit()
const {
return expr_; }
79 void SetExplicit(MaybeSubscriptIntExpr &&expr) {
81 expr_ = std::move(expr);
85 enum class Category { Explicit, Star, Colon };
86 Bound(Category category) : category_{category} {}
87 Bound(Category category, MaybeSubscriptIntExpr &&expr)
88 : category_{category}, expr_{std::move(expr)} {}
89 Category category_{Category::Explicit};
90 MaybeSubscriptIntExpr expr_;
91 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const Bound &);
98 static ParamValue Assumed(common::TypeParamAttr attr) {
101 static ParamValue Deferred(common::TypeParamAttr attr) {
105 explicit ParamValue(MaybeIntExpr &&, common::TypeParamAttr);
107 explicit ParamValue(common::ConstantSubscript, common::TypeParamAttr attr);
108 bool isExplicit()
const {
return category_ == Category::Explicit; }
109 bool isAssumed()
const {
return category_ == Category::Assumed; }
110 bool isDeferred()
const {
return category_ == Category::Deferred; }
111 const MaybeIntExpr &GetExplicit()
const {
return expr_; }
113 bool isKind()
const {
return attr_ == common::TypeParamAttr::Kind; }
114 bool isLen()
const {
return attr_ == common::TypeParamAttr::Len; }
115 void set_attr(common::TypeParamAttr attr) { attr_ = attr; }
116 bool operator==(
const ParamValue &that)
const {
117 return category_ == that.category_ && expr_ == that.expr_;
119 bool operator!=(
const ParamValue &that)
const {
return !(*
this == that); }
120 bool IsEquivalentInInterface(
const ParamValue &that)
const {
121 return (category_ == that.category_ &&
122 expr_.has_value() == that.expr_.has_value() &&
123 (!expr_ || evaluate::AreEquivalentInInterface(*expr_, *that.expr_)));
125 std::string AsFortran()
const;
128 enum class Category { Explicit, Deferred, Assumed };
129 ParamValue(Category category, common::TypeParamAttr attr)
130 : category_{category}, attr_{attr} {}
131 Category category_{Category::Explicit};
132 common::TypeParamAttr attr_{common::TypeParamAttr::Kind};
134 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ParamValue &);
139 TypeCategory category()
const {
return category_; }
140 const KindExpr &kind()
const {
return kind_; }
142 return category_ == x.category_ && kind_ == x.kind_;
145 std::string AsFortran()
const;
151 TypeCategory category_;
153 friend llvm::raw_ostream &operator<<(
161 CHECK(common::IsNumericTypeCategory(category));
175 length_{std::move(length)} {}
176 const ParamValue &length()
const {
return length_; }
178 return kind() == that.kind() && length_ == that.length_;
180 std::string AsFortran()
const;
184 friend llvm::raw_ostream &operator<<(
192 return ShapeSpec(std::move(lb), std::move(ub));
196 return MakeExplicit(
Bound{1}, std::move(ub));
204 return ShapeSpec(std::move(lb), Bound::Colon());
208 return ShapeSpec(Bound::Colon(), Bound::Colon());
214 return ShapeSpec(std::move(lb), Bound::Star());
218 return ShapeSpec(Bound::Star(), Bound::Star());
226 Bound &lbound() {
return lb_; }
227 const Bound &lbound()
const {
return lb_; }
228 Bound &ubound() {
return ub_; }
229 const Bound &ubound()
const {
return ub_; }
235 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ShapeSpec &);
240 int Rank()
const {
return size(); }
245 inline bool IsExplicitShape()
const;
246 inline bool CanBeAssumedShape()
const;
247 inline bool CanBeDeferredShape()
const;
248 inline bool CanBeImpliedShape()
const;
249 inline bool CanBeAssumedSize()
const;
250 inline bool IsAssumedRank()
const;
254 template <
typename P>
bool CheckAll(P predicate)
const {
255 return !empty() && std::all_of(begin(), end(), predicate);
258llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ArraySpec &);
264 enum class Category { DerivedType, IntrinsicVector, PairVector, QuadVector };
266 using RawParameter = std::pair<const parser::Keyword *, ParamValue>;
267 using RawParameters = std::vector<RawParameter>;
268 using ParameterMapType = std::map<SourceName, ParamValue>;
273 const SourceName &name()
const {
return name_; }
274 const Symbol &originalTypeSymbol()
const {
return originalTypeSymbol_; }
275 const Symbol &typeSymbol()
const {
return typeSymbol_; }
276 const Scope *scope()
const {
return scope_; }
278 const Scope *GetScope()
const;
279 void set_scope(
const Scope &);
280 void ReplaceScope(
const Scope &);
281 const RawParameters &rawParameters()
const {
return rawParameters_; }
282 const ParameterMapType ¶meters()
const {
return parameters_; }
284 bool MightBeParameterized()
const;
285 bool IsForwardReferenced()
const;
286 bool HasDefaultInitialization(
287 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
288 bool HasDestruction()
const;
293 void AddRawParamValue(
const parser::Keyword *,
ParamValue &&);
303 void Instantiate(
Scope &containingScope);
307 auto iter{parameters_.find(target)};
308 if (iter != parameters_.end()) {
309 return &iter->second;
315 return RawEquals(that) && parameters_ == that.parameters_;
318 return !(*
this == that);
323 std::string AsFortran()
const;
324 std::string VectorTypeAsFortran()
const;
326 Category category()
const {
return category_; }
327 void set_category(Category category) { category_ = category; }
328 bool IsVectorType()
const {
329 return category_ == Category::IntrinsicVector ||
330 category_ == Category::PairVector || category_ == Category::QuadVector;
335 const Symbol &originalTypeSymbol_;
336 const Symbol &typeSymbol_;
337 const Scope *scope_{
nullptr};
339 bool evaluated_{
false};
340 bool instantiated_{
false};
341 RawParameters rawParameters_;
342 ParameterMapType parameters_;
343 Category category_{Category::DerivedType};
345 return &typeSymbol_ == &that.typeSymbol_ &&
346 &originalTypeSymbol_ == &that.originalTypeSymbol_ &&
347 cooked_ == that.cooked_ && rawParameters_ == that.rawParameters_;
349 friend llvm::raw_ostream &operator<<(
378 bool operator!=(
const DeclTypeSpec &that)
const {
return !operator==(that); }
380 Category category()
const {
return category_; }
381 void set_category(Category category) { category_ = category; }
382 bool IsPolymorphic()
const {
383 return category_ == ClassDerived || IsUnlimitedPolymorphic();
385 bool IsUnlimitedPolymorphic()
const {
386 return category_ == TypeStar || category_ == ClassStar;
388 bool IsAssumedType()
const {
return category_ == TypeStar; }
389 bool IsNumeric(TypeCategory)
const;
390 bool IsSequenceType()
const;
394 CHECK(category_ == Character);
395 return std::get<CharacterTypeSpec>(typeSpec_);
398 CHECK(category_ == TypeDerived || category_ == ClassDerived);
399 return std::get<DerivedTypeSpec>(typeSpec_);
402 CHECK(category_ == TypeDerived || category_ == ClassDerived);
403 return std::get<DerivedTypeSpec>(typeSpec_);
411 std::string AsFortran()
const;
419llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const DeclTypeSpec &);
424inline bool ArraySpec::IsExplicitShape()
const {
425 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
427inline bool ArraySpec::CanBeAssumedShape()
const {
428 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isColon(); });
430inline bool ArraySpec::CanBeDeferredShape()
const {
431 return CheckAll([](
const ShapeSpec &x) {
432 return x.lbound().isColon() && x.ubound().isColon();
435inline bool ArraySpec::CanBeImpliedShape()
const {
436 return !IsAssumedRank() &&
437 CheckAll([](
const ShapeSpec &x) {
return x.ubound().isStar(); });
439inline bool ArraySpec::CanBeAssumedSize()
const {
440 return !empty() && !IsAssumedRank() && back().ubound().isStar() &&
441 std::all_of(begin(), end() - 1,
442 [](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
444inline bool ArraySpec::IsAssumedRank()
const {
445 return Rank() == 1 && front().lbound().isStar();
448inline IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
451 return &std::get<NumericTypeSpec>(typeSpec_);
453 return &std::get<LogicalTypeSpec>(typeSpec_);
455 return &std::get<CharacterTypeSpec>(typeSpec_);
460inline const IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic()
const {
461 return const_cast<DeclTypeSpec *
>(
this)->AsIntrinsic();
464inline DerivedTypeSpec *DeclTypeSpec::AsDerived() {
468 return &std::get<DerivedTypeSpec>(typeSpec_);
473inline const DerivedTypeSpec *DeclTypeSpec::AsDerived()
const {
474 return const_cast<DeclTypeSpec *
>(
this)->AsDerived();
Definition: char-block.h:28
Definition: semantics.h:67
Definition: check-expression.h:19