9#ifndef FORTRAN_EVALUATE_TYPE_H_
10#define FORTRAN_EVALUATE_TYPE_H_
21#include "formatting.h"
25#include "flang/Common/Fortran-features.h"
26#include "flang/Common/Fortran.h"
27#include "flang/Common/idioms.h"
28#include "flang/Common/real.h"
29#include "flang/Common/template.h"
36namespace Fortran::semantics {
45bool IsDescriptor(
const Symbol &);
46bool IsPassedViaDescriptor(
const Symbol &);
51using common::TypeCategory;
52class TargetCharacteristics;
56template <TypeCategory CATEGORY,
int KIND = 0>
class Type;
68static constexpr bool IsValidKindOfIntrinsicType(
69 TypeCategory category, std::int64_t kind) {
71 case TypeCategory::Integer:
72 case TypeCategory::Unsigned:
73 return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16;
74 case TypeCategory::Real:
75 case TypeCategory::Complex:
76 return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 ||
78 case TypeCategory::Character:
79 return kind == 1 || kind == 2 || kind == 4;
80 case TypeCategory::Logical:
81 return kind == 1 || kind == 2 || kind == 4 || kind == 8;
97 constexpr DynamicType(TypeCategory cat,
int k) : category_{cat}, kind_{k} {
98 CHECK(IsValidKindOfIntrinsicType(category_, kind_));
104 : category_{TypeCategory::Character}, kind_{k}, knownLength_{
105 len >= 0 ? len : 0} {
106 CHECK(IsValidKindOfIntrinsicType(category_, kind_));
110 : category_{TypeCategory::Derived}, derived_{&dt} {
115 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(
DynamicType)
121 static constexpr DynamicType TypelessIntrinsicArgument() {
123 result.category_ = TypeCategory::Integer;
124 result.kind_ = TypelessKind;
128 static constexpr DynamicType UnlimitedPolymorphic() {
130 result.category_ = TypeCategory::Derived;
131 result.kind_ = ClassKind;
132 result.derived_ =
nullptr;
138 result.category_ = TypeCategory::Derived;
139 result.kind_ = AssumedTypeKind;
140 result.derived_ =
nullptr;
146 bool operator!=(
const DynamicType &that)
const {
return !(*
this == that); }
148 constexpr TypeCategory category()
const {
return category_; }
149 constexpr int kind()
const {
154 return charLengthParamValue_;
156 constexpr std::optional<std::int64_t> knownLength()
const {
157#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 7
158 if (knownLength_ < 0) {
164 std::optional<Expr<SubscriptInteger>> GetCharLength()
const;
167 std::optional<Expr<SubscriptInteger>> MeasureSizeInBytes(
FoldingContext &,
169 std::optional<std::int64_t> charLength = std::nullopt)
const;
171 std::string AsFortran()
const;
172 std::string AsFortran(std::string &&charLenExpr)
const;
175 bool IsAssumedLengthCharacter()
const;
176 bool IsNonConstantLengthCharacter()
const;
177 bool IsTypelessIntrinsicArgument()
const;
178 constexpr bool IsAssumedType()
const {
179 return kind_ == AssumedTypeKind;
181 constexpr bool IsPolymorphic()
const {
182 return kind_ == ClassKind || IsAssumedType();
184 constexpr bool IsUnlimitedPolymorphic()
const {
185 return IsPolymorphic() && !derived_;
187 bool IsLengthlessIntrinsicType()
const;
189 return DEREF(derived_);
192 bool RequiresDescriptor()
const;
193 bool HasDeferredTypeParameter()
const;
200 bool IsTkCompatibleWith(
const DynamicType &)
const;
201 bool IsTkCompatibleWith(
const DynamicType &, common::IgnoreTKRSet)
const;
205 bool IsTkLenCompatibleWith(
const DynamicType &)
const;
208 std::optional<bool> ExtendsTypeOf(
const DynamicType &)
const;
210 std::optional<bool> SameTypeAs(
const DynamicType &)
const;
221 template <
typename A>
static std::optional<DynamicType> From(
const A &x) {
224 template <
typename A>
static std::optional<DynamicType> From(
const A *p) {
231 template <
typename A>
232 static std::optional<DynamicType> From(
const std::optional<A> &x) {
244 DynamicType DropNonConstantCharacterLength()
const;
252 AssumedTypeKind = -3,
257 TypeCategory category_{TypeCategory::Derived};
260#if defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 7
262 std::int64_t knownLength_{-1};
264 std::optional<std::int64_t> knownLength_;
272 const std::optional<DynamicType> &);
276template <TypeCategory CATEGORY,
int KIND = 0>
struct TypeBase {
277 static constexpr TypeCategory category{CATEGORY};
278 static constexpr int kind{KIND};
279 constexpr bool operator==(
const TypeBase &)
const {
return true; }
280 static constexpr DynamicType GetType() {
return {category, kind}; }
281 static std::string AsFortran() {
return GetType().AsFortran(); }
285class Type<TypeCategory::Integer, KIND>
286 :
public TypeBase<TypeCategory::Integer, KIND> {
288 using Scalar = value::Integer<8 * KIND>;
292class Type<TypeCategory::Unsigned, KIND>
293 :
public TypeBase<TypeCategory::Unsigned, KIND> {
295 using Scalar = value::Integer<8 * KIND>;
299class Type<TypeCategory::Real, KIND>
300 :
public TypeBase<TypeCategory::Real, KIND> {
302 static constexpr int precision{common::PrecisionOfRealKind(KIND)};
303 static constexpr int bits{common::BitsForBinaryPrecision(precision)};
306 value::X87IntegerContainer, value::Integer<bits>>,
312class Type<TypeCategory::Complex, KIND>
313 :
public TypeBase<TypeCategory::Complex, KIND> {
320class Type<TypeCategory::Character, 1>
321 :
public TypeBase<TypeCategory::Character, 1> {
323 using Scalar = std::string;
327class Type<TypeCategory::Character, 2>
328 :
public TypeBase<TypeCategory::Character, 2> {
330 using Scalar = std::u16string;
334class Type<TypeCategory::Character, 4>
335 :
public TypeBase<TypeCategory::Character, 4> {
337 using Scalar = std::u32string;
341class Type<TypeCategory::Logical, KIND>
342 :
public TypeBase<TypeCategory::Logical, KIND> {
350template <TypeCategory CATEGORY,
typename T>
361template <TypeCategory CATEGORY,
int KIND>
362using CategoryKindTuple =
363 std::conditional_t<IsValidKindOfIntrinsicType(CATEGORY, KIND),
364 std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
366template <TypeCategory CATEGORY,
int... KINDS>
367using CategoryTypesHelper =
368 common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>;
370template <TypeCategory CATEGORY>
371using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>;
373using IntegerTypes = CategoryTypes<TypeCategory::Integer>;
374using RealTypes = CategoryTypes<TypeCategory::Real>;
375using ComplexTypes = CategoryTypes<TypeCategory::Complex>;
376using CharacterTypes = CategoryTypes<TypeCategory::Character>;
377using LogicalTypes = CategoryTypes<TypeCategory::Logical>;
378using UnsignedTypes = CategoryTypes<TypeCategory::Unsigned>;
380using FloatingTypes = common::CombineTuples<RealTypes, ComplexTypes>;
382 common::CombineTuples<IntegerTypes, FloatingTypes, UnsignedTypes>;
383using RelationalTypes = common::CombineTuples<IntegerTypes, RealTypes,
384 CharacterTypes, UnsignedTypes>;
385using AllIntrinsicTypes =
386 common::CombineTuples<NumericTypes, CharacterTypes, LogicalTypes>;
387using LengthlessIntrinsicTypes =
388 common::CombineTuples<NumericTypes, LogicalTypes>;
392constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>};
398constexpr bool IsLengthlessIntrinsicType{
399 common::HasMember<T, LengthlessIntrinsicTypes>};
403 static constexpr TypeCategory category{CATEGORY};
404 constexpr bool operator==(
const SomeKind &)
const {
return true; }
405 static std::string AsFortran() {
406 return "Some"s + std::string{common::EnumToString(category)};
410using NumericCategoryTypes =
413using AllIntrinsicCategoryTypes =
421 static std::string AsFortran() {
return "SomeType"s; }
429 static constexpr TypeCategory category{TypeCategory::Derived};
434 : derivedTypeSpec_{&dts} {}
436 :
SomeKind(dt.GetDerivedTypeSpec()) {}
437 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(
SomeKind)
439 bool IsUnlimitedPolymorphic()
const {
return !derivedTypeSpec_; }
441 if (!derivedTypeSpec_) {
442 return DynamicType::UnlimitedPolymorphic();
448 CHECK(derivedTypeSpec_);
449 return *derivedTypeSpec_;
451 bool operator==(
const SomeKind &)
const;
452 std::string AsFortran()
const;
469 common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
471template <
typename T>
using Scalar =
typename std::decay_t<T>::Scalar;
478 static constexpr bool value() {
479 return std::is_same_v<std::decay_t<CONST>,
480 std::decay_t<typename T::Scalar>>;
483 static constexpr int index{
484 common::SearchMembers<Predicate, AllIntrinsicTypes>};
485 using type = std::conditional_t<index >= 0,
486 std::tuple_element_t<index, AllIntrinsicTypes>,
void>;
489template <
typename CONST>
using TypeOf =
typename TypeOfHelper<CONST>::type;
491int SelectedCharKind(
const std::string &,
int defaultKind);
498std::optional<DynamicType> ComparisonType(
499 const DynamicType &,
const DynamicType &);
502std::optional<bool> IsInteroperableIntrinsicType(
const DynamicType &,
504 bool checkCharLength =
true);
505bool IsCUDAIntrinsicType(
const DynamicType &);
509bool AreSameDerivedType(
511bool AreSameDerivedTypeIgnoringTypeParameters(
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: indirection.h:72
Definition: Fortran-features.h:84
Definition: expression.h:740