9#ifndef FORTRAN_EVALUATE_TYPE_H_
10#define FORTRAN_EVALUATE_TYPE_H_
21#include "formatting.h"
25#include "flang/Common/idioms.h"
26#include "flang/Common/real.h"
27#include "flang/Common/template.h"
28#include "flang/Common/type-kinds.h"
29#include "flang/Support/Fortran-features.h"
30#include "flang/Support/Fortran.h"
37namespace Fortran::semantics {
46bool IsDescriptor(
const Symbol &);
47bool IsPassedViaDescriptor(
const Symbol &);
52using common::TypeCategory;
57template <TypeCategory CATEGORY,
int KIND = 0>
class Type;
76 constexpr DynamicType(TypeCategory cat,
int k) : category_{cat}, kind_{k} {
77 CHECK(common::IsValidKindOfIntrinsicType(category_, kind_));
82 constexpr DynamicType(
int k, std::int64_t len)
83 : category_{TypeCategory::Character}, kind_{k}, knownLength_{
85 CHECK(common::IsValidKindOfIntrinsicType(category_, kind_));
87 explicit constexpr DynamicType(
89 : category_{TypeCategory::Derived}, derived_{&dt} {
94 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(DynamicType)
100 static constexpr DynamicType TypelessIntrinsicArgument() {
102 result.category_ = TypeCategory::Integer;
103 result.kind_ = TypelessKind;
107 static constexpr DynamicType UnlimitedPolymorphic() {
109 result.category_ = TypeCategory::Derived;
110 result.kind_ = ClassKind;
111 result.derived_ =
nullptr;
115 static constexpr DynamicType AssumedType() {
117 result.category_ = TypeCategory::Derived;
118 result.kind_ = AssumedTypeKind;
119 result.derived_ =
nullptr;
124 bool operator==(
const DynamicType &)
const;
125 bool operator!=(
const DynamicType &that)
const {
return !(*
this == that); }
127 constexpr TypeCategory category()
const {
return category_; }
128 constexpr int kind()
const {
133 return charLengthParamValue_;
135 constexpr std::optional<std::int64_t> knownLength()
const {
136#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 7
137 if (knownLength_ < 0) {
143 std::optional<Expr<SubscriptInteger>> GetCharLength()
const;
146 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
FoldingContext &,
148 std::optional<std::int64_t> charLength = std::nullopt)
const;
150 std::string AsFortran()
const;
151 std::string AsFortran(std::string &&charLenExpr)
const;
152 DynamicType ResultTypeForMultiply(
const DynamicType &)
const;
154 bool IsAssumedLengthCharacter()
const;
155 bool IsNonConstantLengthCharacter()
const;
156 bool IsTypelessIntrinsicArgument()
const;
157 constexpr bool IsAssumedType()
const {
158 return kind_ == AssumedTypeKind;
160 constexpr bool IsPolymorphic()
const {
161 return kind_ == ClassKind || IsAssumedType();
163 constexpr bool IsUnlimitedPolymorphic()
const {
164 return IsPolymorphic() && !derived_;
166 bool IsLengthlessIntrinsicType()
const;
168 return DEREF(derived_);
171 bool RequiresDescriptor()
const;
172 bool HasDeferredTypeParameter()
const;
173 bool HasDeferredOrAssumedTypeParameter()
const;
180 bool IsTkCompatibleWith(
const DynamicType &)
const;
181 bool IsTkCompatibleWith(
const DynamicType &, common::IgnoreTKRSet)
const;
185 bool IsTkLenCompatibleWith(
const DynamicType &)
const;
188 std::optional<bool> ExtendsTypeOf(
const DynamicType &)
const;
190 std::optional<bool> SameTypeAs(
const DynamicType &)
const;
194 bool IsEquivalentTo(
const DynamicType &)
const;
201 template <
typename A>
static std::optional<DynamicType> From(
const A &x) {
204 template <
typename A>
static std::optional<DynamicType> From(
const A *p) {
211 template <
typename A>
212 static std::optional<DynamicType> From(
const std::optional<A> &x) {
224 DynamicType DropNonConstantCharacterLength()
const;
232 AssumedTypeKind = -3,
235 constexpr DynamicType() {}
237 TypeCategory category_{TypeCategory::Derived};
240#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 7
242 std::int64_t knownLength_{-1};
244 std::optional<std::int64_t> knownLength_;
252 const std::optional<DynamicType> &);
256template <TypeCategory CATEGORY,
int KIND = 0>
struct TypeBase {
257 static constexpr TypeCategory category{CATEGORY};
258 static constexpr int kind{KIND};
259 constexpr bool operator==(
const TypeBase &)
const {
return true; }
260 static constexpr DynamicType GetType() {
return {category, kind}; }
261 static std::string AsFortran() {
return GetType().AsFortran(); }
265class Type<TypeCategory::Integer, KIND>
266 :
public TypeBase<TypeCategory::Integer, KIND> {
272class Type<TypeCategory::Unsigned, KIND>
273 :
public TypeBase<TypeCategory::Unsigned, KIND> {
275 using Scalar = value::Integer<8 * KIND>;
283 constexpr bool isFromInexactLiteralConversion()
const {
284 return isFromInexactLiteralConversion_;
286 void set_isFromInexactLiteralConversion(
bool yes =
true) {
287 isFromInexactLiteralConversion_ = yes;
291 bool isFromInexactLiteralConversion_{
false};
295class Type<TypeCategory::Real, KIND>
296 :
public TypeBase<TypeCategory::Real, KIND>,
299 static constexpr int precision{common::PrecisionOfRealKind(KIND)};
300 static constexpr int bits{common::BitsForBinaryPrecision(precision)};
302 value::Real<std::conditional_t<precision == 64,
303 value::X87IntegerContainer, value::Integer<bits>>,
309class Type<TypeCategory::Complex, KIND>
310 :
public TypeBase<TypeCategory::Complex, KIND>,
313 using Part = Type<TypeCategory::Real, KIND>;
314 using Scalar = value::Complex<typename Part::Scalar>;
318class Type<TypeCategory::Character, 1>
319 :
public TypeBase<TypeCategory::Character, 1> {
321 using Scalar = std::string;
325class Type<TypeCategory::Character, 2>
326 :
public TypeBase<TypeCategory::Character, 2> {
328 using Scalar = std::u16string;
332class Type<TypeCategory::Character, 4>
333 :
public TypeBase<TypeCategory::Character, 4> {
335 using Scalar = std::u32string;
339class Type<TypeCategory::Logical, KIND>
340 :
public TypeBase<TypeCategory::Logical, KIND> {
348template <TypeCategory CATEGORY,
typename T>
349using SameKind = Type<CATEGORY, std::decay_t<T>::kind>;
353using IndirectSubscriptIntegerExpr =
354 common::CopyableIndirection<Expr<SubscriptInteger>>;
359template <TypeCategory CATEGORY,
int KIND>
360using CategoryKindTuple =
361 std::conditional_t<common::IsValidKindOfIntrinsicType(CATEGORY, KIND),
362 std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
364template <TypeCategory CATEGORY,
int... KINDS>
365using CategoryTypesHelper =
366 common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>;
368template <TypeCategory CATEGORY>
369using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>;
371using IntegerTypes = CategoryTypes<TypeCategory::Integer>;
372using RealTypes = CategoryTypes<TypeCategory::Real>;
373using ComplexTypes = CategoryTypes<TypeCategory::Complex>;
374using CharacterTypes = CategoryTypes<TypeCategory::Character>;
375using LogicalTypes = CategoryTypes<TypeCategory::Logical>;
376using UnsignedTypes = CategoryTypes<TypeCategory::Unsigned>;
378using FloatingTypes = common::CombineTuples<RealTypes, ComplexTypes>;
380 common::CombineTuples<IntegerTypes, FloatingTypes, UnsignedTypes>;
381using RelationalTypes = common::CombineTuples<IntegerTypes, RealTypes,
382 CharacterTypes, UnsignedTypes>;
383using AllIntrinsicTypes =
384 common::CombineTuples<NumericTypes, CharacterTypes, LogicalTypes>;
385using LengthlessIntrinsicTypes =
386 common::CombineTuples<NumericTypes, LogicalTypes>;
390constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>};
396constexpr bool IsLengthlessIntrinsicType{
397 common::HasMember<T, LengthlessIntrinsicTypes>};
401 static constexpr TypeCategory category{CATEGORY};
402 constexpr bool operator==(
const SomeKind &)
const {
return true; }
403 static std::string AsFortran() {
404 return "Some"s + std::string{common::EnumToString(category)};
408using NumericCategoryTypes =
411using AllIntrinsicCategoryTypes =
419 static std::string AsFortran() {
return "SomeType"s; }
425template <>
class SomeKind<TypeCategory::Derived> {
427 static constexpr TypeCategory category{TypeCategory::Derived};
428 using Scalar = StructureConstructor;
430 constexpr SomeKind() {}
431 constexpr explicit SomeKind(
const semantics::DerivedTypeSpec &dts)
432 : derivedTypeSpec_{&dts} {}
433 constexpr explicit SomeKind(
const DynamicType &dt)
434 : SomeKind(dt.GetDerivedTypeSpec()) {}
435 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(SomeKind)
437 bool IsUnlimitedPolymorphic()
const {
return !derivedTypeSpec_; }
438 constexpr DynamicType GetType()
const {
439 if (!derivedTypeSpec_) {
440 return DynamicType::UnlimitedPolymorphic();
442 return DynamicType{*derivedTypeSpec_};
445 const semantics::DerivedTypeSpec &derivedTypeSpec()
const {
446 CHECK(derivedTypeSpec_);
447 return *derivedTypeSpec_;
449 bool operator==(
const SomeKind &)
const;
450 std::string AsFortran()
const;
453 const semantics::DerivedTypeSpec *derivedTypeSpec_{
nullptr};
463using SomeCategory = std::tuple<SomeInteger, SomeReal, SomeComplex,
464 SomeCharacter, SomeLogical, SomeUnsigned, SomeDerived>;
467 common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
469template <
typename T>
using Scalar =
typename std::decay_t<T>::Scalar;
476 static constexpr bool value() {
477 return std::is_same_v<std::decay_t<CONST>,
478 std::decay_t<typename T::Scalar>>;
481 static constexpr int index{
482 common::SearchMembers<Predicate, AllIntrinsicTypes>};
483 using type = std::conditional_t<index >= 0,
484 std::tuple_element_t<index, AllIntrinsicTypes>,
void>;
487template <
typename CONST>
using TypeOf =
typename TypeOfHelper<CONST>::type;
489int SelectedCharKind(
const std::string &,
int defaultKind);
496std::optional<DynamicType> ComparisonType(
497 const DynamicType &,
const DynamicType &);
500std::optional<bool> IsInteroperableIntrinsicType(
const DynamicType &,
502 bool checkCharLength =
true);
503bool IsCUDAIntrinsicType(
const DynamicType &);
507bool AreSameDerivedType(
509bool AreSameDerivedTypeIgnoringTypeParameters(
511bool AreSameDerivedTypeIgnoringSequence(
515#define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \
516 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16)
517#define EXPAND_FOR_EACH_REAL_KIND(M, P, S) \
518 M(P, S, 2) M(P, S, 3) M(P, S, 4) M(P, S, 8) M(P, S, 10) M(P, S, 16)
519#define EXPAND_FOR_EACH_COMPLEX_KIND(M, P, S) EXPAND_FOR_EACH_REAL_KIND(M, P, S)
520#define EXPAND_FOR_EACH_CHARACTER_KIND(M, P, S) M(P, S, 1) M(P, S, 2) M(P, S, 4)
521#define EXPAND_FOR_EACH_LOGICAL_KIND(M, P, S) \
522 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8)
523#define EXPAND_FOR_EACH_UNSIGNED_KIND EXPAND_FOR_EACH_INTEGER_KIND
525#define FOR_EACH_INTEGER_KIND_HELP(PREFIX, SUFFIX, K) \
526 PREFIX<Type<TypeCategory::Integer, K>> SUFFIX;
527#define FOR_EACH_REAL_KIND_HELP(PREFIX, SUFFIX, K) \
528 PREFIX<Type<TypeCategory::Real, K>> SUFFIX;
529#define FOR_EACH_COMPLEX_KIND_HELP(PREFIX, SUFFIX, K) \
530 PREFIX<Type<TypeCategory::Complex, K>> SUFFIX;
531#define FOR_EACH_CHARACTER_KIND_HELP(PREFIX, SUFFIX, K) \
532 PREFIX<Type<TypeCategory::Character, K>> SUFFIX;
533#define FOR_EACH_LOGICAL_KIND_HELP(PREFIX, SUFFIX, K) \
534 PREFIX<Type<TypeCategory::Logical, K>> SUFFIX;
535#define FOR_EACH_UNSIGNED_KIND_HELP(PREFIX, SUFFIX, K) \
536 PREFIX<Type<TypeCategory::Unsigned, K>> SUFFIX;
538#define FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
539 EXPAND_FOR_EACH_INTEGER_KIND(FOR_EACH_INTEGER_KIND_HELP, PREFIX, SUFFIX)
540#define FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
541 EXPAND_FOR_EACH_REAL_KIND(FOR_EACH_REAL_KIND_HELP, PREFIX, SUFFIX)
542#define FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
543 EXPAND_FOR_EACH_COMPLEX_KIND(FOR_EACH_COMPLEX_KIND_HELP, PREFIX, SUFFIX)
544#define FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX) \
545 EXPAND_FOR_EACH_CHARACTER_KIND(FOR_EACH_CHARACTER_KIND_HELP, PREFIX, SUFFIX)
546#define FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \
547 EXPAND_FOR_EACH_LOGICAL_KIND(FOR_EACH_LOGICAL_KIND_HELP, PREFIX, SUFFIX)
548#define FOR_EACH_UNSIGNED_KIND(PREFIX, SUFFIX) \
549 EXPAND_FOR_EACH_UNSIGNED_KIND(FOR_EACH_UNSIGNED_KIND_HELP, PREFIX, SUFFIX)
551#define FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
552 FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
553 FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
554 FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
555 FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \
556 FOR_EACH_UNSIGNED_KIND(PREFIX, SUFFIX)
557#define FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
558 FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
559 FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX)
560#define FOR_EACH_SPECIFIC_TYPE(PREFIX, SUFFIX) \
561 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
562 PREFIX<SomeDerived> SUFFIX;
564#define FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) \
565 PREFIX<SomeInteger> SUFFIX; \
566 PREFIX<SomeReal> SUFFIX; \
567 PREFIX<SomeComplex> SUFFIX; \
568 PREFIX<SomeCharacter> SUFFIX; \
569 PREFIX<SomeLogical> SUFFIX; \
570 PREFIX<SomeUnsigned> SUFFIX; \
571 PREFIX<SomeDerived> SUFFIX; \
572 PREFIX<SomeType> SUFFIX;
573#define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \
574 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
575 FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX)
Definition Fortran-features.h:97
Definition expression.h:782