1 //===-- lib/Evaluate/type.cpp ---------------------------------------------===// 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 #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" 19 #include <algorithm> 20 #include <optional> 21 #include <string> 22 23 // IsDescriptor() predicate: true when a symbol is implemented 24 // at runtime with a descriptor. 25 namespace Fortran::semantics { 26 27 static bool IsDescriptor(const DeclTypeSpec *type) { 28 if (type) { 29 if (auto dynamicType{evaluate::DynamicType::From(*type)}) { 30 return dynamicType->RequiresDescriptor(); 31 } 32 } 33 return false; 34 } 35 36 static bool IsDescriptor(const ObjectEntityDetails &details) { 37 if (IsDescriptor(details.type())) { 38 return true; 39 } 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)) { 44 return true; 45 } 46 } 47 return false; 48 } 49 50 bool IsDescriptor(const Symbol &symbol) { 51 return common::visit( 52 common::visitors{ 53 [&](const ObjectEntityDetails &d) { 54 return IsAllocatableOrPointer(symbol) || IsDescriptor(d); 55 }, 56 [&](const ProcEntityDetails &d) { return false; }, 57 [&](const EntityDetails &d) { return IsDescriptor(d.type()); }, 58 [](const AssocEntityDetails &d) { 59 if (const auto &expr{d.expr()}) { 60 if (expr->Rank() > 0) { 61 return true; 62 } 63 if (const auto dynamicType{expr->GetType()}) { 64 if (dynamicType->RequiresDescriptor()) { 65 return true; 66 } 67 } 68 } 69 return false; 70 }, 71 [](const SubprogramDetails &d) { 72 return d.isFunction() && IsDescriptor(d.result()); 73 }, 74 [](const UseDetails &d) { return IsDescriptor(d.symbol()); }, 75 [](const HostAssocDetails &d) { return IsDescriptor(d.symbol()); }, 76 [](const auto &) { return false; }, 77 }, 78 symbol.details()); 79 } 80 81 bool IsPassedViaDescriptor(const Symbol &symbol) { 82 if (!IsDescriptor(symbol)) { 83 return false; 84 } 85 if (IsAllocatableOrPointer(symbol)) { 86 return true; 87 } 88 if (const auto *object{ 89 symbol.GetUltimate().detailsIf<ObjectEntityDetails>()}) { 90 if (object->isDummy()) { 91 if (object->type() && 92 object->type()->category() == DeclTypeSpec::Character) { 93 return false; 94 } 95 if (object->IsAssumedSize()) { 96 return false; 97 } 98 bool isExplicitShape{true}; 99 for (const ShapeSpec &shapeSpec : object->shape()) { 100 if (!shapeSpec.lbound().GetExplicit() || 101 !shapeSpec.ubound().GetExplicit()) { 102 isExplicitShape = false; 103 break; 104 } 105 } 106 if (isExplicitShape) { 107 return false; // explicit shape but non-constant bounds 108 } 109 } 110 } 111 return true; 112 } 113 } // namespace Fortran::semantics 114 115 namespace Fortran::evaluate { 116 117 DynamicType::DynamicType(int k, const semantics::ParamValue &pv) 118 : category_{TypeCategory::Character}, kind_{k} { 119 CHECK(IsValidKindOfIntrinsicType(category_, kind_)); 120 if (auto n{ToInt64(pv.GetExplicit())}) { 121 knownLength_ = *n > 0 ? *n : 0; 122 } else { 123 charLengthParamValue_ = &pv; 124 } 125 } 126 127 template <typename A> inline bool PointeeComparison(const A *x, const A *y) { 128 return x == y || (x && y && *x == *y); 129 } 130 131 bool DynamicType::operator==(const DynamicType &that) const { 132 return category_ == that.category_ && kind_ == that.kind_ && 133 PointeeComparison(charLengthParamValue_, that.charLengthParamValue_) && 134 knownLength().has_value() == that.knownLength().has_value() && 135 (!knownLength() || *knownLength() == *that.knownLength()) && 136 PointeeComparison(derived_, that.derived_); 137 } 138 139 std::optional<Expr<SubscriptInteger>> DynamicType::GetCharLength() const { 140 if (category_ == TypeCategory::Character) { 141 if (knownLength()) { 142 return AsExpr(Constant<SubscriptInteger>(*knownLength())); 143 } else if (charLengthParamValue_) { 144 if (auto length{charLengthParamValue_->GetExplicit()}) { 145 return ConvertToType<SubscriptInteger>(std::move(*length)); 146 } 147 } 148 } 149 return std::nullopt; 150 } 151 152 std::size_t DynamicType::GetAlignment( 153 const TargetCharacteristics &targetCharacteristics) const { 154 if (category_ == TypeCategory::Derived) { 155 switch (GetDerivedTypeSpec().category()) { 156 SWITCH_COVERS_ALL_CASES 157 case semantics::DerivedTypeSpec::Category::DerivedType: 158 if (derived_ && derived_->scope()) { 159 return derived_->scope()->alignment().value_or(1); 160 } 161 break; 162 case semantics::DerivedTypeSpec::Category::IntrinsicVector: 163 case semantics::DerivedTypeSpec::Category::PairVector: 164 case semantics::DerivedTypeSpec::Category::QuadVector: 165 if (derived_ && derived_->scope()) { 166 return derived_->scope()->size(); 167 } else { 168 common::die("Missing scope for Vector type."); 169 } 170 } 171 } else { 172 return targetCharacteristics.GetAlignment(category_, kind_); 173 } 174 return 1; // needs to be after switch to dodge a bogus gcc warning 175 } 176 177 std::optional<Expr<SubscriptInteger>> DynamicType::MeasureSizeInBytes( 178 FoldingContext &context, bool aligned, 179 std::optional<std::int64_t> charLength) const { 180 switch (category_) { 181 case TypeCategory::Integer: 182 case TypeCategory::Real: 183 case TypeCategory::Complex: 184 case TypeCategory::Logical: 185 return Expr<SubscriptInteger>{ 186 context.targetCharacteristics().GetByteSize(category_, kind_)}; 187 case TypeCategory::Character: 188 if (auto len{charLength ? Expr<SubscriptInteger>{Constant<SubscriptInteger>{ 189 *charLength}} 190 : GetCharLength()}) { 191 return Fold(context, 192 Expr<SubscriptInteger>{ 193 context.targetCharacteristics().GetByteSize(category_, kind_)} * 194 std::move(*len)); 195 } 196 break; 197 case TypeCategory::Derived: 198 if (!IsPolymorphic() && derived_ && derived_->scope()) { 199 auto size{derived_->scope()->size()}; 200 auto align{aligned ? derived_->scope()->alignment().value_or(0) : 0}; 201 auto alignedSize{align > 0 ? ((size + align - 1) / align) * align : size}; 202 return Expr<SubscriptInteger>{ 203 static_cast<ConstantSubscript>(alignedSize)}; 204 } 205 break; 206 } 207 return std::nullopt; 208 } 209 210 bool DynamicType::IsAssumedLengthCharacter() const { 211 return category_ == TypeCategory::Character && charLengthParamValue_ && 212 charLengthParamValue_->isAssumed(); 213 } 214 215 bool DynamicType::IsNonConstantLengthCharacter() const { 216 if (category_ != TypeCategory::Character) { 217 return false; 218 } else if (knownLength()) { 219 return false; 220 } else if (!charLengthParamValue_) { 221 return true; 222 } else if (const auto &expr{charLengthParamValue_->GetExplicit()}) { 223 return !IsConstantExpr(*expr); 224 } else { 225 return true; 226 } 227 } 228 229 bool DynamicType::IsTypelessIntrinsicArgument() const { 230 return category_ == TypeCategory::Integer && kind_ == TypelessKind; 231 } 232 233 const semantics::DerivedTypeSpec *GetDerivedTypeSpec( 234 const std::optional<DynamicType> &type) { 235 return type ? GetDerivedTypeSpec(*type) : nullptr; 236 } 237 238 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(const DynamicType &type) { 239 if (type.category() == TypeCategory::Derived && 240 !type.IsUnlimitedPolymorphic()) { 241 return &type.GetDerivedTypeSpec(); 242 } else { 243 return nullptr; 244 } 245 } 246 247 static const semantics::Symbol *FindParentComponent( 248 const semantics::DerivedTypeSpec &derived) { 249 const semantics::Symbol &typeSymbol{derived.typeSymbol()}; 250 const semantics::Scope *scope{derived.scope()}; 251 if (!scope) { 252 scope = typeSymbol.scope(); 253 } 254 if (scope) { 255 const auto &dtDetails{typeSymbol.get<semantics::DerivedTypeDetails>()}; 256 // TODO: Combine with semantics::DerivedTypeDetails::GetParentComponent 257 if (auto extends{dtDetails.GetParentComponentName()}) { 258 if (auto iter{scope->find(*extends)}; iter != scope->cend()) { 259 if (const semantics::Symbol & symbol{*iter->second}; 260 symbol.test(semantics::Symbol::Flag::ParentComp)) { 261 return &symbol; 262 } 263 } 264 } 265 } 266 return nullptr; 267 } 268 269 const semantics::DerivedTypeSpec *GetParentTypeSpec( 270 const semantics::DerivedTypeSpec &derived) { 271 if (const semantics::Symbol * parent{FindParentComponent(derived)}) { 272 return &parent->get<semantics::ObjectEntityDetails>() 273 .type() 274 ->derivedTypeSpec(); 275 } else { 276 return nullptr; 277 } 278 } 279 280 // Compares two derived type representations to see whether they both 281 // represent the "same type" in the sense of section 7.5.2.4. 282 using SetOfDerivedTypePairs = 283 std::set<std::pair<const semantics::DerivedTypeSpec *, 284 const semantics::DerivedTypeSpec *>>; 285 286 static bool AreSameComponent(const semantics::Symbol &x, 287 const semantics::Symbol &y, 288 SetOfDerivedTypePairs & /* inProgress - not yet used */) { 289 if (x.attrs() != y.attrs()) { 290 return false; 291 } 292 if (x.attrs().test(semantics::Attr::PRIVATE)) { 293 return false; 294 } 295 // TODO: compare types, parameters, bounds, &c. 296 return x.has<semantics::ObjectEntityDetails>() == 297 y.has<semantics::ObjectEntityDetails>(); 298 } 299 300 // TODO: These utilities were cloned out of Semantics to avoid a cyclic 301 // dependency and should be repackaged into then "namespace semantics" 302 // part of Evaluate/tools.cpp. 303 304 static const semantics::Symbol *GetParentComponent( 305 const semantics::DerivedTypeDetails &details, 306 const semantics::Scope &scope) { 307 if (auto extends{details.GetParentComponentName()}) { 308 if (auto iter{scope.find(*extends)}; iter != scope.cend()) { 309 if (const Symbol & symbol{*iter->second}; 310 symbol.test(semantics::Symbol::Flag::ParentComp)) { 311 return &symbol; 312 } 313 } 314 } 315 return nullptr; 316 } 317 318 static const semantics::Symbol *GetParentComponent( 319 const semantics::Symbol *symbol, const semantics::Scope &scope) { 320 if (symbol) { 321 if (const auto *dtDetails{ 322 symbol->detailsIf<semantics::DerivedTypeDetails>()}) { 323 return GetParentComponent(*dtDetails, scope); 324 } 325 } 326 return nullptr; 327 } 328 329 static const semantics::DerivedTypeSpec *GetParentTypeSpec( 330 const semantics::Symbol *symbol, const semantics::Scope &scope) { 331 if (const Symbol * parentComponent{GetParentComponent(symbol, scope)}) { 332 return &parentComponent->get<semantics::ObjectEntityDetails>() 333 .type() 334 ->derivedTypeSpec(); 335 } else { 336 return nullptr; 337 } 338 } 339 340 static const semantics::Scope *GetDerivedTypeParent( 341 const semantics::Scope *scope) { 342 if (scope) { 343 CHECK(scope->IsDerivedType()); 344 if (const auto *parent{GetParentTypeSpec(scope->GetSymbol(), *scope)}) { 345 return parent->scope(); 346 } 347 } 348 return nullptr; 349 } 350 351 static const semantics::Symbol *FindComponent( 352 const semantics::Scope *scope, parser::CharBlock name) { 353 if (!scope) { 354 return nullptr; 355 } 356 CHECK(scope->IsDerivedType()); 357 auto found{scope->find(name)}; 358 if (found != scope->end()) { 359 return &*found->second; 360 } else { 361 return FindComponent(GetDerivedTypeParent(scope), name); 362 } 363 } 364 365 static bool AreTypeParamCompatible(const semantics::DerivedTypeSpec &x, 366 const semantics::DerivedTypeSpec &y, bool ignoreLenParameters) { 367 const auto *xScope{x.typeSymbol().scope()}; 368 const auto *yScope{y.typeSymbol().scope()}; 369 for (const auto &[paramName, value] : x.parameters()) { 370 const auto *yValue{y.FindParameter(paramName)}; 371 if (!yValue) { 372 return false; 373 } 374 const auto *xParm{FindComponent(xScope, paramName)}; 375 const auto *yParm{FindComponent(yScope, paramName)}; 376 if (xParm && yParm) { 377 const auto *xTPD{xParm->detailsIf<semantics::TypeParamDetails>()}; 378 const auto *yTPD{yParm->detailsIf<semantics::TypeParamDetails>()}; 379 if (xTPD && yTPD) { 380 if (xTPD->attr() != yTPD->attr()) { 381 return false; 382 } 383 if (!ignoreLenParameters || 384 xTPD->attr() != common::TypeParamAttr::Len) { 385 auto xExpr{value.GetExplicit()}; 386 auto yExpr{yValue->GetExplicit()}; 387 if (xExpr && yExpr) { 388 auto xVal{ToInt64(*xExpr)}; 389 auto yVal{ToInt64(*yExpr)}; 390 if (xVal && yVal && *xVal != *yVal) { 391 return false; 392 } 393 } 394 } 395 } 396 } 397 } 398 for (const auto &[paramName, _] : y.parameters()) { 399 if (!x.FindParameter(paramName)) { 400 return false; // y has more parameters than x 401 } 402 } 403 return true; 404 } 405 406 static bool AreSameDerivedType(const semantics::DerivedTypeSpec &x, 407 const semantics::DerivedTypeSpec &y, bool ignoreTypeParameterValues, 408 bool ignoreLenParameters, SetOfDerivedTypePairs &inProgress) { 409 if (&x == &y) { 410 return true; 411 } 412 if (!ignoreTypeParameterValues && 413 !AreTypeParamCompatible(x, y, ignoreLenParameters)) { 414 return false; 415 } 416 const auto &xSymbol{x.typeSymbol()}; 417 const auto &ySymbol{y.typeSymbol()}; 418 if (xSymbol == ySymbol) { 419 return true; 420 } 421 if (xSymbol.name() != ySymbol.name()) { 422 return false; 423 } 424 auto thisQuery{std::make_pair(&x, &y)}; 425 if (inProgress.find(thisQuery) != inProgress.end()) { 426 return true; // recursive use of types in components 427 } 428 inProgress.insert(thisQuery); 429 const auto &xDetails{xSymbol.get<semantics::DerivedTypeDetails>()}; 430 const auto &yDetails{ySymbol.get<semantics::DerivedTypeDetails>()}; 431 if (!(xDetails.sequence() && yDetails.sequence()) && 432 !(xSymbol.attrs().test(semantics::Attr::BIND_C) && 433 ySymbol.attrs().test(semantics::Attr::BIND_C))) { 434 // PGI does not enforce this requirement; all other Fortran 435 // processors do with a hard error when violations are caught. 436 return false; 437 } 438 // Compare the component lists in their orders of declaration. 439 auto xEnd{xDetails.componentNames().cend()}; 440 auto yComponentName{yDetails.componentNames().cbegin()}; 441 auto yEnd{yDetails.componentNames().cend()}; 442 for (auto xComponentName{xDetails.componentNames().cbegin()}; 443 xComponentName != xEnd; ++xComponentName, ++yComponentName) { 444 if (yComponentName == yEnd || *xComponentName != *yComponentName || 445 !xSymbol.scope() || !ySymbol.scope()) { 446 return false; 447 } 448 const auto xLookup{xSymbol.scope()->find(*xComponentName)}; 449 const auto yLookup{ySymbol.scope()->find(*yComponentName)}; 450 if (xLookup == xSymbol.scope()->end() || 451 yLookup == ySymbol.scope()->end() || 452 !AreSameComponent(*xLookup->second, *yLookup->second, inProgress)) { 453 return false; 454 } 455 } 456 return yComponentName == yEnd; 457 } 458 459 bool AreSameDerivedType( 460 const semantics::DerivedTypeSpec &x, const semantics::DerivedTypeSpec &y) { 461 SetOfDerivedTypePairs inProgress; 462 return AreSameDerivedType(x, y, false, false, inProgress); 463 } 464 465 static bool AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec *x, 466 const semantics::DerivedTypeSpec *y, bool isPolymorphic, 467 bool ignoreTypeParameterValues, bool ignoreLenTypeParameters) { 468 if (!x || !y) { 469 return false; 470 } else { 471 SetOfDerivedTypePairs inProgress; 472 if (AreSameDerivedType(*x, *y, ignoreTypeParameterValues, 473 ignoreLenTypeParameters, inProgress)) { 474 return true; 475 } else { 476 return isPolymorphic && 477 AreCompatibleDerivedTypes(x, GetParentTypeSpec(*y), true, 478 ignoreTypeParameterValues, ignoreLenTypeParameters); 479 } 480 } 481 } 482 483 static bool AreCompatibleTypes(const DynamicType &x, const DynamicType &y, 484 bool ignoreTypeParameterValues, bool ignoreLengths) { 485 if (x.IsUnlimitedPolymorphic()) { 486 return true; 487 } else if (y.IsUnlimitedPolymorphic()) { 488 return false; 489 } else if (x.category() != y.category()) { 490 return false; 491 } else if (x.category() == TypeCategory::Character) { 492 const auto xLen{x.knownLength()}; 493 const auto yLen{y.knownLength()}; 494 return x.kind() == y.kind() && 495 (ignoreLengths || !xLen || !yLen || *xLen == *yLen); 496 } else if (x.category() != TypeCategory::Derived) { 497 return x.kind() == y.kind(); 498 } else { 499 const auto *xdt{GetDerivedTypeSpec(x)}; 500 const auto *ydt{GetDerivedTypeSpec(y)}; 501 return AreCompatibleDerivedTypes( 502 xdt, ydt, x.IsPolymorphic(), ignoreTypeParameterValues, false); 503 } 504 } 505 506 // See 7.3.2.3 (5) & 15.5.2.4 507 bool DynamicType::IsTkCompatibleWith(const DynamicType &that) const { 508 return AreCompatibleTypes(*this, that, false, true); 509 } 510 511 bool DynamicType::IsTkCompatibleWith( 512 const DynamicType &that, common::IgnoreTKRSet ignoreTKR) const { 513 if (ignoreTKR.test(common::IgnoreTKR::Type) && 514 (category() == TypeCategory::Derived || 515 that.category() == TypeCategory::Derived || 516 category() != that.category())) { 517 return true; 518 } else if (ignoreTKR.test(common::IgnoreTKR::Kind) && 519 category() == that.category()) { 520 return true; 521 } else { 522 return AreCompatibleTypes(*this, that, false, true); 523 } 524 } 525 526 bool DynamicType::IsTkLenCompatibleWith(const DynamicType &that) const { 527 return AreCompatibleTypes(*this, that, false, false); 528 } 529 530 // 16.9.165 531 std::optional<bool> DynamicType::SameTypeAs(const DynamicType &that) const { 532 bool x{AreCompatibleTypes(*this, that, true, true)}; 533 bool y{AreCompatibleTypes(that, *this, true, true)}; 534 if (!x && !y) { 535 return false; 536 } else if (x && y && !IsPolymorphic() && !that.IsPolymorphic()) { 537 return true; 538 } else { 539 return std::nullopt; 540 } 541 } 542 543 // 16.9.76 544 std::optional<bool> DynamicType::ExtendsTypeOf(const DynamicType &that) const { 545 if (IsUnlimitedPolymorphic() || that.IsUnlimitedPolymorphic()) { 546 return std::nullopt; // unknown 547 } 548 const auto *thisDts{evaluate::GetDerivedTypeSpec(*this)}; 549 const auto *thatDts{evaluate::GetDerivedTypeSpec(that)}; 550 if (!thisDts || !thatDts) { 551 return std::nullopt; 552 } else if (!AreCompatibleDerivedTypes(thatDts, thisDts, true, true, true)) { 553 // Note that I check *thisDts, not its parent, so that EXTENDS_TYPE_OF() 554 // is .true. when they are the same type. This is technically 555 // an implementation-defined case in the standard, but every other 556 // compiler works this way. 557 if (IsPolymorphic() && 558 AreCompatibleDerivedTypes(thisDts, thatDts, true, true, true)) { 559 // 'that' is *this or an extension of *this, and so runtime *this 560 // could be an extension of 'that' 561 return std::nullopt; 562 } else { 563 return false; 564 } 565 } else if (that.IsPolymorphic()) { 566 return std::nullopt; // unknown 567 } else { 568 return true; 569 } 570 } 571 572 std::optional<DynamicType> DynamicType::From( 573 const semantics::DeclTypeSpec &type) { 574 if (const auto *intrinsic{type.AsIntrinsic()}) { 575 if (auto kind{ToInt64(intrinsic->kind())}) { 576 TypeCategory category{intrinsic->category()}; 577 if (IsValidKindOfIntrinsicType(category, *kind)) { 578 if (category == TypeCategory::Character) { 579 const auto &charType{type.characterTypeSpec()}; 580 return DynamicType{static_cast<int>(*kind), charType.length()}; 581 } else { 582 return DynamicType{category, static_cast<int>(*kind)}; 583 } 584 } 585 } 586 } else if (const auto *derived{type.AsDerived()}) { 587 return DynamicType{ 588 *derived, type.category() == semantics::DeclTypeSpec::ClassDerived}; 589 } else if (type.category() == semantics::DeclTypeSpec::ClassStar) { 590 return DynamicType::UnlimitedPolymorphic(); 591 } else if (type.category() == semantics::DeclTypeSpec::TypeStar) { 592 return DynamicType::AssumedType(); 593 } else { 594 common::die("DynamicType::From(DeclTypeSpec): failed"); 595 } 596 return std::nullopt; 597 } 598 599 std::optional<DynamicType> DynamicType::From(const semantics::Symbol &symbol) { 600 return From(symbol.GetType()); // Symbol -> DeclTypeSpec -> DynamicType 601 } 602 603 DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const { 604 switch (category_) { 605 case TypeCategory::Integer: 606 switch (that.category_) { 607 case TypeCategory::Integer: 608 return DynamicType{TypeCategory::Integer, std::max(kind_, that.kind_)}; 609 case TypeCategory::Real: 610 case TypeCategory::Complex: 611 return that; 612 default: 613 CRASH_NO_CASE; 614 } 615 break; 616 case TypeCategory::Real: 617 switch (that.category_) { 618 case TypeCategory::Integer: 619 return *this; 620 case TypeCategory::Real: 621 return DynamicType{TypeCategory::Real, std::max(kind_, that.kind_)}; 622 case TypeCategory::Complex: 623 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 624 default: 625 CRASH_NO_CASE; 626 } 627 break; 628 case TypeCategory::Complex: 629 switch (that.category_) { 630 case TypeCategory::Integer: 631 return *this; 632 case TypeCategory::Real: 633 case TypeCategory::Complex: 634 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 635 default: 636 CRASH_NO_CASE; 637 } 638 break; 639 case TypeCategory::Logical: 640 switch (that.category_) { 641 case TypeCategory::Logical: 642 return DynamicType{TypeCategory::Logical, std::max(kind_, that.kind_)}; 643 default: 644 CRASH_NO_CASE; 645 } 646 break; 647 default: 648 CRASH_NO_CASE; 649 } 650 return *this; 651 } 652 653 bool DynamicType::RequiresDescriptor() const { 654 return IsPolymorphic() || IsNonConstantLengthCharacter() || 655 (derived_ && CountNonConstantLenParameters(*derived_) > 0); 656 } 657 658 bool DynamicType::HasDeferredTypeParameter() const { 659 if (derived_) { 660 for (const auto &pair : derived_->parameters()) { 661 if (pair.second.isDeferred()) { 662 return true; 663 } 664 } 665 } 666 return charLengthParamValue_ && charLengthParamValue_->isDeferred(); 667 } 668 669 bool SomeKind<TypeCategory::Derived>::operator==( 670 const SomeKind<TypeCategory::Derived> &that) const { 671 return PointeeComparison(derivedTypeSpec_, that.derivedTypeSpec_); 672 } 673 674 int SelectedCharKind(const std::string &s, int defaultKind) { // 16.9.168 675 auto lower{parser::ToLowerCaseLetters(s)}; 676 auto n{lower.size()}; 677 while (n > 0 && lower[0] == ' ') { 678 lower.erase(0, 1); 679 --n; 680 } 681 while (n > 0 && lower[n - 1] == ' ') { 682 lower.erase(--n, 1); 683 } 684 if (lower == "ascii") { 685 return 1; 686 } else if (lower == "ucs-2") { 687 return 2; 688 } else if (lower == "iso_10646" || lower == "ucs-4") { 689 return 4; 690 } else if (lower == "default") { 691 return defaultKind; 692 } else { 693 return -1; 694 } 695 } 696 697 std::optional<DynamicType> ComparisonType( 698 const DynamicType &t1, const DynamicType &t2) { 699 switch (t1.category()) { 700 case TypeCategory::Integer: 701 switch (t2.category()) { 702 case TypeCategory::Integer: 703 return DynamicType{TypeCategory::Integer, std::max(t1.kind(), t2.kind())}; 704 case TypeCategory::Real: 705 case TypeCategory::Complex: 706 return t2; 707 default: 708 return std::nullopt; 709 } 710 case TypeCategory::Real: 711 switch (t2.category()) { 712 case TypeCategory::Integer: 713 return t1; 714 case TypeCategory::Real: 715 case TypeCategory::Complex: 716 return DynamicType{t2.category(), std::max(t1.kind(), t2.kind())}; 717 default: 718 return std::nullopt; 719 } 720 case TypeCategory::Complex: 721 switch (t2.category()) { 722 case TypeCategory::Integer: 723 return t1; 724 case TypeCategory::Real: 725 case TypeCategory::Complex: 726 return DynamicType{TypeCategory::Complex, std::max(t1.kind(), t2.kind())}; 727 default: 728 return std::nullopt; 729 } 730 case TypeCategory::Character: 731 switch (t2.category()) { 732 case TypeCategory::Character: 733 return DynamicType{ 734 TypeCategory::Character, std::max(t1.kind(), t2.kind())}; 735 default: 736 return std::nullopt; 737 } 738 case TypeCategory::Logical: 739 switch (t2.category()) { 740 case TypeCategory::Logical: 741 return DynamicType{TypeCategory::Logical, LogicalResult::kind}; 742 default: 743 return std::nullopt; 744 } 745 default: 746 return std::nullopt; 747 } 748 } 749 750 bool IsInteroperableIntrinsicType( 751 const DynamicType &type, bool checkCharLength) { 752 switch (type.category()) { 753 case TypeCategory::Integer: 754 return true; 755 case TypeCategory::Real: 756 case TypeCategory::Complex: 757 return type.kind() >= 4; // no short or half floats 758 case TypeCategory::Logical: 759 return type.kind() == 1; // C_BOOL 760 case TypeCategory::Character: 761 if (checkCharLength && type.knownLength().value_or(0) != 1) { 762 return false; 763 } 764 return type.kind() == 1 /* C_CHAR */; 765 default: 766 // Derived types are tested in Semantics/check-declarations.cpp 767 return false; 768 } 769 } 770 771 } // namespace Fortran::evaluate 772