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;
255 template <
typename P>
bool CheckAll(P predicate)
const {
256 return !empty() && std::all_of(begin(), end(), predicate);
259llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ArraySpec &);
263class DerivedTypeSpec {
265 enum class Category {
273 using RawParameter = std::pair<const parser::Keyword *, ParamValue>;
274 using RawParameters = std::vector<RawParameter>;
275 using ParameterMapType = std::map<SourceName, ParamValue>;
276 DerivedTypeSpec(SourceName,
const Symbol &);
277 DerivedTypeSpec(
const DerivedTypeSpec &);
278 DerivedTypeSpec(DerivedTypeSpec &&);
280 const SourceName &name()
const {
return name_; }
281 const Symbol &originalTypeSymbol()
const {
return originalTypeSymbol_; }
282 const Symbol &typeSymbol()
const {
return typeSymbol_; }
283 const Scope *scope()
const {
return scope_; }
285 const Scope *GetScope()
const;
286 void set_scope(
const Scope &);
287 void ReplaceScope(
const Scope &);
288 const RawParameters &rawParameters()
const {
return rawParameters_; }
289 const ParameterMapType ¶meters()
const {
return parameters_; }
291 bool MightBeParameterized()
const;
292 bool IsForwardReferenced()
const;
293 bool HasDefaultInitialization(
294 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
295 std::optional<std::string>
296 ComponentWithDefaultInitialization(
297 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
298 bool HasDestruction()
const;
303 void AddRawParamValue(
const parser::Keyword *,
ParamValue &&);
310 void AddParamValue(SourceName,
ParamValue &&);
314 void Instantiate(
Scope &containingScope);
317 void PrepareForScopeClone();
320 const ParamValue *FindParameter(SourceName target)
const {
321 auto iter{parameters_.find(target)};
322 if (iter != parameters_.end()) {
323 return &iter->second;
328 bool operator==(
const DerivedTypeSpec &that)
const {
329 return RawEquals(that) && parameters_ == that.parameters_;
331 bool operator!=(
const DerivedTypeSpec &that)
const {
332 return !(*
this == that);
336 bool MatchesOrExtends(
const DerivedTypeSpec &)
const;
337 std::string AsFortran()
const;
338 std::string VectorTypeAsFortran()
const;
340 Category category()
const {
return category_; }
341 void set_category(Category category) { category_ = category; }
342 bool IsVectorType()
const {
343 return category_ == Category::IntrinsicVector ||
344 category_ == Category::PairVector || category_ == Category::QuadVector;
346 bool IsEnumerationType()
const {
347 return category_ == Category::EnumerationType;
352 const Symbol &originalTypeSymbol_;
353 const Symbol &typeSymbol_;
354 const Scope *scope_{
nullptr};
356 bool evaluated_{
false};
357 bool instantiated_{
false};
358 RawParameters rawParameters_;
359 ParameterMapType parameters_;
360 Category category_{Category::DerivedType};
361 bool RawEquals(
const DerivedTypeSpec &that)
const {
362 return &typeSymbol_ == &that.typeSymbol_ &&
363 &originalTypeSymbol_ == &that.originalTypeSymbol_ &&
364 cooked_ == that.cooked_ && rawParameters_ == that.rawParameters_;
366 friend llvm::raw_ostream &operator<<(
367 llvm::raw_ostream &,
const DerivedTypeSpec &);
392 DeclTypeSpec(Category);
394 bool operator==(
const DeclTypeSpec &)
const;
395 bool operator!=(
const DeclTypeSpec &that)
const {
return !operator==(that); }
397 Category category()
const {
return category_; }
398 void set_category(Category category) { category_ = category; }
399 bool IsPolymorphic()
const {
400 return category_ == ClassDerived || IsUnlimitedPolymorphic();
402 bool IsUnlimitedPolymorphic()
const {
403 return category_ == TypeStar || category_ == ClassStar;
405 bool IsAssumedType()
const {
return category_ == TypeStar; }
406 bool IsNumeric(TypeCategory)
const;
407 bool IsSequenceType()
const;
411 CHECK(category_ == Character);
412 return std::get<CharacterTypeSpec>(typeSpec_);
415 CHECK(category_ == TypeDerived || category_ == ClassDerived);
416 return std::get<DerivedTypeSpec>(typeSpec_);
419 CHECK(category_ == TypeDerived || category_ == ClassDerived);
420 return std::get<DerivedTypeSpec>(typeSpec_);
428 std::string AsFortran()
const;
436llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const DeclTypeSpec &);
441inline bool ArraySpec::IsExplicitShape()
const {
442 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
444inline bool ArraySpec::CanBeAssumedShape()
const {
445 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isColon(); });
447inline bool ArraySpec::CanBeDeferredShape()
const {
448 return CheckAll([](
const ShapeSpec &x) {
449 return x.lbound().isColon() && x.ubound().isColon();
452inline bool ArraySpec::CanBeImpliedShape()
const {
453 return !IsAssumedRank() &&
454 CheckAll([](
const ShapeSpec &x) {
return x.ubound().isStar(); });
456inline bool ArraySpec::CanBeAssumedSize()
const {
457 return !empty() && !IsAssumedRank() && back().ubound().isStar() &&
458 std::all_of(begin(), end() - 1,
459 [](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
461inline bool ArraySpec::IsAssumedRank()
const {
462 return Rank() == 1 && front().lbound().isStar();
465inline IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
468 return &std::get<NumericTypeSpec>(typeSpec_);
470 return &std::get<LogicalTypeSpec>(typeSpec_);
472 return &std::get<CharacterTypeSpec>(typeSpec_);
477inline const IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic()
const {
478 return const_cast<DeclTypeSpec *
>(
this)->AsIntrinsic();
481inline DerivedTypeSpec *DeclTypeSpec::AsDerived() {
485 return &std::get<DerivedTypeSpec>(typeSpec_);
490inline const DerivedTypeSpec *DeclTypeSpec::AsDerived()
const {
491 return const_cast<DeclTypeSpec *
>(
this)->AsDerived();
Definition semantics.h:67
Definition check-expression.h:19