1 //===-- lib/Evaluate/type.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "flang/Evaluate/type.h"
10 #include "flang/Common/idioms.h"
11 #include "flang/Evaluate/expression.h"
12 #include "flang/Evaluate/fold.h"
13 #include "flang/Evaluate/target.h"
14 #include "flang/Parser/characters.h"
15 #include "flang/Semantics/scope.h"
16 #include "flang/Semantics/symbol.h"
17 #include "flang/Semantics/tools.h"
18 #include "flang/Semantics/type.h"
23 // IsDescriptor() predicate: true when a symbol is implemented
24 // at runtime with a descriptor.
25 namespace Fortran::semantics
{
27 static bool IsDescriptor(const DeclTypeSpec
*type
) {
29 if (auto dynamicType
{evaluate::DynamicType::From(*type
)}) {
30 return dynamicType
->RequiresDescriptor();
36 static bool IsDescriptor(const ObjectEntityDetails
&details
) {
37 if (IsDescriptor(details
.type())) {
40 for (const ShapeSpec
&shapeSpec
: details
.shape()) {
41 const auto &lb
{shapeSpec
.lbound().GetExplicit()};
42 const auto &ub
{shapeSpec
.ubound().GetExplicit()};
43 if (!lb
|| !ub
|| !IsConstantExpr(*lb
) || !IsConstantExpr(*ub
)) {
50 static bool IsDescriptor(const ProcEntityDetails
&details
) {
51 // A procedure pointer or dummy procedure must be & is a descriptor if
52 // and only if it requires a static link.
53 // TODO: refine this placeholder
54 return details
.HasExplicitInterface();
57 bool IsDescriptor(const Symbol
&symbol
) {
60 [&](const ObjectEntityDetails
&d
) {
61 return IsAllocatableOrPointer(symbol
) || IsDescriptor(d
);
63 [&](const ProcEntityDetails
&d
) {
64 return (symbol
.attrs().test(Attr::POINTER
) ||
65 symbol
.attrs().test(Attr::EXTERNAL
)) &&
68 [&](const EntityDetails
&d
) { return IsDescriptor(d
.type()); },
69 [](const AssocEntityDetails
&d
) {
70 if (const auto &expr
{d
.expr()}) {
71 if (expr
->Rank() > 0) {
74 if (const auto dynamicType
{expr
->GetType()}) {
75 if (dynamicType
->RequiresDescriptor()) {
82 [](const SubprogramDetails
&d
) {
83 return d
.isFunction() && IsDescriptor(d
.result());
85 [](const UseDetails
&d
) { return IsDescriptor(d
.symbol()); },
86 [](const HostAssocDetails
&d
) { return IsDescriptor(d
.symbol()); },
87 [](const auto &) { return false; },
91 } // namespace Fortran::semantics
93 namespace Fortran::evaluate
{
95 DynamicType::DynamicType(int k
, const semantics::ParamValue
&pv
)
96 : category_
{TypeCategory::Character
}, kind_
{k
} {
97 CHECK(IsValidKindOfIntrinsicType(category_
, kind_
));
98 if (auto n
{ToInt64(pv
.GetExplicit())}) {
99 knownLength_
= *n
> 0 ? *n
: 0;
101 charLengthParamValue_
= &pv
;
105 template <typename A
> inline bool PointeeComparison(const A
*x
, const A
*y
) {
106 return x
== y
|| (x
&& y
&& *x
== *y
);
109 bool DynamicType::operator==(const DynamicType
&that
) const {
110 return category_
== that
.category_
&& kind_
== that
.kind_
&&
111 PointeeComparison(charLengthParamValue_
, that
.charLengthParamValue_
) &&
112 knownLength().has_value() == that
.knownLength().has_value() &&
113 (!knownLength() || *knownLength() == *that
.knownLength()) &&
114 PointeeComparison(derived_
, that
.derived_
);
117 std::optional
<Expr
<SubscriptInteger
>> DynamicType::GetCharLength() const {
118 if (category_
== TypeCategory::Character
) {
120 return AsExpr(Constant
<SubscriptInteger
>(*knownLength()));
121 } else if (charLengthParamValue_
) {
122 if (auto length
{charLengthParamValue_
->GetExplicit()}) {
123 return ConvertToType
<SubscriptInteger
>(std::move(*length
));
130 std::size_t DynamicType::GetAlignment(
131 const TargetCharacteristics
&targetCharacteristics
) const {
132 if (category_
== TypeCategory::Derived
) {
133 if (derived_
&& derived_
->scope()) {
134 return derived_
->scope()->alignment().value_or(1);
137 return targetCharacteristics
.GetAlignment(category_
, kind_
);
139 return 1; // needs to be after switch to dodge a bogus gcc warning
142 std::optional
<Expr
<SubscriptInteger
>> DynamicType::MeasureSizeInBytes(
143 FoldingContext
&context
, bool aligned
) const {
145 case TypeCategory::Integer
:
146 case TypeCategory::Real
:
147 case TypeCategory::Complex
:
148 case TypeCategory::Logical
:
149 return Expr
<SubscriptInteger
>{
150 context
.targetCharacteristics().GetByteSize(category_
, kind_
)};
151 case TypeCategory::Character
:
152 if (auto len
{GetCharLength()}) {
154 Expr
<SubscriptInteger
>{
155 context
.targetCharacteristics().GetByteSize(category_
, kind_
)} *
159 case TypeCategory::Derived
:
160 if (!IsPolymorphic() && derived_
&& derived_
->scope()) {
161 auto size
{derived_
->scope()->size()};
162 auto align
{aligned
? derived_
->scope()->alignment().value_or(0) : 0};
163 auto alignedSize
{align
> 0 ? ((size
+ align
- 1) / align
) * align
: size
};
164 return Expr
<SubscriptInteger
>{
165 static_cast<ConstantSubscript
>(alignedSize
)};
172 bool DynamicType::IsAssumedLengthCharacter() const {
173 return category_
== TypeCategory::Character
&& charLengthParamValue_
&&
174 charLengthParamValue_
->isAssumed();
177 bool DynamicType::IsNonConstantLengthCharacter() const {
178 if (category_
!= TypeCategory::Character
) {
180 } else if (knownLength()) {
182 } else if (!charLengthParamValue_
) {
184 } else if (const auto &expr
{charLengthParamValue_
->GetExplicit()}) {
185 return !IsConstantExpr(*expr
);
191 bool DynamicType::IsTypelessIntrinsicArgument() const {
192 return category_
== TypeCategory::Integer
&& kind_
== TypelessKind
;
195 const semantics::DerivedTypeSpec
*GetDerivedTypeSpec(
196 const std::optional
<DynamicType
> &type
) {
197 return type
? GetDerivedTypeSpec(*type
) : nullptr;
200 const semantics::DerivedTypeSpec
*GetDerivedTypeSpec(const DynamicType
&type
) {
201 if (type
.category() == TypeCategory::Derived
&&
202 !type
.IsUnlimitedPolymorphic()) {
203 return &type
.GetDerivedTypeSpec();
209 static const semantics::Symbol
*FindParentComponent(
210 const semantics::DerivedTypeSpec
&derived
) {
211 const semantics::Symbol
&typeSymbol
{derived
.typeSymbol()};
212 const semantics::Scope
*scope
{derived
.scope()};
214 scope
= typeSymbol
.scope();
217 const auto &dtDetails
{typeSymbol
.get
<semantics::DerivedTypeDetails
>()};
218 // TODO: Combine with semantics::DerivedTypeDetails::GetParentComponent
219 if (auto extends
{dtDetails
.GetParentComponentName()}) {
220 if (auto iter
{scope
->find(*extends
)}; iter
!= scope
->cend()) {
221 if (const semantics::Symbol
& symbol
{*iter
->second
};
222 symbol
.test(semantics::Symbol::Flag::ParentComp
)) {
231 const semantics::DerivedTypeSpec
*GetParentTypeSpec(
232 const semantics::DerivedTypeSpec
&derived
) {
233 if (const semantics::Symbol
* parent
{FindParentComponent(derived
)}) {
234 return &parent
->get
<semantics::ObjectEntityDetails
>()
242 // Compares two derived type representations to see whether they both
243 // represent the "same type" in the sense of section 7.5.2.4.
244 using SetOfDerivedTypePairs
=
245 std::set
<std::pair
<const semantics::DerivedTypeSpec
*,
246 const semantics::DerivedTypeSpec
*>>;
248 static bool AreSameComponent(const semantics::Symbol
&x
,
249 const semantics::Symbol
&y
,
250 SetOfDerivedTypePairs
& /* inProgress - not yet used */) {
251 if (x
.attrs() != y
.attrs()) {
254 if (x
.attrs().test(semantics::Attr::PRIVATE
)) {
257 // TODO: compare types, parameters, bounds, &c.
258 return x
.has
<semantics::ObjectEntityDetails
>() ==
259 y
.has
<semantics::ObjectEntityDetails
>();
262 static bool AreSameDerivedType(const semantics::DerivedTypeSpec
&x
,
263 const semantics::DerivedTypeSpec
&y
, SetOfDerivedTypePairs
&inProgress
) {
264 const auto &xSymbol
{x
.typeSymbol()};
265 const auto &ySymbol
{y
.typeSymbol()};
266 if (&x
== &y
|| xSymbol
== ySymbol
) {
269 auto thisQuery
{std::make_pair(&x
, &y
)};
270 if (inProgress
.find(thisQuery
) != inProgress
.end()) {
271 return true; // recursive use of types in components
273 inProgress
.insert(thisQuery
);
274 const auto &xDetails
{xSymbol
.get
<semantics::DerivedTypeDetails
>()};
275 const auto &yDetails
{ySymbol
.get
<semantics::DerivedTypeDetails
>()};
276 if (xSymbol
.name() != ySymbol
.name()) {
279 if (!(xDetails
.sequence() && yDetails
.sequence()) &&
280 !(xSymbol
.attrs().test(semantics::Attr::BIND_C
) &&
281 ySymbol
.attrs().test(semantics::Attr::BIND_C
))) {
282 // PGI does not enforce this requirement; all other Fortran
283 // processors do with a hard error when violations are caught.
286 // Compare the component lists in their orders of declaration.
287 auto xEnd
{xDetails
.componentNames().cend()};
288 auto yComponentName
{yDetails
.componentNames().cbegin()};
289 auto yEnd
{yDetails
.componentNames().cend()};
290 for (auto xComponentName
{xDetails
.componentNames().cbegin()};
291 xComponentName
!= xEnd
; ++xComponentName
, ++yComponentName
) {
292 if (yComponentName
== yEnd
|| *xComponentName
!= *yComponentName
||
293 !xSymbol
.scope() || !ySymbol
.scope()) {
296 const auto xLookup
{xSymbol
.scope()->find(*xComponentName
)};
297 const auto yLookup
{ySymbol
.scope()->find(*yComponentName
)};
298 if (xLookup
== xSymbol
.scope()->end() ||
299 yLookup
== ySymbol
.scope()->end() ||
300 !AreSameComponent(*xLookup
->second
, *yLookup
->second
, inProgress
)) {
304 return yComponentName
== yEnd
;
307 bool AreSameDerivedType(
308 const semantics::DerivedTypeSpec
&x
, const semantics::DerivedTypeSpec
&y
) {
309 SetOfDerivedTypePairs inProgress
;
310 return AreSameDerivedType(x
, y
, inProgress
);
313 static bool AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec
*x
,
314 const semantics::DerivedTypeSpec
*y
, bool isPolymorphic
) {
318 if (AreSameDerivedType(*x
, *y
)) {
321 return isPolymorphic
&&
322 AreCompatibleDerivedTypes(x
, GetParentTypeSpec(*y
), true);
327 static bool AreCompatibleTypes(const DynamicType
&x
, const DynamicType
&y
,
328 bool ignoreTypeParameterValues
, bool ignoreLengths
) {
329 if (x
.IsUnlimitedPolymorphic()) {
331 } else if (y
.IsUnlimitedPolymorphic()) {
333 } else if (x
.category() != y
.category()) {
335 } else if (x
.category() == TypeCategory::Character
) {
336 const auto xLen
{x
.knownLength()};
337 const auto yLen
{y
.knownLength()};
338 return x
.kind() == y
.kind() &&
339 (ignoreLengths
|| !xLen
|| !yLen
|| *xLen
== *yLen
);
340 } else if (x
.category() != TypeCategory::Derived
) {
341 return x
.kind() == y
.kind();
343 const auto *xdt
{GetDerivedTypeSpec(x
)};
344 const auto *ydt
{GetDerivedTypeSpec(y
)};
345 return AreCompatibleDerivedTypes(xdt
, ydt
, x
.IsPolymorphic()) &&
346 (ignoreTypeParameterValues
||
347 (xdt
&& ydt
&& AreTypeParamCompatible(*xdt
, *ydt
)));
351 // See 7.3.2.3 (5) & 15.5.2.4
352 bool DynamicType::IsTkCompatibleWith(const DynamicType
&that
) const {
353 return AreCompatibleTypes(*this, that
, false, true);
356 bool DynamicType::IsTkLenCompatibleWith(const DynamicType
&that
) const {
357 return AreCompatibleTypes(*this, that
, false, false);
361 std::optional
<bool> DynamicType::SameTypeAs(const DynamicType
&that
) const {
362 bool x
{AreCompatibleTypes(*this, that
, true, true)};
363 bool y
{AreCompatibleTypes(that
, *this, true, true)};
366 } else if (x
&& y
&& !IsPolymorphic() && !that
.IsPolymorphic()) {
374 std::optional
<bool> DynamicType::ExtendsTypeOf(const DynamicType
&that
) const {
375 if (IsUnlimitedPolymorphic() || that
.IsUnlimitedPolymorphic()) {
376 return std::nullopt
; // unknown
378 const auto *thisDts
{evaluate::GetDerivedTypeSpec(*this)};
379 const auto *thatDts
{evaluate::GetDerivedTypeSpec(that
)};
380 if (!thisDts
|| !thatDts
) {
382 } else if (!AreCompatibleDerivedTypes(thatDts
, thisDts
, true)) {
383 // Note that I check *thisDts, not its parent, so that EXTENDS_TYPE_OF()
384 // is .true. when they are the same type. This is technically
385 // an implementation-defined case in the standard, but every other
386 // compiler works this way.
387 if (IsPolymorphic() && AreCompatibleDerivedTypes(thisDts
, thatDts
, true)) {
388 // 'that' is *this or an extension of *this, and so runtime *this
389 // could be an extension of 'that'
394 } else if (that
.IsPolymorphic()) {
395 return std::nullopt
; // unknown
401 std::optional
<DynamicType
> DynamicType::From(
402 const semantics::DeclTypeSpec
&type
) {
403 if (const auto *intrinsic
{type
.AsIntrinsic()}) {
404 if (auto kind
{ToInt64(intrinsic
->kind())}) {
405 TypeCategory category
{intrinsic
->category()};
406 if (IsValidKindOfIntrinsicType(category
, *kind
)) {
407 if (category
== TypeCategory::Character
) {
408 const auto &charType
{type
.characterTypeSpec()};
409 return DynamicType
{static_cast<int>(*kind
), charType
.length()};
411 return DynamicType
{category
, static_cast<int>(*kind
)};
415 } else if (const auto *derived
{type
.AsDerived()}) {
417 *derived
, type
.category() == semantics::DeclTypeSpec::ClassDerived
};
418 } else if (type
.category() == semantics::DeclTypeSpec::ClassStar
) {
419 return DynamicType::UnlimitedPolymorphic();
420 } else if (type
.category() == semantics::DeclTypeSpec::TypeStar
) {
421 return DynamicType::AssumedType();
423 common::die("DynamicType::From(DeclTypeSpec): failed");
428 std::optional
<DynamicType
> DynamicType::From(const semantics::Symbol
&symbol
) {
429 return From(symbol
.GetType()); // Symbol -> DeclTypeSpec -> DynamicType
432 DynamicType
DynamicType::ResultTypeForMultiply(const DynamicType
&that
) const {
434 case TypeCategory::Integer
:
435 switch (that
.category_
) {
436 case TypeCategory::Integer
:
437 return DynamicType
{TypeCategory::Integer
, std::max(kind_
, that
.kind_
)};
438 case TypeCategory::Real
:
439 case TypeCategory::Complex
:
445 case TypeCategory::Real
:
446 switch (that
.category_
) {
447 case TypeCategory::Integer
:
449 case TypeCategory::Real
:
450 return DynamicType
{TypeCategory::Real
, std::max(kind_
, that
.kind_
)};
451 case TypeCategory::Complex
:
452 return DynamicType
{TypeCategory::Complex
, std::max(kind_
, that
.kind_
)};
457 case TypeCategory::Complex
:
458 switch (that
.category_
) {
459 case TypeCategory::Integer
:
461 case TypeCategory::Real
:
462 case TypeCategory::Complex
:
463 return DynamicType
{TypeCategory::Complex
, std::max(kind_
, that
.kind_
)};
468 case TypeCategory::Logical
:
469 switch (that
.category_
) {
470 case TypeCategory::Logical
:
471 return DynamicType
{TypeCategory::Logical
, std::max(kind_
, that
.kind_
)};
482 bool DynamicType::RequiresDescriptor() const {
483 return IsPolymorphic() || IsNonConstantLengthCharacter() ||
484 (derived_
&& CountNonConstantLenParameters(*derived_
) > 0);
487 bool DynamicType::HasDeferredTypeParameter() const {
489 for (const auto &pair
: derived_
->parameters()) {
490 if (pair
.second
.isDeferred()) {
495 return charLengthParamValue_
&& charLengthParamValue_
->isDeferred();
498 bool SomeKind
<TypeCategory::Derived
>::operator==(
499 const SomeKind
<TypeCategory::Derived
> &that
) const {
500 return PointeeComparison(derivedTypeSpec_
, that
.derivedTypeSpec_
);
503 int SelectedCharKind(const std::string
&s
, int defaultKind
) { // 16.9.168
504 auto lower
{parser::ToLowerCaseLetters(s
)};
505 auto n
{lower
.size()};
506 while (n
> 0 && lower
[0] == ' ') {
510 while (n
> 0 && lower
[n
- 1] == ' ') {
513 if (lower
== "ascii") {
515 } else if (lower
== "ucs-2") {
517 } else if (lower
== "iso_10646" || lower
== "ucs-4") {
519 } else if (lower
== "default") {
526 std::optional
<DynamicType
> ComparisonType(
527 const DynamicType
&t1
, const DynamicType
&t2
) {
528 switch (t1
.category()) {
529 case TypeCategory::Integer
:
530 switch (t2
.category()) {
531 case TypeCategory::Integer
:
532 return DynamicType
{TypeCategory::Integer
, std::max(t1
.kind(), t2
.kind())};
533 case TypeCategory::Real
:
534 case TypeCategory::Complex
:
539 case TypeCategory::Real
:
540 switch (t2
.category()) {
541 case TypeCategory::Integer
:
543 case TypeCategory::Real
:
544 case TypeCategory::Complex
:
545 return DynamicType
{t2
.category(), std::max(t1
.kind(), t2
.kind())};
549 case TypeCategory::Complex
:
550 switch (t2
.category()) {
551 case TypeCategory::Integer
:
553 case TypeCategory::Real
:
554 case TypeCategory::Complex
:
555 return DynamicType
{TypeCategory::Complex
, std::max(t1
.kind(), t2
.kind())};
559 case TypeCategory::Character
:
560 switch (t2
.category()) {
561 case TypeCategory::Character
:
563 TypeCategory::Character
, std::max(t1
.kind(), t2
.kind())};
567 case TypeCategory::Logical
:
568 switch (t2
.category()) {
569 case TypeCategory::Logical
:
570 return DynamicType
{TypeCategory::Logical
, LogicalResult::kind
};
579 bool IsInteroperableIntrinsicType(const DynamicType
&type
) {
580 switch (type
.category()) {
581 case TypeCategory::Integer
:
583 case TypeCategory::Real
:
584 case TypeCategory::Complex
:
585 return type
.kind() >= 4; // no short or half floats
586 case TypeCategory::Logical
:
587 return type
.kind() == 1; // C_BOOL
588 case TypeCategory::Character
:
589 return type
.kind() == 1 /* C_CHAR */ && type
.knownLength().value_or(0) == 1;
591 // Derived types are tested in Semantics/check-declarations.cpp
596 } // namespace Fortran::evaluate