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;
179 bool IsTkCompatibleWith(
const DynamicType &)
const;
180 bool IsTkCompatibleWith(
const DynamicType &, common::IgnoreTKRSet)
const;
184 bool IsTkLenCompatibleWith(
const DynamicType &)
const;
187 std::optional<bool> ExtendsTypeOf(
const DynamicType &)
const;
189 std::optional<bool> SameTypeAs(
const DynamicType &)
const;
193 bool IsEquivalentTo(
const DynamicType &)
const;
200 template <
typename A>
static std::optional<DynamicType> From(
const A &x) {
203 template <
typename A>
static std::optional<DynamicType> From(
const A *p) {
210 template <
typename A>
211 static std::optional<DynamicType> From(
const std::optional<A> &x) {
223 DynamicType DropNonConstantCharacterLength()
const;
231 AssumedTypeKind = -3,
234 constexpr DynamicType() {}
236 TypeCategory category_{TypeCategory::Derived};
239#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 7
241 std::int64_t knownLength_{-1};
243 std::optional<std::int64_t> knownLength_;
251 const std::optional<DynamicType> &);
255template <TypeCategory CATEGORY,
int KIND = 0>
struct TypeBase {
256 static constexpr TypeCategory category{CATEGORY};
257 static constexpr int kind{KIND};
258 constexpr bool operator==(
const TypeBase &)
const {
return true; }
259 static constexpr DynamicType GetType() {
return {category, kind}; }
260 static std::string AsFortran() {
return GetType().AsFortran(); }
264class Type<TypeCategory::Integer, KIND>
265 :
public TypeBase<TypeCategory::Integer, KIND> {
271class Type<TypeCategory::Unsigned, KIND>
272 :
public TypeBase<TypeCategory::Unsigned, KIND> {
274 using Scalar = value::Integer<8 * KIND>;
282 constexpr bool isFromInexactLiteralConversion()
const {
283 return isFromInexactLiteralConversion_;
285 void set_isFromInexactLiteralConversion(
bool yes =
true) {
286 isFromInexactLiteralConversion_ = yes;
290 bool isFromInexactLiteralConversion_{
false};
294class Type<TypeCategory::Real, KIND>
295 :
public TypeBase<TypeCategory::Real, KIND>,
298 static constexpr int precision{common::PrecisionOfRealKind(KIND)};
299 static constexpr int bits{common::BitsForBinaryPrecision(precision)};
301 value::Real<std::conditional_t<precision == 64,
302 value::X87IntegerContainer, value::Integer<bits>>,
308class Type<TypeCategory::Complex, KIND>
309 :
public TypeBase<TypeCategory::Complex, KIND>,
312 using Part = Type<TypeCategory::Real, KIND>;
313 using Scalar = value::Complex<typename Part::Scalar>;
317class Type<TypeCategory::Character, 1>
318 :
public TypeBase<TypeCategory::Character, 1> {
320 using Scalar = std::string;
324class Type<TypeCategory::Character, 2>
325 :
public TypeBase<TypeCategory::Character, 2> {
327 using Scalar = std::u16string;
331class Type<TypeCategory::Character, 4>
332 :
public TypeBase<TypeCategory::Character, 4> {
334 using Scalar = std::u32string;
338class Type<TypeCategory::Logical, KIND>
339 :
public TypeBase<TypeCategory::Logical, KIND> {
347template <TypeCategory CATEGORY,
typename T>
348using SameKind = Type<CATEGORY, std::decay_t<T>::kind>;
352using IndirectSubscriptIntegerExpr =
353 common::CopyableIndirection<Expr<SubscriptInteger>>;
358template <TypeCategory CATEGORY,
int KIND>
359using CategoryKindTuple =
360 std::conditional_t<common::IsValidKindOfIntrinsicType(CATEGORY, KIND),
361 std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
363template <TypeCategory CATEGORY,
int... KINDS>
364using CategoryTypesHelper =
365 common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>;
367template <TypeCategory CATEGORY>
368using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>;
370using IntegerTypes = CategoryTypes<TypeCategory::Integer>;
371using RealTypes = CategoryTypes<TypeCategory::Real>;
372using ComplexTypes = CategoryTypes<TypeCategory::Complex>;
373using CharacterTypes = CategoryTypes<TypeCategory::Character>;
374using LogicalTypes = CategoryTypes<TypeCategory::Logical>;
375using UnsignedTypes = CategoryTypes<TypeCategory::Unsigned>;
377using FloatingTypes = common::CombineTuples<RealTypes, ComplexTypes>;
379 common::CombineTuples<IntegerTypes, FloatingTypes, UnsignedTypes>;
380using RelationalTypes = common::CombineTuples<IntegerTypes, RealTypes,
381 CharacterTypes, UnsignedTypes>;
382using AllIntrinsicTypes =
383 common::CombineTuples<NumericTypes, CharacterTypes, LogicalTypes>;
384using LengthlessIntrinsicTypes =
385 common::CombineTuples<NumericTypes, LogicalTypes>;
389constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>};
395constexpr bool IsLengthlessIntrinsicType{
396 common::HasMember<T, LengthlessIntrinsicTypes>};
400 static constexpr TypeCategory category{CATEGORY};
401 constexpr bool operator==(
const SomeKind &)
const {
return true; }
402 static std::string AsFortran() {
403 return "Some"s + std::string{common::EnumToString(category)};
407using NumericCategoryTypes =
410using AllIntrinsicCategoryTypes =
418 static std::string AsFortran() {
return "SomeType"s; }
424template <>
class SomeKind<TypeCategory::Derived> {
426 static constexpr TypeCategory category{TypeCategory::Derived};
427 using Scalar = StructureConstructor;
429 constexpr SomeKind() {}
430 constexpr explicit SomeKind(
const semantics::DerivedTypeSpec &dts)
431 : derivedTypeSpec_{&dts} {}
432 constexpr explicit SomeKind(
const DynamicType &dt)
433 : SomeKind(dt.GetDerivedTypeSpec()) {}
434 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(SomeKind)
436 bool IsUnlimitedPolymorphic()
const {
return !derivedTypeSpec_; }
437 constexpr DynamicType GetType()
const {
438 if (!derivedTypeSpec_) {
439 return DynamicType::UnlimitedPolymorphic();
441 return DynamicType{*derivedTypeSpec_};
444 const semantics::DerivedTypeSpec &derivedTypeSpec()
const {
445 CHECK(derivedTypeSpec_);
446 return *derivedTypeSpec_;
448 bool operator==(
const SomeKind &)
const;
449 std::string AsFortran()
const;
452 const semantics::DerivedTypeSpec *derivedTypeSpec_{
nullptr};
462using SomeCategory = std::tuple<SomeInteger, SomeReal, SomeComplex,
463 SomeCharacter, SomeLogical, SomeUnsigned, SomeDerived>;
466 common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
468template <
typename T>
using Scalar =
typename std::decay_t<T>::Scalar;
475 static constexpr bool value() {
476 return std::is_same_v<std::decay_t<CONST>,
477 std::decay_t<typename T::Scalar>>;
480 static constexpr int index{
481 common::SearchMembers<Predicate, AllIntrinsicTypes>};
482 using type = std::conditional_t<index >= 0,
483 std::tuple_element_t<index, AllIntrinsicTypes>,
void>;
486template <
typename CONST>
using TypeOf =
typename TypeOfHelper<CONST>::type;
488int SelectedCharKind(
const std::string &,
int defaultKind);
495std::optional<DynamicType> ComparisonType(
496 const DynamicType &,
const DynamicType &);
499std::optional<bool> IsInteroperableIntrinsicType(
const DynamicType &,
501 bool checkCharLength =
true);
502bool IsCUDAIntrinsicType(
const DynamicType &);
506bool AreSameDerivedType(
508bool AreSameDerivedTypeIgnoringTypeParameters(
510bool AreSameDerivedTypeIgnoringSequence(
514#define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \
515 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16)
516#define EXPAND_FOR_EACH_REAL_KIND(M, P, S) \
517 M(P, S, 2) M(P, S, 3) M(P, S, 4) M(P, S, 8) M(P, S, 10) M(P, S, 16)
518#define EXPAND_FOR_EACH_COMPLEX_KIND(M, P, S) EXPAND_FOR_EACH_REAL_KIND(M, P, S)
519#define EXPAND_FOR_EACH_CHARACTER_KIND(M, P, S) M(P, S, 1) M(P, S, 2) M(P, S, 4)
520#define EXPAND_FOR_EACH_LOGICAL_KIND(M, P, S) \
521 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8)
522#define EXPAND_FOR_EACH_UNSIGNED_KIND EXPAND_FOR_EACH_INTEGER_KIND
524#define FOR_EACH_INTEGER_KIND_HELP(PREFIX, SUFFIX, K) \
525 PREFIX<Type<TypeCategory::Integer, K>> SUFFIX;
526#define FOR_EACH_REAL_KIND_HELP(PREFIX, SUFFIX, K) \
527 PREFIX<Type<TypeCategory::Real, K>> SUFFIX;
528#define FOR_EACH_COMPLEX_KIND_HELP(PREFIX, SUFFIX, K) \
529 PREFIX<Type<TypeCategory::Complex, K>> SUFFIX;
530#define FOR_EACH_CHARACTER_KIND_HELP(PREFIX, SUFFIX, K) \
531 PREFIX<Type<TypeCategory::Character, K>> SUFFIX;
532#define FOR_EACH_LOGICAL_KIND_HELP(PREFIX, SUFFIX, K) \
533 PREFIX<Type<TypeCategory::Logical, K>> SUFFIX;
534#define FOR_EACH_UNSIGNED_KIND_HELP(PREFIX, SUFFIX, K) \
535 PREFIX<Type<TypeCategory::Unsigned, K>> SUFFIX;
537#define FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
538 EXPAND_FOR_EACH_INTEGER_KIND(FOR_EACH_INTEGER_KIND_HELP, PREFIX, SUFFIX)
539#define FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
540 EXPAND_FOR_EACH_REAL_KIND(FOR_EACH_REAL_KIND_HELP, PREFIX, SUFFIX)
541#define FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
542 EXPAND_FOR_EACH_COMPLEX_KIND(FOR_EACH_COMPLEX_KIND_HELP, PREFIX, SUFFIX)
543#define FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX) \
544 EXPAND_FOR_EACH_CHARACTER_KIND(FOR_EACH_CHARACTER_KIND_HELP, PREFIX, SUFFIX)
545#define FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \
546 EXPAND_FOR_EACH_LOGICAL_KIND(FOR_EACH_LOGICAL_KIND_HELP, PREFIX, SUFFIX)
547#define FOR_EACH_UNSIGNED_KIND(PREFIX, SUFFIX) \
548 EXPAND_FOR_EACH_UNSIGNED_KIND(FOR_EACH_UNSIGNED_KIND_HELP, PREFIX, SUFFIX)
550#define FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
551 FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
552 FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
553 FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
554 FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \
555 FOR_EACH_UNSIGNED_KIND(PREFIX, SUFFIX)
556#define FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
557 FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
558 FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX)
559#define FOR_EACH_SPECIFIC_TYPE(PREFIX, SUFFIX) \
560 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
561 PREFIX<SomeDerived> SUFFIX;
563#define FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) \
564 PREFIX<SomeInteger> SUFFIX; \
565 PREFIX<SomeReal> SUFFIX; \
566 PREFIX<SomeComplex> SUFFIX; \
567 PREFIX<SomeCharacter> SUFFIX; \
568 PREFIX<SomeLogical> SUFFIX; \
569 PREFIX<SomeUnsigned> SUFFIX; \
570 PREFIX<SomeDerived> SUFFIX; \
571 PREFIX<SomeType> SUFFIX;
572#define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \
573 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
574 FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX)
Definition Fortran-features.h:90
Definition expression.h:740