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 AreSameDerivedType(const semantics::DerivedTypeSpec &, 287 const semantics::DerivedTypeSpec &, bool ignoreTypeParameterValues, 288 bool ignoreLenParameters, SetOfDerivedTypePairs &inProgress); 289 290 // F2023 7.5.3.2 291 static bool AreSameComponent(const semantics::Symbol &x, 292 const semantics::Symbol &y, SetOfDerivedTypePairs &inProgress) { 293 if (x.attrs() != y.attrs()) { 294 return false; 295 } 296 if (x.attrs().test(semantics::Attr::PRIVATE)) { 297 return false; 298 } 299 if (x.size() && y.size()) { 300 if (x.offset() != y.offset() || x.size() != y.size()) { 301 return false; 302 } 303 } 304 const auto *xObj{x.detailsIf<semantics::ObjectEntityDetails>()}; 305 const auto *yObj{y.detailsIf<semantics::ObjectEntityDetails>()}; 306 const auto *xProc{x.detailsIf<semantics::ProcEntityDetails>()}; 307 const auto *yProc{y.detailsIf<semantics::ProcEntityDetails>()}; 308 if (!xObj != !yObj || !xProc != !yProc) { 309 return false; 310 } 311 auto xType{DynamicType::From(x)}; 312 auto yType{DynamicType::From(y)}; 313 if (xType && yType) { 314 if (xType->category() == TypeCategory::Derived) { 315 if (yType->category() != TypeCategory::Derived || 316 !xType->IsUnlimitedPolymorphic() != 317 !yType->IsUnlimitedPolymorphic() || 318 (!xType->IsUnlimitedPolymorphic() && 319 !AreSameDerivedType(xType->GetDerivedTypeSpec(), 320 yType->GetDerivedTypeSpec(), false, false, inProgress))) { 321 return false; 322 } 323 } else if (!xType->IsTkLenCompatibleWith(*yType)) { 324 return false; 325 } 326 } else if (xType || yType || !(xProc && yProc)) { 327 return false; 328 } 329 if (xProc) { 330 // TODO: compare argument types, &c. 331 } 332 return true; 333 } 334 335 // TODO: These utilities were cloned out of Semantics to avoid a cyclic 336 // dependency and should be repackaged into then "namespace semantics" 337 // part of Evaluate/tools.cpp. 338 339 static const semantics::Symbol *GetParentComponent( 340 const semantics::DerivedTypeDetails &details, 341 const semantics::Scope &scope) { 342 if (auto extends{details.GetParentComponentName()}) { 343 if (auto iter{scope.find(*extends)}; iter != scope.cend()) { 344 if (const Symbol & symbol{*iter->second}; 345 symbol.test(semantics::Symbol::Flag::ParentComp)) { 346 return &symbol; 347 } 348 } 349 } 350 return nullptr; 351 } 352 353 static const semantics::Symbol *GetParentComponent( 354 const semantics::Symbol *symbol, const semantics::Scope &scope) { 355 if (symbol) { 356 if (const auto *dtDetails{ 357 symbol->detailsIf<semantics::DerivedTypeDetails>()}) { 358 return GetParentComponent(*dtDetails, scope); 359 } 360 } 361 return nullptr; 362 } 363 364 static const semantics::DerivedTypeSpec *GetParentTypeSpec( 365 const semantics::Symbol *symbol, const semantics::Scope &scope) { 366 if (const Symbol * parentComponent{GetParentComponent(symbol, scope)}) { 367 return &parentComponent->get<semantics::ObjectEntityDetails>() 368 .type() 369 ->derivedTypeSpec(); 370 } else { 371 return nullptr; 372 } 373 } 374 375 static const semantics::Scope *GetDerivedTypeParent( 376 const semantics::Scope *scope) { 377 if (scope) { 378 CHECK(scope->IsDerivedType()); 379 if (const auto *parent{GetParentTypeSpec(scope->GetSymbol(), *scope)}) { 380 return parent->scope(); 381 } 382 } 383 return nullptr; 384 } 385 386 static const semantics::Symbol *FindComponent( 387 const semantics::Scope *scope, parser::CharBlock name) { 388 if (!scope) { 389 return nullptr; 390 } 391 CHECK(scope->IsDerivedType()); 392 auto found{scope->find(name)}; 393 if (found != scope->end()) { 394 return &*found->second; 395 } else { 396 return FindComponent(GetDerivedTypeParent(scope), name); 397 } 398 } 399 400 static bool AreTypeParamCompatible(const semantics::DerivedTypeSpec &x, 401 const semantics::DerivedTypeSpec &y, bool ignoreLenParameters) { 402 const auto *xScope{x.typeSymbol().scope()}; 403 const auto *yScope{y.typeSymbol().scope()}; 404 for (const auto &[paramName, value] : x.parameters()) { 405 const auto *yValue{y.FindParameter(paramName)}; 406 if (!yValue) { 407 return false; 408 } 409 const auto *xParm{FindComponent(xScope, paramName)}; 410 const auto *yParm{FindComponent(yScope, paramName)}; 411 if (xParm && yParm) { 412 const auto *xTPD{xParm->detailsIf<semantics::TypeParamDetails>()}; 413 const auto *yTPD{yParm->detailsIf<semantics::TypeParamDetails>()}; 414 if (xTPD && yTPD) { 415 if (xTPD->attr() != yTPD->attr()) { 416 return false; 417 } 418 if (!ignoreLenParameters || 419 xTPD->attr() != common::TypeParamAttr::Len) { 420 auto xExpr{value.GetExplicit()}; 421 auto yExpr{yValue->GetExplicit()}; 422 if (xExpr && yExpr) { 423 auto xVal{ToInt64(*xExpr)}; 424 auto yVal{ToInt64(*yExpr)}; 425 if (xVal && yVal && *xVal != *yVal) { 426 return false; 427 } 428 } 429 } 430 } 431 } 432 } 433 for (const auto &[paramName, _] : y.parameters()) { 434 if (!x.FindParameter(paramName)) { 435 return false; // y has more parameters than x 436 } 437 } 438 return true; 439 } 440 441 // F2023 7.5.3.2 442 static bool AreSameDerivedType(const semantics::DerivedTypeSpec &x, 443 const semantics::DerivedTypeSpec &y, bool ignoreTypeParameterValues, 444 bool ignoreLenParameters, SetOfDerivedTypePairs &inProgress) { 445 if (&x == &y) { 446 return true; 447 } 448 if (!ignoreTypeParameterValues && 449 !AreTypeParamCompatible(x, y, ignoreLenParameters)) { 450 return false; 451 } 452 const auto &xSymbol{x.typeSymbol().GetUltimate()}; 453 const auto &ySymbol{y.typeSymbol().GetUltimate()}; 454 if (xSymbol == ySymbol) { 455 return true; 456 } 457 if (xSymbol.name() != ySymbol.name()) { 458 return false; 459 } 460 auto thisQuery{std::make_pair(&x, &y)}; 461 if (inProgress.find(thisQuery) != inProgress.end()) { 462 return true; // recursive use of types in components 463 } 464 inProgress.insert(thisQuery); 465 const auto &xDetails{xSymbol.get<semantics::DerivedTypeDetails>()}; 466 const auto &yDetails{ySymbol.get<semantics::DerivedTypeDetails>()}; 467 if (!(xDetails.sequence() && yDetails.sequence()) && 468 !(xSymbol.attrs().test(semantics::Attr::BIND_C) && 469 ySymbol.attrs().test(semantics::Attr::BIND_C))) { 470 // PGI does not enforce this requirement; all other Fortran 471 // compilers do with a hard error when violations are caught. 472 return false; 473 } 474 // Compare the component lists in their orders of declaration. 475 auto xEnd{xDetails.componentNames().cend()}; 476 auto yComponentName{yDetails.componentNames().cbegin()}; 477 auto yEnd{yDetails.componentNames().cend()}; 478 for (auto xComponentName{xDetails.componentNames().cbegin()}; 479 xComponentName != xEnd; ++xComponentName, ++yComponentName) { 480 if (yComponentName == yEnd || *xComponentName != *yComponentName || 481 !xSymbol.scope() || !ySymbol.scope()) { 482 return false; 483 } 484 const auto xLookup{xSymbol.scope()->find(*xComponentName)}; 485 const auto yLookup{ySymbol.scope()->find(*yComponentName)}; 486 if (xLookup == xSymbol.scope()->end() || 487 yLookup == ySymbol.scope()->end() || 488 !AreSameComponent(*xLookup->second, *yLookup->second, inProgress)) { 489 return false; 490 } 491 } 492 return yComponentName == yEnd; 493 } 494 495 bool AreSameDerivedType( 496 const semantics::DerivedTypeSpec &x, const semantics::DerivedTypeSpec &y) { 497 SetOfDerivedTypePairs inProgress; 498 return AreSameDerivedType(x, y, false, false, inProgress); 499 } 500 501 static bool AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec *x, 502 const semantics::DerivedTypeSpec *y, bool isPolymorphic, 503 bool ignoreTypeParameterValues, bool ignoreLenTypeParameters) { 504 if (!x || !y) { 505 return false; 506 } else { 507 SetOfDerivedTypePairs inProgress; 508 if (AreSameDerivedType(*x, *y, ignoreTypeParameterValues, 509 ignoreLenTypeParameters, inProgress)) { 510 return true; 511 } else { 512 return isPolymorphic && 513 AreCompatibleDerivedTypes(x, GetParentTypeSpec(*y), true, 514 ignoreTypeParameterValues, ignoreLenTypeParameters); 515 } 516 } 517 } 518 519 static bool AreCompatibleTypes(const DynamicType &x, const DynamicType &y, 520 bool ignoreTypeParameterValues, bool ignoreLengths) { 521 if (x.IsUnlimitedPolymorphic()) { 522 return true; 523 } else if (y.IsUnlimitedPolymorphic()) { 524 return false; 525 } else if (x.category() != y.category()) { 526 return false; 527 } else if (x.category() == TypeCategory::Character) { 528 const auto xLen{x.knownLength()}; 529 const auto yLen{y.knownLength()}; 530 return x.kind() == y.kind() && 531 (ignoreLengths || !xLen || !yLen || *xLen == *yLen); 532 } else if (x.category() != TypeCategory::Derived) { 533 return x.kind() == y.kind(); 534 } else { 535 const auto *xdt{GetDerivedTypeSpec(x)}; 536 const auto *ydt{GetDerivedTypeSpec(y)}; 537 return AreCompatibleDerivedTypes( 538 xdt, ydt, x.IsPolymorphic(), ignoreTypeParameterValues, false); 539 } 540 } 541 542 // See 7.3.2.3 (5) & 15.5.2.4 543 bool DynamicType::IsTkCompatibleWith(const DynamicType &that) const { 544 return AreCompatibleTypes(*this, that, false, true); 545 } 546 547 bool DynamicType::IsTkCompatibleWith( 548 const DynamicType &that, common::IgnoreTKRSet ignoreTKR) const { 549 if (ignoreTKR.test(common::IgnoreTKR::Type) && 550 (category() == TypeCategory::Derived || 551 that.category() == TypeCategory::Derived || 552 category() != that.category())) { 553 return true; 554 } else if (ignoreTKR.test(common::IgnoreTKR::Kind) && 555 category() == that.category()) { 556 return true; 557 } else { 558 return AreCompatibleTypes(*this, that, false, true); 559 } 560 } 561 562 bool DynamicType::IsTkLenCompatibleWith(const DynamicType &that) const { 563 return AreCompatibleTypes(*this, that, false, false); 564 } 565 566 // 16.9.165 567 std::optional<bool> DynamicType::SameTypeAs(const DynamicType &that) const { 568 bool x{AreCompatibleTypes(*this, that, true, true)}; 569 bool y{AreCompatibleTypes(that, *this, true, true)}; 570 if (!x && !y) { 571 return false; 572 } else if (x && y && !IsPolymorphic() && !that.IsPolymorphic()) { 573 return true; 574 } else { 575 return std::nullopt; 576 } 577 } 578 579 // 16.9.76 580 std::optional<bool> DynamicType::ExtendsTypeOf(const DynamicType &that) const { 581 if (IsUnlimitedPolymorphic() || that.IsUnlimitedPolymorphic()) { 582 return std::nullopt; // unknown 583 } 584 const auto *thisDts{evaluate::GetDerivedTypeSpec(*this)}; 585 const auto *thatDts{evaluate::GetDerivedTypeSpec(that)}; 586 if (!thisDts || !thatDts) { 587 return std::nullopt; 588 } else if (!AreCompatibleDerivedTypes(thatDts, thisDts, true, true, true)) { 589 // Note that I check *thisDts, not its parent, so that EXTENDS_TYPE_OF() 590 // is .true. when they are the same type. This is technically 591 // an implementation-defined case in the standard, but every other 592 // compiler works this way. 593 if (IsPolymorphic() && 594 AreCompatibleDerivedTypes(thisDts, thatDts, true, true, true)) { 595 // 'that' is *this or an extension of *this, and so runtime *this 596 // could be an extension of 'that' 597 return std::nullopt; 598 } else { 599 return false; 600 } 601 } else if (that.IsPolymorphic()) { 602 return std::nullopt; // unknown 603 } else { 604 return true; 605 } 606 } 607 608 std::optional<DynamicType> DynamicType::From( 609 const semantics::DeclTypeSpec &type) { 610 if (const auto *intrinsic{type.AsIntrinsic()}) { 611 if (auto kind{ToInt64(intrinsic->kind())}) { 612 TypeCategory category{intrinsic->category()}; 613 if (IsValidKindOfIntrinsicType(category, *kind)) { 614 if (category == TypeCategory::Character) { 615 const auto &charType{type.characterTypeSpec()}; 616 return DynamicType{static_cast<int>(*kind), charType.length()}; 617 } else { 618 return DynamicType{category, static_cast<int>(*kind)}; 619 } 620 } 621 } 622 } else if (const auto *derived{type.AsDerived()}) { 623 return DynamicType{ 624 *derived, type.category() == semantics::DeclTypeSpec::ClassDerived}; 625 } else if (type.category() == semantics::DeclTypeSpec::ClassStar) { 626 return DynamicType::UnlimitedPolymorphic(); 627 } else if (type.category() == semantics::DeclTypeSpec::TypeStar) { 628 return DynamicType::AssumedType(); 629 } else { 630 common::die("DynamicType::From(DeclTypeSpec): failed"); 631 } 632 return std::nullopt; 633 } 634 635 std::optional<DynamicType> DynamicType::From(const semantics::Symbol &symbol) { 636 return From(symbol.GetType()); // Symbol -> DeclTypeSpec -> DynamicType 637 } 638 639 DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const { 640 switch (category_) { 641 case TypeCategory::Integer: 642 switch (that.category_) { 643 case TypeCategory::Integer: 644 return DynamicType{TypeCategory::Integer, std::max(kind_, that.kind_)}; 645 case TypeCategory::Real: 646 case TypeCategory::Complex: 647 return that; 648 default: 649 CRASH_NO_CASE; 650 } 651 break; 652 case TypeCategory::Real: 653 switch (that.category_) { 654 case TypeCategory::Integer: 655 return *this; 656 case TypeCategory::Real: 657 return DynamicType{TypeCategory::Real, std::max(kind_, that.kind_)}; 658 case TypeCategory::Complex: 659 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 660 default: 661 CRASH_NO_CASE; 662 } 663 break; 664 case TypeCategory::Complex: 665 switch (that.category_) { 666 case TypeCategory::Integer: 667 return *this; 668 case TypeCategory::Real: 669 case TypeCategory::Complex: 670 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 671 default: 672 CRASH_NO_CASE; 673 } 674 break; 675 case TypeCategory::Logical: 676 switch (that.category_) { 677 case TypeCategory::Logical: 678 return DynamicType{TypeCategory::Logical, std::max(kind_, that.kind_)}; 679 default: 680 CRASH_NO_CASE; 681 } 682 break; 683 default: 684 CRASH_NO_CASE; 685 } 686 return *this; 687 } 688 689 bool DynamicType::RequiresDescriptor() const { 690 return IsPolymorphic() || IsNonConstantLengthCharacter() || 691 (derived_ && CountNonConstantLenParameters(*derived_) > 0); 692 } 693 694 bool DynamicType::HasDeferredTypeParameter() const { 695 if (derived_) { 696 for (const auto &pair : derived_->parameters()) { 697 if (pair.second.isDeferred()) { 698 return true; 699 } 700 } 701 } 702 return charLengthParamValue_ && charLengthParamValue_->isDeferred(); 703 } 704 705 bool SomeKind<TypeCategory::Derived>::operator==( 706 const SomeKind<TypeCategory::Derived> &that) const { 707 return PointeeComparison(derivedTypeSpec_, that.derivedTypeSpec_); 708 } 709 710 int SelectedCharKind(const std::string &s, int defaultKind) { // 16.9.168 711 auto lower{parser::ToLowerCaseLetters(s)}; 712 auto n{lower.size()}; 713 while (n > 0 && lower[0] == ' ') { 714 lower.erase(0, 1); 715 --n; 716 } 717 while (n > 0 && lower[n - 1] == ' ') { 718 lower.erase(--n, 1); 719 } 720 if (lower == "ascii") { 721 return 1; 722 } else if (lower == "ucs-2") { 723 return 2; 724 } else if (lower == "iso_10646" || lower == "ucs-4") { 725 return 4; 726 } else if (lower == "default") { 727 return defaultKind; 728 } else { 729 return -1; 730 } 731 } 732 733 std::optional<DynamicType> ComparisonType( 734 const DynamicType &t1, const DynamicType &t2) { 735 switch (t1.category()) { 736 case TypeCategory::Integer: 737 switch (t2.category()) { 738 case TypeCategory::Integer: 739 return DynamicType{TypeCategory::Integer, std::max(t1.kind(), t2.kind())}; 740 case TypeCategory::Real: 741 case TypeCategory::Complex: 742 return t2; 743 default: 744 return std::nullopt; 745 } 746 case TypeCategory::Real: 747 switch (t2.category()) { 748 case TypeCategory::Integer: 749 return t1; 750 case TypeCategory::Real: 751 case TypeCategory::Complex: 752 return DynamicType{t2.category(), std::max(t1.kind(), t2.kind())}; 753 default: 754 return std::nullopt; 755 } 756 case TypeCategory::Complex: 757 switch (t2.category()) { 758 case TypeCategory::Integer: 759 return t1; 760 case TypeCategory::Real: 761 case TypeCategory::Complex: 762 return DynamicType{TypeCategory::Complex, std::max(t1.kind(), t2.kind())}; 763 default: 764 return std::nullopt; 765 } 766 case TypeCategory::Character: 767 switch (t2.category()) { 768 case TypeCategory::Character: 769 return DynamicType{ 770 TypeCategory::Character, std::max(t1.kind(), t2.kind())}; 771 default: 772 return std::nullopt; 773 } 774 case TypeCategory::Logical: 775 switch (t2.category()) { 776 case TypeCategory::Logical: 777 return DynamicType{TypeCategory::Logical, LogicalResult::kind}; 778 default: 779 return std::nullopt; 780 } 781 default: 782 return std::nullopt; 783 } 784 } 785 786 bool IsInteroperableIntrinsicType(const DynamicType &type, 787 const common::LanguageFeatureControl *features, bool checkCharLength) { 788 switch (type.category()) { 789 case TypeCategory::Integer: 790 return true; 791 case TypeCategory::Real: 792 case TypeCategory::Complex: 793 return (features && features->IsEnabled(common::LanguageFeature::CUDA)) || 794 type.kind() >= 4; // no short or half floats 795 case TypeCategory::Logical: 796 return type.kind() == 1; // C_BOOL 797 case TypeCategory::Character: 798 if (checkCharLength && type.knownLength().value_or(0) != 1) { 799 return false; 800 } 801 return type.kind() == 1 /* C_CHAR */; 802 default: 803 // Derived types are tested in Semantics/check-declarations.cpp 804 return false; 805 } 806 } 807 808 bool IsCUDAIntrinsicType(const DynamicType &type) { 809 switch (type.category()) { 810 case TypeCategory::Integer: 811 case TypeCategory::Logical: 812 return type.kind() <= 8; 813 case TypeCategory::Real: 814 return type.kind() >= 2 && type.kind() <= 8; 815 case TypeCategory::Complex: 816 return type.kind() == 2 || type.kind() == 4 || type.kind() == 8; 817 case TypeCategory::Character: 818 return type.kind() == 1; 819 default: 820 // Derived types are tested in Semantics/check-declarations.cpp 821 return false; 822 } 823 } 824 825 } // namespace Fortran::evaluate 826