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"
34std::optional<bool> AreEquivalentInInterface(
const Expr<T> &,
const Expr<T> &);
35extern template std::optional<bool> AreEquivalentInInterface<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);
70 Bound(
const Bound &) =
default;
71 Bound(Bound &&) =
default;
72 Bound &operator=(
const Bound &) =
default;
73 Bound &operator=(Bound &&) =
default;
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) {
99 return ParamValue{Category::Assumed, attr};
101 static ParamValue Deferred(common::TypeParamAttr attr) {
102 return ParamValue{Category::Deferred, attr};
104 ParamValue(
const ParamValue &) =
default;
105 explicit ParamValue(MaybeIntExpr &&, common::TypeParamAttr);
106 explicit ParamValue(SomeIntExpr &&, common::TypeParamAttr attr);
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_; }
112 void SetExplicit(SomeIntExpr &&);
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() &&
124 evaluate::AreEquivalentInInterface(*expr_, *that.expr_)
127 std::string AsFortran()
const;
130 enum class Category { Explicit, Deferred, Assumed };
131 ParamValue(Category category, common::TypeParamAttr attr)
132 : category_{category}, attr_{attr} {}
133 Category category_{Category::Explicit};
134 common::TypeParamAttr attr_{common::TypeParamAttr::Kind};
136 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ParamValue &);
139class IntrinsicTypeSpec {
141 TypeCategory category()
const {
return category_; }
142 const KindExpr &kind()
const {
return kind_; }
143 bool operator==(
const IntrinsicTypeSpec &x)
const {
144 return category_ == x.category_ && kind_ == x.kind_;
146 bool operator!=(
const IntrinsicTypeSpec &x)
const {
return !operator==(x); }
147 std::string AsFortran()
const;
150 IntrinsicTypeSpec(TypeCategory, KindExpr &&);
153 TypeCategory category_;
155 friend llvm::raw_ostream &operator<<(
156 llvm::raw_ostream &os,
const IntrinsicTypeSpec &x);
159class NumericTypeSpec :
public IntrinsicTypeSpec {
161 NumericTypeSpec(TypeCategory category, KindExpr &&kind)
162 : IntrinsicTypeSpec(category, std::move(kind)) {
163 CHECK(common::IsNumericTypeCategory(category));
167class LogicalTypeSpec :
public IntrinsicTypeSpec {
169 explicit LogicalTypeSpec(KindExpr &&kind)
170 : IntrinsicTypeSpec(TypeCategory::Logical, std::move(kind)) {}
173class CharacterTypeSpec :
public IntrinsicTypeSpec {
175 CharacterTypeSpec(
ParamValue &&length, KindExpr &&kind)
176 : IntrinsicTypeSpec(TypeCategory::Character, std::move(kind)),
177 length_{std::move(length)} {}
178 const ParamValue &length()
const {
return length_; }
179 bool operator==(
const CharacterTypeSpec &that)
const {
180 return kind() == that.kind() && length_ == that.length_;
182 std::string AsFortran()
const;
186 friend llvm::raw_ostream &operator<<(
187 llvm::raw_ostream &os,
const CharacterTypeSpec &x);
193 static ShapeSpec MakeExplicit(
Bound &&lb,
Bound &&ub) {
194 return ShapeSpec(std::move(lb), std::move(ub));
197 static const ShapeSpec MakeExplicit(
Bound &&ub) {
198 return MakeExplicit(
Bound{1}, std::move(ub));
201 static ShapeSpec MakeAssumedShape() {
202 return ShapeSpec(
Bound{1}, Bound::Colon());
205 static ShapeSpec MakeAssumedShape(
Bound &&lb) {
206 return ShapeSpec(std::move(lb), Bound::Colon());
209 static ShapeSpec MakeDeferred() {
210 return ShapeSpec(Bound::Colon(), Bound::Colon());
213 static ShapeSpec MakeImplied() {
return ShapeSpec(
Bound{1}, Bound::Star()); }
215 static ShapeSpec MakeImplied(
Bound &&lb) {
216 return ShapeSpec(std::move(lb), Bound::Star());
219 static ShapeSpec MakeAssumedRank() {
220 return ShapeSpec(Bound::Star(), Bound::Star());
223 ShapeSpec(
const ShapeSpec &) =
default;
224 ShapeSpec(ShapeSpec &&) =
default;
225 ShapeSpec &operator=(
const ShapeSpec &) =
default;
226 ShapeSpec &operator=(ShapeSpec &&) =
default;
228 Bound &lbound() {
return lb_; }
229 const Bound &lbound()
const {
return lb_; }
230 Bound &ubound() {
return ub_; }
231 const Bound &ubound()
const {
return ub_; }
234 ShapeSpec(
Bound &&lb,
Bound &&ub) : lb_{std::move(lb)}, ub_{std::move(ub)} {}
237 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ShapeSpec &);
240struct ArraySpec :
public std::vector<ShapeSpec> {
242 int Rank()
const {
return size(); }
247 inline bool IsExplicitShape()
const;
248 inline bool CanBeAssumedShape()
const;
249 inline bool CanBeDeferredShape()
const;
250 inline bool CanBeImpliedShape()
const;
251 inline bool CanBeAssumedSize()
const;
252 inline bool IsAssumedRank()
const;
256 template <
typename P>
bool CheckAll(P predicate)
const {
257 return !empty() && std::all_of(begin(), end(), predicate);
260llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const ArraySpec &);
264class DerivedTypeSpec {
266 enum class Category { DerivedType, IntrinsicVector, PairVector, QuadVector };
268 using RawParameter = std::pair<const parser::Keyword *, ParamValue>;
269 using RawParameters = std::vector<RawParameter>;
270 using ParameterMapType = std::map<SourceName, ParamValue>;
271 DerivedTypeSpec(SourceName,
const Symbol &);
272 DerivedTypeSpec(
const DerivedTypeSpec &);
273 DerivedTypeSpec(DerivedTypeSpec &&);
275 const SourceName &name()
const {
return name_; }
276 const Symbol &originalTypeSymbol()
const {
return originalTypeSymbol_; }
277 const Symbol &typeSymbol()
const {
return typeSymbol_; }
278 const Scope *scope()
const {
return scope_; }
280 const Scope *GetScope()
const;
281 void set_scope(
const Scope &);
282 void ReplaceScope(
const Scope &);
283 const RawParameters &rawParameters()
const {
return rawParameters_; }
284 const ParameterMapType ¶meters()
const {
return parameters_; }
286 bool MightBeParameterized()
const;
287 bool IsForwardReferenced()
const;
288 bool HasDefaultInitialization(
289 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
290 std::optional<std::string>
291 ComponentWithDefaultInitialization(
292 bool ignoreAllocatable =
false,
bool ignorePointer =
true)
const;
293 bool HasDestruction()
const;
298 void AddRawParamValue(
const parser::Keyword *,
ParamValue &&);
304 void AddParamValue(SourceName,
ParamValue &&);
308 void Instantiate(
Scope &containingScope);
311 const ParamValue *FindParameter(SourceName target)
const {
312 auto iter{parameters_.find(target)};
313 if (iter != parameters_.end()) {
314 return &iter->second;
319 bool operator==(
const DerivedTypeSpec &that)
const {
320 return RawEquals(that) && parameters_ == that.parameters_;
322 bool operator!=(
const DerivedTypeSpec &that)
const {
323 return !(*
this == that);
327 bool MatchesOrExtends(
const DerivedTypeSpec &)
const;
328 std::string AsFortran()
const;
329 std::string VectorTypeAsFortran()
const;
331 Category category()
const {
return category_; }
332 void set_category(Category category) { category_ = category; }
333 bool IsVectorType()
const {
334 return category_ == Category::IntrinsicVector ||
335 category_ == Category::PairVector || category_ == Category::QuadVector;
340 const Symbol &originalTypeSymbol_;
341 const Symbol &typeSymbol_;
342 const Scope *scope_{
nullptr};
344 bool evaluated_{
false};
345 bool instantiated_{
false};
346 RawParameters rawParameters_;
347 ParameterMapType parameters_;
348 Category category_{Category::DerivedType};
349 bool RawEquals(
const DerivedTypeSpec &that)
const {
350 return &typeSymbol_ == &that.typeSymbol_ &&
351 &originalTypeSymbol_ == &that.originalTypeSymbol_ &&
352 cooked_ == that.cooked_ && rawParameters_ == that.rawParameters_;
354 friend llvm::raw_ostream &operator<<(
355 llvm::raw_ostream &,
const DerivedTypeSpec &);
380 DeclTypeSpec(Category);
382 bool operator==(
const DeclTypeSpec &)
const;
383 bool operator!=(
const DeclTypeSpec &that)
const {
return !operator==(that); }
385 Category category()
const {
return category_; }
386 void set_category(Category category) { category_ = category; }
387 bool IsPolymorphic()
const {
388 return category_ == ClassDerived || IsUnlimitedPolymorphic();
390 bool IsUnlimitedPolymorphic()
const {
391 return category_ == TypeStar || category_ == ClassStar;
393 bool IsAssumedType()
const {
return category_ == TypeStar; }
394 bool IsNumeric(TypeCategory)
const;
395 bool IsSequenceType()
const;
399 CHECK(category_ == Character);
400 return std::get<CharacterTypeSpec>(typeSpec_);
403 CHECK(category_ == TypeDerived || category_ == ClassDerived);
404 return std::get<DerivedTypeSpec>(typeSpec_);
407 CHECK(category_ == TypeDerived || category_ == ClassDerived);
408 return std::get<DerivedTypeSpec>(typeSpec_);
416 std::string AsFortran()
const;
424llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const DeclTypeSpec &);
429inline bool ArraySpec::IsExplicitShape()
const {
430 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
432inline bool ArraySpec::CanBeAssumedShape()
const {
433 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isColon(); });
435inline bool ArraySpec::CanBeDeferredShape()
const {
436 return CheckAll([](
const ShapeSpec &x) {
437 return x.lbound().isColon() && x.ubound().isColon();
440inline bool ArraySpec::CanBeImpliedShape()
const {
441 return !IsAssumedRank() &&
442 CheckAll([](
const ShapeSpec &x) {
return x.ubound().isStar(); });
444inline bool ArraySpec::CanBeAssumedSize()
const {
445 return !empty() && !IsAssumedRank() && back().ubound().isStar() &&
446 std::all_of(begin(), end() - 1,
447 [](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
449inline bool ArraySpec::IsAssumedRank()
const {
450 return Rank() == 1 && front().lbound().isStar();
453inline IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
456 return &std::get<NumericTypeSpec>(typeSpec_);
458 return &std::get<LogicalTypeSpec>(typeSpec_);
460 return &std::get<CharacterTypeSpec>(typeSpec_);
465inline const IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic()
const {
466 return const_cast<DeclTypeSpec *
>(
this)->AsIntrinsic();
469inline DerivedTypeSpec *DeclTypeSpec::AsDerived() {
473 return &std::get<DerivedTypeSpec>(typeSpec_);
478inline const DerivedTypeSpec *DeclTypeSpec::AsDerived()
const {
479 return const_cast<DeclTypeSpec *
>(
this)->AsDerived();
Definition semantics.h:67
Definition check-expression.h:19