9#ifndef FORTRAN_SEMANTICS_TYPE_H_
10#define FORTRAN_SEMANTICS_TYPE_H_
12#include "flang/Common/idioms.h"
13#include "flang/Evaluate/expression.h"
14#include "flang/Parser/char-block.h"
15#include "flang/Support/Fortran.h"
33std::optional<bool> AreEquivalentInInterface(
const Expr<T> &,
const Expr<T> &);
34extern template std::optional<bool> AreEquivalentInInterface<SomeInteger>(
38namespace Fortran::semantics {
41class SemanticsContext;
46using SourceName = parser::CharBlock;
47using TypeCategory = common::TypeCategory;
48using SomeExpr = evaluate::Expr<evaluate::SomeType>;
49using MaybeExpr = std::optional<SomeExpr>;
50using SomeIntExpr = evaluate::Expr<evaluate::SomeInteger>;
51using MaybeIntExpr = std::optional<SomeIntExpr>;
52using SubscriptIntExpr = evaluate::Expr<evaluate::SubscriptInteger>;
53using MaybeSubscriptIntExpr = std::optional<SubscriptIntExpr>;
54using KindExpr = SubscriptIntExpr;
65 static Bound Star() {
return Bound(Category::Star); }
66 static Bound Colon() {
return Bound(Category::Colon); }
67 explicit Bound(MaybeSubscriptIntExpr &&expr) : expr_{std::move(expr)} {}
68 explicit Bound(common::ConstantSubscript bound);
69 Bound(
const Bound &) =
default;
70 Bound(Bound &&) =
default;
71 Bound &operator=(
const Bound &) =
default;
72 Bound &operator=(Bound &&) =
default;
73 bool isExplicit()
const {
return category_ == Category::Explicit; }
74 bool isStar()
const {
return category_ == Category::Star; }
75 bool isColon()
const {
return category_ == Category::Colon; }
76 MaybeSubscriptIntExpr &GetExplicit() {
return expr_; }
77 const MaybeSubscriptIntExpr &GetExplicit()
const {
return expr_; }
78 void SetExplicit(MaybeSubscriptIntExpr &&expr) {
80 expr_ = std::move(expr);
84 enum class Category { Explicit, Star, Colon };
85 Bound(Category category) : category_{category} {}
86 Bound(Category category, MaybeSubscriptIntExpr &&expr)
87 : category_{category}, expr_{std::move(expr)} {}
88 Category category_{Category::Explicit};
89 MaybeSubscriptIntExpr expr_;
90 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const Bound &);
97 static ParamValue Assumed(common::TypeParamAttr attr) {
98 return ParamValue{Category::Assumed, attr};
100 static ParamValue Deferred(common::TypeParamAttr attr) {
101 return ParamValue{Category::Deferred, attr};
103 ParamValue(
const ParamValue &) =
default;
104 explicit ParamValue(MaybeIntExpr &&, common::TypeParamAttr);
105 explicit ParamValue(SomeIntExpr &&, common::TypeParamAttr attr);
106 explicit ParamValue(common::ConstantSubscript, common::TypeParamAttr attr);
107 bool isExplicit()
const {
return category_ == Category::Explicit; }
108 bool isAssumed()
const {
return category_ == Category::Assumed; }
109 bool isDeferred()
const {
return category_ == Category::Deferred; }
110 const MaybeIntExpr &GetExplicit()
const {
return expr_; }
111 void SetExplicit(SomeIntExpr &&);
112 bool isKind()
const {
return attr_ == common::TypeParamAttr::Kind; }
113 bool isLen()
const {
return attr_ == common::TypeParamAttr::Len; }
114 void set_attr(common::TypeParamAttr attr) { attr_ = attr; }
115 bool operator==(
const ParamValue &that)
const {
116 return category_ == that.category_ && expr_ == that.expr_;
118 bool operator!=(
const ParamValue &that)
const {
return !(*
this == that); }
119 bool IsEquivalentInInterface(
const ParamValue &that)
const {
120 return (category_ == that.category_ &&
121 expr_.has_value() == that.expr_.has_value() &&
123 evaluate::AreEquivalentInInterface(*expr_, *that.expr_)
126 std::string AsFortran()
const;
129 enum class Category { Explicit, Deferred, Assumed };
130 ParamValue(Category category, common::TypeParamAttr attr)
131 : category_{category}, attr_{attr} {}
132 Category category_{Category::Explicit};
133 common::TypeParamAttr attr_{common::TypeParamAttr::Kind};
135 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ParamValue &);
138class IntrinsicTypeSpec {
140 TypeCategory category()
const {
return category_; }
141 const KindExpr &kind()
const {
return kind_; }
142 bool operator==(
const IntrinsicTypeSpec &x)
const {
143 return category_ == x.category_ && kind_ == x.kind_;
145 bool operator!=(
const IntrinsicTypeSpec &x)
const {
return !operator==(x); }
146 std::string AsFortran()
const;
149 IntrinsicTypeSpec(TypeCategory, KindExpr &&);
152 TypeCategory category_;
154 friend llvm::raw_ostream &operator<<(
155 llvm::raw_ostream &os,
const IntrinsicTypeSpec &x);
158class NumericTypeSpec :
public IntrinsicTypeSpec {
160 NumericTypeSpec(TypeCategory category, KindExpr &&kind)
161 : IntrinsicTypeSpec(category, std::move(kind)) {
162 CHECK(common::IsNumericTypeCategory(category));
166class LogicalTypeSpec :
public IntrinsicTypeSpec {
168 explicit LogicalTypeSpec(KindExpr &&kind)
169 : IntrinsicTypeSpec(TypeCategory::Logical, std::move(kind)) {}
172class CharacterTypeSpec :
public IntrinsicTypeSpec {
174 CharacterTypeSpec(
ParamValue &&length, KindExpr &&kind)
175 : IntrinsicTypeSpec(TypeCategory::Character, std::move(kind)),
176 length_{std::move(length)} {}
177 const ParamValue &length()
const {
return length_; }
178 bool operator==(
const CharacterTypeSpec &that)
const {
179 return kind() == that.kind() && length_ == that.length_;
181 std::string AsFortran()
const;
185 friend llvm::raw_ostream &operator<<(
186 llvm::raw_ostream &os,
const CharacterTypeSpec &x);
192 static ShapeSpec MakeExplicit(
Bound &&lb,
Bound &&ub) {
193 return ShapeSpec(std::move(lb), std::move(ub));
196 static const ShapeSpec MakeExplicit(
Bound &&ub) {
197 return MakeExplicit(
Bound{1}, std::move(ub));
200 static ShapeSpec MakeAssumedShape() {
201 return ShapeSpec(
Bound{1}, Bound::Colon());
204 static ShapeSpec MakeAssumedShape(
Bound &&lb) {
205 return ShapeSpec(std::move(lb), Bound::Colon());
208 static ShapeSpec MakeDeferred() {
209 return ShapeSpec(Bound::Colon(), Bound::Colon());
212 static ShapeSpec MakeImplied() {
return ShapeSpec(
Bound{1}, Bound::Star()); }
214 static ShapeSpec MakeImplied(
Bound &&lb) {
215 return ShapeSpec(std::move(lb), Bound::Star());
218 static ShapeSpec MakeAssumedRank() {
219 return ShapeSpec(Bound::Star(), Bound::Star());
222 ShapeSpec(
const ShapeSpec &) =
default;
223 ShapeSpec(ShapeSpec &&) =
default;
224 ShapeSpec &operator=(
const ShapeSpec &) =
default;
225 ShapeSpec &operator=(ShapeSpec &&) =
default;
227 Bound &lbound() {
return lb_; }
228 const Bound &lbound()
const {
return lb_; }
229 Bound &ubound() {
return ub_; }
230 const Bound &ubound()
const {
return ub_; }
233 ShapeSpec(
Bound &&lb,
Bound &&ub) : lb_{std::move(lb)}, ub_{std::move(ub)} {}
236 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ShapeSpec &);
239struct ArraySpec :
public std::vector<ShapeSpec> {
241 int Rank()
const {
return size(); }
246 inline bool IsExplicitShape()
const;
247 inline bool CanBeAssumedShape()
const;
248 inline bool CanBeDeferredShape()
const;
249 inline bool CanBeImpliedShape()
const;
250 inline bool CanBeAssumedSize()
const;
251 inline bool IsAssumedRank()
const;
257 bool isFromRankOneBounds()
const {
258 return lboundIsRankOne_ || uboundIsRankOne_;
260 bool lboundIsRankOne()
const {
return lboundIsRankOne_; }
261 bool uboundIsRankOne()
const {
return uboundIsRankOne_; }
262 void set_rankOneBounds(
bool lower,
bool upper) {
263 lboundIsRankOne_ =
lower;
264 uboundIsRankOne_ = upper;
267 std::vector<ShapeSpec>::clear();
268 lboundIsRankOne_ = uboundIsRankOne_ =
false;
272 bool lboundIsRankOne_{
false};
273 bool uboundIsRankOne_{
false};
275 template <
typename P>
bool CheckAll(P predicate)
const {
276 return !empty() && std::all_of(begin(), end(), predicate);
279llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ArraySpec &);
283class DerivedTypeSpec {
285 enum class Category {
293 using RawParameter = std::pair<const parser::Keyword *, ParamValue>;
294 using RawParameters = std::vector<RawParameter>;
295 using ParameterMapType = std::map<SourceName, ParamValue>;
296 DerivedTypeSpec(SourceName,
const Symbol &);
297 DerivedTypeSpec(
const DerivedTypeSpec &);
298 DerivedTypeSpec(DerivedTypeSpec &&);
300 const SourceName &name()
const {
return name_; }
301 const Symbol &originalTypeSymbol()
const {
return originalTypeSymbol_; }
302 const Symbol &typeSymbol()
const {
return typeSymbol_; }
303 const Scope *scope()
const {
return scope_; }
305 const Scope *GetScope()
const;
306 void set_scope(
const Scope &);
307 void ReplaceScope(
const Scope &);
308 const RawParameters &rawParameters()
const {
return rawParameters_; }
309 const ParameterMapType ¶meters()
const {
return parameters_; }
311 bool MightBeParameterized()
const;
312 bool IsForwardReferenced()
const;
313 bool HasDefaultInitialization(
314 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
315 std::optional<std::string>
316 ComponentWithDefaultInitialization(
317 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
318 bool HasDestruction()
const;
323 void AddRawParamValue(
const parser::Keyword *,
ParamValue &&);
330 void AddParamValue(SourceName,
ParamValue &&);
334 void Instantiate(
Scope &containingScope);
337 void PrepareForScopeClone();
340 const ParamValue *FindParameter(SourceName target)
const {
341 auto iter{parameters_.find(target)};
342 if (iter != parameters_.end()) {
343 return &iter->second;
348 bool operator==(
const DerivedTypeSpec &that)
const {
349 return RawEquals(that) && parameters_ == that.parameters_;
351 bool operator!=(
const DerivedTypeSpec &that)
const {
352 return !(*
this == that);
356 bool MatchesOrExtends(
const DerivedTypeSpec &)
const;
357 std::string AsFortran()
const;
358 std::string VectorTypeAsFortran()
const;
360 Category category()
const {
return category_; }
361 void set_category(Category category) { category_ = category; }
362 bool IsVectorType()
const {
363 return category_ == Category::IntrinsicVector ||
364 category_ == Category::PairVector || category_ == Category::QuadVector;
366 bool IsEnumerationType()
const {
367 return category_ == Category::EnumerationType;
372 const Symbol &originalTypeSymbol_;
373 const Symbol &typeSymbol_;
374 const Scope *scope_{
nullptr};
376 bool evaluated_{
false};
377 bool instantiated_{
false};
378 RawParameters rawParameters_;
379 ParameterMapType parameters_;
380 Category category_{Category::DerivedType};
381 bool RawEquals(
const DerivedTypeSpec &that)
const {
382 return &typeSymbol_ == &that.typeSymbol_ &&
383 &originalTypeSymbol_ == &that.originalTypeSymbol_ &&
384 cooked_ == that.cooked_ && rawParameters_ == that.rawParameters_;
386 friend llvm::raw_ostream &operator<<(
387 llvm::raw_ostream &,
const DerivedTypeSpec &);
412 DeclTypeSpec(Category);
414 bool operator==(
const DeclTypeSpec &)
const;
415 bool operator!=(
const DeclTypeSpec &that)
const {
return !operator==(that); }
417 Category category()
const {
return category_; }
418 void set_category(Category category) { category_ = category; }
419 bool IsPolymorphic()
const {
420 return category_ == ClassDerived || IsUnlimitedPolymorphic();
422 bool IsUnlimitedPolymorphic()
const {
423 return category_ == TypeStar || category_ == ClassStar;
425 bool IsAssumedType()
const {
return category_ == TypeStar; }
426 bool IsNumeric(TypeCategory)
const;
427 bool IsSequenceType()
const;
431 CHECK(category_ == Character);
432 return std::get<CharacterTypeSpec>(typeSpec_);
435 CHECK(category_ == TypeDerived || category_ == ClassDerived);
436 return std::get<DerivedTypeSpec>(typeSpec_);
439 CHECK(category_ == TypeDerived || category_ == ClassDerived);
440 return std::get<DerivedTypeSpec>(typeSpec_);
448 std::string AsFortran()
const;
456llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const DeclTypeSpec &);
461inline bool ArraySpec::IsExplicitShape()
const {
462 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
464inline bool ArraySpec::CanBeAssumedShape()
const {
465 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isColon(); });
467inline bool ArraySpec::CanBeDeferredShape()
const {
468 return CheckAll([](
const ShapeSpec &x) {
469 return x.lbound().isColon() && x.ubound().isColon();
472inline bool ArraySpec::CanBeImpliedShape()
const {
473 return !IsAssumedRank() &&
474 CheckAll([](
const ShapeSpec &x) {
return x.ubound().isStar(); });
476inline bool ArraySpec::CanBeAssumedSize()
const {
477 return !empty() && !IsAssumedRank() && back().ubound().isStar() &&
478 std::all_of(begin(), end() - 1,
479 [](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
481inline bool ArraySpec::IsAssumedRank()
const {
482 return Rank() == 1 && front().lbound().isStar();
485inline IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
488 return &std::get<NumericTypeSpec>(typeSpec_);
490 return &std::get<LogicalTypeSpec>(typeSpec_);
492 return &std::get<CharacterTypeSpec>(typeSpec_);
497inline const IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic()
const {
498 return const_cast<DeclTypeSpec *
>(
this)->AsIntrinsic();
501inline DerivedTypeSpec *DeclTypeSpec::AsDerived() {
505 return &std::get<DerivedTypeSpec>(typeSpec_);
510inline const DerivedTypeSpec *DeclTypeSpec::AsDerived()
const {
511 return const_cast<DeclTypeSpec *
>(
this)->AsDerived();
Definition semantics.h:71
Definition ParserActions.h:24
Definition check-expression.h:19