FLANG

type.h
1 //===-- include/flang/Evaluate/type.h ---------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef FORTRAN_EVALUATE_TYPE_H_
10 #define FORTRAN_EVALUATE_TYPE_H_
11
12 // These definitions map Fortran's intrinsic types, characterized by byte
13 // sizes encoded in KIND type parameter values, to their value representation
14 // types in the evaluation library, which are parameterized in terms of
15 // total bit width and real precision. Instances of the Type class template
16 // are suitable for use as template parameters to instantiate other class
17 // templates, like expressions, over the supported types and kinds.
18
19 #include "common.h"
20 #include "complex.h"
21 #include "formatting.h"
22 #include "integer.h"
23 #include "logical.h"
24 #include "real.h"
25 #include "flang/Common/Fortran.h"
26 #include "flang/Common/idioms.h"
27 #include "flang/Common/template.h"
28 #include <cinttypes>
29 #include <optional>
30 #include <string>
31 #include <type_traits>
32 #include <variant>
33
34 namespace Fortran::semantics {
35 class DeclTypeSpec;
36 class DerivedTypeSpec;
37 class ParamValue;
38 class Symbol;
39 bool IsDescriptor(const Symbol &);
40 } // namespace Fortran::semantics
41
42 namespace Fortran::evaluate {
43
44 using common::TypeCategory;
45
46 // Specific intrinsic types are represented by specializations of
47 // this class template Type<CATEGORY, KIND>.
48 template <TypeCategory CATEGORY, int KIND = 0> class Type;
49
50 using SubscriptInteger = Type<TypeCategory::Integer, 8>;
51 using CInteger = Type<TypeCategory::Integer, 4>;
52 using LogicalResult = Type<TypeCategory::Logical, 4>;
53 using LargestReal = Type<TypeCategory::Real, 16>;
54
55 // A predicate that is true when a kind value is a kind that could possibly
56 // be supported for an intrinsic type category on some target instruction
57 // set architecture.
58 // TODO: specialize for the actual target architecture
59 static constexpr bool IsValidKindOfIntrinsicType(
60 TypeCategory category, std::int64_t kind) {
61 switch (category) {
62 case TypeCategory::Integer:
63 return kind == 1 || kind == 2 || kind == 4 || kind == 8 || kind == 16;
64 case TypeCategory::Real:
65 case TypeCategory::Complex:
66 return kind == 2 || kind == 3 || kind == 4 || kind == 8 || kind == 10 ||
67 kind == 16;
68 case TypeCategory::Character:
69 return kind == 1 || kind == 2 || kind == 4;
70 case TypeCategory::Logical:
71 return kind == 1 || kind == 2 || kind == 4 || kind == 8;
72 default:
73 return false;
74 }
75 }
76
77 // DynamicType is meant to be suitable for use as the result type for
78 // GetType() functions and member functions; consequently, it must be
79 // capable of being used in a constexpr context. So it does *not*
80 // directly hold anything requiring a destructor, such as an arbitrary
81 // CHARACTER length type parameter expression. Those must be derived
82 // via LEN() member functions, packaged elsewhere (e.g. as in
83 // ArrayConstructor), or copied from a parameter spec in the symbol table
84 // if one is supplied.
85 class DynamicType {
86 public:
87 constexpr DynamicType(TypeCategory cat, int k) : category_{cat}, kind_{k} {
88 CHECK(IsValidKindOfIntrinsicType(category_, kind_));
89 }
90 constexpr DynamicType(int k, const semantics::ParamValue &pv)
91 : category_{TypeCategory::Character}, kind_{k}, charLength_{&pv} {
92 CHECK(IsValidKindOfIntrinsicType(category_, kind_));
93 }
94 explicit constexpr DynamicType(
95 const semantics::DerivedTypeSpec &dt, bool poly = false)
96 : category_{TypeCategory::Derived}, derived_{&dt} {
97 if (poly) {
98 kind_ = ClassKind;
99 }
100 }
101 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(DynamicType)
102
103 // A rare use case used for representing the characteristics of an
104 // intrinsic function like REAL() that accepts a typeless BOZ literal
105 // argument, which is something that real user Fortran can't do.
106 static constexpr DynamicType TypelessIntrinsicArgument() {
107 DynamicType result;
108 result.category_ = TypeCategory::Integer;
109 result.kind_ = TypelessKind;
110 return result;
111 }
112
113 static constexpr DynamicType UnlimitedPolymorphic() {
114 DynamicType result;
115 result.category_ = TypeCategory::Derived;
116 result.kind_ = ClassKind;
117 result.derived_ = nullptr;
118 return result; // CLASS(*)
119 }
120
121 static constexpr DynamicType AssumedType() {
122 DynamicType result;
123 result.category_ = TypeCategory::Derived;
124 result.kind_ = AssumedTypeKind;
125 result.derived_ = nullptr;
126 return result; // TYPE(*)
127 }
128
129 // Comparison is deep -- type parameters are compared independently.
130 bool operator==(const DynamicType &) const;
131 bool operator!=(const DynamicType &that) const { return !(*this == that); }
132
133 constexpr TypeCategory category() const { return category_; }
134 constexpr int kind() const {
135 CHECK(kind_ > 0);
136 return kind_;
137 }
138 constexpr const semantics::ParamValue *charLength() const {
139 return charLength_;
140 }
141 std::optional<common::ConstantSubscript> GetCharLength() const;
142 std::optional<std::size_t> MeasureSizeInBytes() const;
143
144 std::string AsFortran() const;
145 std::string AsFortran(std::string &&charLenExpr) const;
146 DynamicType ResultTypeForMultiply(const DynamicType &) const;
147
148 bool IsAssumedLengthCharacter() const;
149 bool IsNonConstantLengthCharacter() const;
150 bool IsTypelessIntrinsicArgument() const;
151 constexpr bool IsAssumedType() const { // TYPE(*)
152 return kind_ == AssumedTypeKind;
153 }
154 constexpr bool IsPolymorphic() const { // TYPE(*) or CLASS()
155 return kind_ == ClassKind || IsAssumedType();
156 }
157 constexpr bool IsUnlimitedPolymorphic() const { // TYPE(*) or CLASS(*)
158 return IsPolymorphic() && !derived_;
159 }
160 constexpr const semantics::DerivedTypeSpec &GetDerivedTypeSpec() const {
161 return DEREF(derived_);
162 }
163
164 bool RequiresDescriptor() const;
165 bool HasDeferredTypeParameter() const;
166
167 // 7.3.2.3 & 15.5.2.4 type compatibility.
168 // x.IsTypeCompatibleWith(y) is true if "x => y" or passing actual y to
169 // dummy argument x would be valid. Be advised, this is not a reflexive
170 // relation.
171 bool IsTypeCompatibleWith(const DynamicType &) const;
172 // Type compatible and kind type parameters match
173 bool IsTkCompatibleWith(const DynamicType &) const;
174
175 // Result will be missing when a symbol is absent or
176 // has an erroneous type, e.g., REAL(KIND=666).
177 static std::optional<DynamicType> From(const semantics::DeclTypeSpec &);
178 static std::optional<DynamicType> From(const semantics::Symbol &);
179
180 template <typename A> static std::optional<DynamicType> From(const A &x) {
181 return x.GetType();
182 }
183 template <typename A> static std::optional<DynamicType> From(const A *p) {
184 if (!p) {
185 return std::nullopt;
186 } else {
187 return From(*p);
188 }
189 }
190 template <typename A>
191 static std::optional<DynamicType> From(const std::optional<A> &x) {
192 if (x) {
193 return From(*x);
194 } else {
195 return std::nullopt;
196 }
197 }
198
199 private:
200 // Special kind codes are used to distinguish the following Fortran types.
201 enum SpecialKind {
202 TypelessKind = -1, // BOZ actual argument to intrinsic function
203 ClassKind = -2, // CLASS(T) or CLASS(*)
204 AssumedTypeKind = -3, // TYPE(*)
205 };
206
207 constexpr DynamicType() {}
208
209 TypeCategory category_{TypeCategory::Derived}; // overridable default
210 int kind_{0};
211 const semantics::ParamValue *charLength_{nullptr};
212 const semantics::DerivedTypeSpec *derived_{nullptr}; // TYPE(T), CLASS(T)
213 };
214
215 // Return the DerivedTypeSpec of a DynamicType if it has one.
216 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(const DynamicType &);
217 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(
218 const std::optional<DynamicType> &);
219
220 std::string DerivedTypeSpecAsFortran(const semantics::DerivedTypeSpec &);
221
222 template <TypeCategory CATEGORY, int KIND = 0> struct TypeBase {
223 static constexpr TypeCategory category{CATEGORY};
224 static constexpr int kind{KIND};
225 constexpr bool operator==(const TypeBase &) const { return true; }
226 static constexpr DynamicType GetType() { return {category, kind}; }
227 static std::string AsFortran() { return GetType().AsFortran(); }
228 };
229
230 template <int KIND>
231 class Type<TypeCategory::Integer, KIND>
232 : public TypeBase<TypeCategory::Integer, KIND> {
233 public:
234 using Scalar = value::Integer<8 * KIND>;
235 };
236
237 // REAL(KIND=2) is IEEE half-precision (16 bits)
238 template <>
239 class Type<TypeCategory::Real, 2> : public TypeBase<TypeCategory::Real, 2> {
240 public:
241 using Scalar =
242 value::Real<typename Type<TypeCategory::Integer, 2>::Scalar, 11>;
243 };
244
245 // REAL(KIND=3) identifies the "other" half-precision format, which is
246 // basically REAL(4) without its least-order 16 fraction bits.
247 template <>
248 class Type<TypeCategory::Real, 3> : public TypeBase<TypeCategory::Real, 3> {
249 public:
250 using Scalar =
251 value::Real<typename Type<TypeCategory::Integer, 2>::Scalar, 8>;
252 };
253
254 // REAL(KIND=4) is IEEE-754 single precision (32 bits)
255 template <>
256 class Type<TypeCategory::Real, 4> : public TypeBase<TypeCategory::Real, 4> {
257 public:
258 using Scalar =
259 value::Real<typename Type<TypeCategory::Integer, 4>::Scalar, 24>;
260 };
261
262 // REAL(KIND=8) is IEEE double precision (64 bits)
263 template <>
264 class Type<TypeCategory::Real, 8> : public TypeBase<TypeCategory::Real, 8> {
265 public:
266 using Scalar =
267 value::Real<typename Type<TypeCategory::Integer, 8>::Scalar, 53>;
268 };
269
270 // REAL(KIND=10) is x87 FPU extended precision (80 bits, all explicit)
271 template <>
272 class Type<TypeCategory::Real, 10> : public TypeBase<TypeCategory::Real, 10> {
273 public:
274 using Scalar = value::Real<value::Integer<80>, 64>;
275 };
276
277 // REAL(KIND=16) is IEEE quad precision (128 bits)
278 template <>
279 class Type<TypeCategory::Real, 16> : public TypeBase<TypeCategory::Real, 16> {
280 public:
281 using Scalar = value::Real<value::Integer<128>, 113>;
282 };
283
284 // The KIND type parameter on COMPLEX is the kind of each of its components.
285 template <int KIND>
286 class Type<TypeCategory::Complex, KIND>
287 : public TypeBase<TypeCategory::Complex, KIND> {
288 public:
289 using Part = Type<TypeCategory::Real, KIND>;
290 using Scalar = value::Complex<typename Part::Scalar>;
291 };
292
293 template <>
294 class Type<TypeCategory::Character, 1>
295 : public TypeBase<TypeCategory::Character, 1> {
296 public:
297 using Scalar = std::string;
298 };
299
300 template <>
301 class Type<TypeCategory::Character, 2>
302 : public TypeBase<TypeCategory::Character, 2> {
303 public:
304 using Scalar = std::u16string;
305 };
306
307 template <>
308 class Type<TypeCategory::Character, 4>
309 : public TypeBase<TypeCategory::Character, 4> {
310 public:
311 using Scalar = std::u32string;
312 };
313
314 template <int KIND>
315 class Type<TypeCategory::Logical, KIND>
316 : public TypeBase<TypeCategory::Logical, KIND> {
317 public:
318 using Scalar = value::Logical<8 * KIND>;
319 };
320
321 // Type functions
322
323 // Given a specific type, find the type of the same kind in another category.
324 template <TypeCategory CATEGORY, typename T>
325 using SameKind = Type<CATEGORY, std::decay_t<T>::kind>;
326
327 // Many expressions, including subscripts, CHARACTER lengths, array bounds,
328 // and effective type parameter values, are of a maximal kind of INTEGER.
329 using IndirectSubscriptIntegerExpr =
330 common::CopyableIndirection<Expr<SubscriptInteger>>;
331
332 // For each intrinsic type category CAT, CategoryTypes<CAT> is an instantiation
333 // of std::tuple<Type<CAT, K>> that comprises every kind value K in that
334 // category that could possibly be supported on any target.
335 template <TypeCategory CATEGORY, int KIND>
336 using CategoryKindTuple =
337 std::conditional_t<IsValidKindOfIntrinsicType(CATEGORY, KIND),
338 std::tuple<Type<CATEGORY, KIND>>, std::tuple<>>;
339
340 template <TypeCategory CATEGORY, int... KINDS>
341 using CategoryTypesHelper =
342 common::CombineTuples<CategoryKindTuple<CATEGORY, KINDS>...>;
343
344 template <TypeCategory CATEGORY>
345 using CategoryTypes = CategoryTypesHelper<CATEGORY, 1, 2, 3, 4, 8, 10, 16, 32>;
346
347 using IntegerTypes = CategoryTypes<TypeCategory::Integer>;
348 using RealTypes = CategoryTypes<TypeCategory::Real>;
349 using ComplexTypes = CategoryTypes<TypeCategory::Complex>;
350 using CharacterTypes = CategoryTypes<TypeCategory::Character>;
351 using LogicalTypes = CategoryTypes<TypeCategory::Logical>;
352
353 using FloatingTypes = common::CombineTuples<RealTypes, ComplexTypes>;
354 using NumericTypes = common::CombineTuples<IntegerTypes, FloatingTypes>;
355 using RelationalTypes = common::CombineTuples<NumericTypes, CharacterTypes>;
356 using AllIntrinsicTypes = common::CombineTuples<RelationalTypes, LogicalTypes>;
357 using LengthlessIntrinsicTypes =
358 common::CombineTuples<NumericTypes, LogicalTypes>;
359
360 // Predicates: does a type represent a specific intrinsic type?
361 template <typename T>
362 constexpr bool IsSpecificIntrinsicType{common::HasMember<T, AllIntrinsicTypes>};
363
364 // Predicate: is a type an intrinsic type that is completely characterized
365 // by its category and kind parameter value, or might it have a derived type
366 // &/or a length type parameter?
367 template <typename T>
368 constexpr bool IsLengthlessIntrinsicType{
369 common::HasMember<T, LengthlessIntrinsicTypes>};
370
371 // Represents a type of any supported kind within a particular category.
372 template <TypeCategory CATEGORY> struct SomeKind {
373 static constexpr TypeCategory category{CATEGORY};
374 constexpr bool operator==(const SomeKind &) const { return true; }
375 };
376
377 using NumericCategoryTypes = std::tuple<SomeKind<TypeCategory::Integer>,
378 SomeKind<TypeCategory::Real>, SomeKind<TypeCategory::Complex>>;
379 using AllIntrinsicCategoryTypes = std::tuple<SomeKind<TypeCategory::Integer>,
380 SomeKind<TypeCategory::Real>, SomeKind<TypeCategory::Complex>,
381 SomeKind<TypeCategory::Character>, SomeKind<TypeCategory::Logical>>;
382
383 // Represents a completely generic type (or, for Expr<SomeType>, a typeless
384 // value like a BOZ literal or NULL() pointer).
385 struct SomeType {};
386
387 class StructureConstructor;
388
389 // Represents any derived type, polymorphic or not, as well as CLASS(*).
390 template <> class SomeKind<TypeCategory::Derived> {
391 public:
392 static constexpr TypeCategory category{TypeCategory::Derived};
393 using Scalar = StructureConstructor;
394
395 constexpr SomeKind() {} // CLASS(*)
396 constexpr explicit SomeKind(const semantics::DerivedTypeSpec &dts)
397 : derivedTypeSpec_{&dts} {}
398 constexpr explicit SomeKind(const DynamicType &dt)
399 : SomeKind(dt.GetDerivedTypeSpec()) {}
400 CONSTEXPR_CONSTRUCTORS_AND_ASSIGNMENTS(SomeKind)
401
402 bool IsUnlimitedPolymorphic() const { return !derivedTypeSpec_; }
403 constexpr DynamicType GetType() const {
404 if (!derivedTypeSpec_) {
405 return DynamicType::UnlimitedPolymorphic();
406 } else {
407 return DynamicType{*derivedTypeSpec_};
408 }
409 }
410 const semantics::DerivedTypeSpec &derivedTypeSpec() const {
411 CHECK(derivedTypeSpec_);
412 return *derivedTypeSpec_;
413 }
414 bool operator==(const SomeKind &) const;
415 std::string AsFortran() const;
416
417 private:
418 const semantics::DerivedTypeSpec *derivedTypeSpec_{nullptr};
419 };
420
421 using SomeInteger = SomeKind<TypeCategory::Integer>;
422 using SomeReal = SomeKind<TypeCategory::Real>;
423 using SomeComplex = SomeKind<TypeCategory::Complex>;
424 using SomeCharacter = SomeKind<TypeCategory::Character>;
425 using SomeLogical = SomeKind<TypeCategory::Logical>;
426 using SomeDerived = SomeKind<TypeCategory::Derived>;
427 using SomeCategory = std::tuple<SomeInteger, SomeReal, SomeComplex,
428 SomeCharacter, SomeLogical, SomeDerived>;
429
430 using AllTypes =
431 common::CombineTuples<AllIntrinsicTypes, std::tuple<SomeDerived>>;
432
433 template <typename T> using Scalar = typename std::decay_t<T>::Scalar;
434
435 // When Scalar<T> is S, then TypeOf<S> is T.
436 // TypeOf is implemented by scanning all supported types for a match
437 // with Type<T>::Scalar.
438 template <typename CONST> struct TypeOfHelper {
439 template <typename T> struct Predicate {
440 static constexpr bool value() {
441 return std::is_same_v<std::decay_t<CONST>,
442 std::decay_t<typename T::Scalar>>;
443 }
444 };
445 static constexpr int index{
446 common::SearchMembers<Predicate, AllIntrinsicTypes>};
447 using type = std::conditional_t<index >= 0,
448 std::tuple_element_t<index, AllIntrinsicTypes>, void>;
449 };
450
451 template <typename CONST> using TypeOf = typename TypeOfHelper<CONST>::type;
452
453 int SelectedCharKind(const std::string &, int defaultKind);
454 int SelectedIntKind(std::int64_t precision = 0);
455 int SelectedRealKind(
456 std::int64_t precision = 0, std::int64_t range = 0, std::int64_t radix = 2);
457
458 // Utilities
459 bool IsKindTypeParameter(const semantics::Symbol &);
460
461 // For generating "[extern] template class", &c. boilerplate
462 #define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \
463 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16)
464 #define EXPAND_FOR_EACH_REAL_KIND(M, P, S) \
465 M(P, S, 2) M(P, S, 3) M(P, S, 4) M(P, S, 8) M(P, S, 10) M(P, S, 16)
466 #define EXPAND_FOR_EACH_COMPLEX_KIND(M, P, S) EXPAND_FOR_EACH_REAL_KIND(M, P, S)
467 #define EXPAND_FOR_EACH_CHARACTER_KIND(M, P, S) M(P, S, 1) M(P, S, 2) M(P, S, 4)
468 #define EXPAND_FOR_EACH_LOGICAL_KIND(M, P, S) \
469 M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8)
470 #define TEMPLATE_INSTANTIATION(P, S, ARG) P<ARG> S;
471
472 #define FOR_EACH_INTEGER_KIND_HELP(PREFIX, SUFFIX, K) \
473 PREFIX<Type<TypeCategory::Integer, K>> SUFFIX;
474 #define FOR_EACH_REAL_KIND_HELP(PREFIX, SUFFIX, K) \
475 PREFIX<Type<TypeCategory::Real, K>> SUFFIX;
476 #define FOR_EACH_COMPLEX_KIND_HELP(PREFIX, SUFFIX, K) \
477 PREFIX<Type<TypeCategory::Complex, K>> SUFFIX;
478 #define FOR_EACH_CHARACTER_KIND_HELP(PREFIX, SUFFIX, K) \
479 PREFIX<Type<TypeCategory::Character, K>> SUFFIX;
480 #define FOR_EACH_LOGICAL_KIND_HELP(PREFIX, SUFFIX, K) \
481 PREFIX<Type<TypeCategory::Logical, K>> SUFFIX;
482
483 #define FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
484 EXPAND_FOR_EACH_INTEGER_KIND(FOR_EACH_INTEGER_KIND_HELP, PREFIX, SUFFIX)
485 #define FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
486 EXPAND_FOR_EACH_REAL_KIND(FOR_EACH_REAL_KIND_HELP, PREFIX, SUFFIX)
487 #define FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
488 EXPAND_FOR_EACH_COMPLEX_KIND(FOR_EACH_COMPLEX_KIND_HELP, PREFIX, SUFFIX)
489 #define FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX) \
490 EXPAND_FOR_EACH_CHARACTER_KIND(FOR_EACH_CHARACTER_KIND_HELP, PREFIX, SUFFIX)
491 #define FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX) \
492 EXPAND_FOR_EACH_LOGICAL_KIND(FOR_EACH_LOGICAL_KIND_HELP, PREFIX, SUFFIX)
493
494 #define FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
495 FOR_EACH_INTEGER_KIND(PREFIX, SUFFIX) \
496 FOR_EACH_REAL_KIND(PREFIX, SUFFIX) \
497 FOR_EACH_COMPLEX_KIND(PREFIX, SUFFIX) \
498 FOR_EACH_LOGICAL_KIND(PREFIX, SUFFIX)
499 #define FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
500 FOR_EACH_LENGTHLESS_INTRINSIC_KIND(PREFIX, SUFFIX) \
501 FOR_EACH_CHARACTER_KIND(PREFIX, SUFFIX)
502 #define FOR_EACH_SPECIFIC_TYPE(PREFIX, SUFFIX) \
503 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
504 PREFIX<SomeDerived> SUFFIX;
505
506 #define FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX) \
507 PREFIX<SomeInteger> SUFFIX; \
508 PREFIX<SomeReal> SUFFIX; \
509 PREFIX<SomeComplex> SUFFIX; \
510 PREFIX<SomeCharacter> SUFFIX; \
511 PREFIX<SomeLogical> SUFFIX; \
512 PREFIX<SomeDerived> SUFFIX; \
513 PREFIX<SomeType> SUFFIX;
514 #define FOR_EACH_TYPE_AND_KIND(PREFIX, SUFFIX) \
515 FOR_EACH_INTRINSIC_KIND(PREFIX, SUFFIX) \
516 FOR_EACH_CATEGORY_TYPE(PREFIX, SUFFIX)
517 } // namespace Fortran::evaluate
518 #endif // FORTRAN_EVALUATE_TYPE_H_
Fortran::evaluate::StructureConstructor
Definition: expression.h:687
Fortran::evaluate::DynamicType
Definition: type.h:85
Fortran::evaluate::Type
Definition: type.h:48
Fortran::semantics::DeclTypeSpec
Definition: type.h:302
Fortran::semantics::Symbol
Definition: symbol.h:479
Fortran::semantics::DerivedTypeSpec
Definition: type.h:237
Fortran::evaluate::Type< TypeCategory::Real, 16 >
Definition: type.h:279
Fortran::evaluate::SomeType
Definition: type.h:385
Fortran::evaluate::TypeBase
Definition: type.h:222
Fortran::common::Indirection< A, true >
Definition: indirection.h:72
Fortran::evaluate::value::Real
Definition: real.h:39
Fortran::evaluate::TypeOfHelper
Definition: type.h:438
Fortran::evaluate::SomeKind
Definition: type.h:372
Fortran::evaluate::TypeOfHelper::Predicate
Definition: type.h:439
Fortran::evaluate::value::Complex
Definition: complex.h:22
Fortran::semantics::ParamValue
Definition: type.h:82
Fortran::evaluate::value::Logical
Definition: logical.h:17
Fortran::evaluate::SomeKind< TypeCategory::Derived >
Definition: type.h:390