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 &&);
305 void AddParamValue(SourceName,
ParamValue &&);
309 void Instantiate(
Scope &containingScope);
312 const ParamValue *FindParameter(SourceName target)
const {
313 auto iter{parameters_.find(target)};
314 if (iter != parameters_.end()) {
315 return &iter->second;
320 bool operator==(
const DerivedTypeSpec &that)
const {
321 return RawEquals(that) && parameters_ == that.parameters_;
323 bool operator!=(
const DerivedTypeSpec &that)
const {
324 return !(*
this == that);
328 bool MatchesOrExtends(
const DerivedTypeSpec &)
const;
329 std::string AsFortran()
const;
330 std::string VectorTypeAsFortran()
const;
332 Category category()
const {
return category_; }
333 void set_category(Category category) { category_ = category; }
334 bool IsVectorType()
const {
335 return category_ == Category::IntrinsicVector ||
336 category_ == Category::PairVector || category_ == Category::QuadVector;
341 const Symbol &originalTypeSymbol_;
342 const Symbol &typeSymbol_;
343 const Scope *scope_{
nullptr};
345 bool evaluated_{
false};
346 bool instantiated_{
false};
347 RawParameters rawParameters_;
348 ParameterMapType parameters_;
349 Category category_{Category::DerivedType};
350 bool RawEquals(
const DerivedTypeSpec &that)
const {
351 return &typeSymbol_ == &that.typeSymbol_ &&
352 &originalTypeSymbol_ == &that.originalTypeSymbol_ &&
353 cooked_ == that.cooked_ && rawParameters_ == that.rawParameters_;
355 friend llvm::raw_ostream &operator<<(
356 llvm::raw_ostream &,
const DerivedTypeSpec &);
381 DeclTypeSpec(Category);
383 bool operator==(
const DeclTypeSpec &)
const;
384 bool operator!=(
const DeclTypeSpec &that)
const {
return !operator==(that); }
386 Category category()
const {
return category_; }
387 void set_category(Category category) { category_ = category; }
388 bool IsPolymorphic()
const {
389 return category_ == ClassDerived || IsUnlimitedPolymorphic();
391 bool IsUnlimitedPolymorphic()
const {
392 return category_ == TypeStar || category_ == ClassStar;
394 bool IsAssumedType()
const {
return category_ == TypeStar; }
395 bool IsNumeric(TypeCategory)
const;
396 bool IsSequenceType()
const;
400 CHECK(category_ == Character);
401 return std::get<CharacterTypeSpec>(typeSpec_);
404 CHECK(category_ == TypeDerived || category_ == ClassDerived);
405 return std::get<DerivedTypeSpec>(typeSpec_);
408 CHECK(category_ == TypeDerived || category_ == ClassDerived);
409 return std::get<DerivedTypeSpec>(typeSpec_);
417 std::string AsFortran()
const;
425llvm::raw_ostream &operator<<(llvm::raw_ostream &,
const DeclTypeSpec &);
430inline bool ArraySpec::IsExplicitShape()
const {
431 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
433inline bool ArraySpec::CanBeAssumedShape()
const {
434 return CheckAll([](
const ShapeSpec &x) {
return x.ubound().isColon(); });
436inline bool ArraySpec::CanBeDeferredShape()
const {
437 return CheckAll([](
const ShapeSpec &x) {
438 return x.lbound().isColon() && x.ubound().isColon();
441inline bool ArraySpec::CanBeImpliedShape()
const {
442 return !IsAssumedRank() &&
443 CheckAll([](
const ShapeSpec &x) {
return x.ubound().isStar(); });
445inline bool ArraySpec::CanBeAssumedSize()
const {
446 return !empty() && !IsAssumedRank() && back().ubound().isStar() &&
447 std::all_of(begin(), end() - 1,
448 [](
const ShapeSpec &x) {
return x.ubound().isExplicit(); });
450inline bool ArraySpec::IsAssumedRank()
const {
451 return Rank() == 1 && front().lbound().isStar();
454inline IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() {
457 return &std::get<NumericTypeSpec>(typeSpec_);
459 return &std::get<LogicalTypeSpec>(typeSpec_);
461 return &std::get<CharacterTypeSpec>(typeSpec_);
466inline const IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic()
const {
467 return const_cast<DeclTypeSpec *
>(
this)->AsIntrinsic();
470inline DerivedTypeSpec *DeclTypeSpec::AsDerived() {
474 return &std::get<DerivedTypeSpec>(typeSpec_);
479inline const DerivedTypeSpec *DeclTypeSpec::AsDerived()
const {
480 return const_cast<DeclTypeSpec *
>(
this)->AsDerived();
Definition semantics.h:67
Definition check-expression.h:19