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/Common/template.h" 12 #include "flang/Evaluate/expression.h" 13 #include "flang/Evaluate/fold.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 // TODO: Automatic (adjustable) arrays - are they descriptors? 41 for (const ShapeSpec &shapeSpec : details.shape()) { 42 const auto &lb{shapeSpec.lbound().GetExplicit()}; 43 const auto &ub{shapeSpec.ubound().GetExplicit()}; 44 if (!lb || !ub || !IsConstantExpr(*lb) || !IsConstantExpr(*ub)) { 45 return true; 46 } 47 } 48 return false; 49 } 50 51 static bool IsDescriptor(const ProcEntityDetails &details) { 52 // A procedure pointer or dummy procedure must be & is a descriptor if 53 // and only if it requires a static link. 54 // TODO: refine this placeholder 55 return details.HasExplicitInterface(); 56 } 57 58 bool IsDescriptor(const Symbol &symbol) { 59 return std::visit( 60 common::visitors{ 61 [&](const ObjectEntityDetails &d) { 62 return IsAllocatableOrPointer(symbol) || IsDescriptor(d); 63 }, 64 [&](const ProcEntityDetails &d) { 65 return (symbol.attrs().test(Attr::POINTER) || 66 symbol.attrs().test(Attr::EXTERNAL)) && 67 IsDescriptor(d); 68 }, 69 [&](const EntityDetails &d) { return IsDescriptor(d.type()); }, 70 [](const AssocEntityDetails &d) { 71 if (const auto &expr{d.expr()}) { 72 if (expr->Rank() > 0) { 73 return true; 74 } 75 if (const auto dynamicType{expr->GetType()}) { 76 if (dynamicType->RequiresDescriptor()) { 77 return true; 78 } 79 } 80 } 81 return false; 82 }, 83 [](const SubprogramDetails &d) { 84 return d.isFunction() && IsDescriptor(d.result()); 85 }, 86 [](const UseDetails &d) { return IsDescriptor(d.symbol()); }, 87 [](const HostAssocDetails &d) { return IsDescriptor(d.symbol()); }, 88 [](const auto &) { return false; }, 89 }, 90 symbol.details()); 91 } 92 } // namespace Fortran::semantics 93 94 namespace Fortran::evaluate { 95 96 template <typename A> inline bool PointeeComparison(const A *x, const A *y) { 97 return x == y || (x && y && *x == *y); 98 } 99 100 bool DynamicType::operator==(const DynamicType &that) const { 101 return category_ == that.category_ && kind_ == that.kind_ && 102 PointeeComparison(charLength_, that.charLength_) && 103 PointeeComparison(derived_, that.derived_); 104 } 105 106 std::optional<Expr<SubscriptInteger>> DynamicType::GetCharLength() const { 107 if (category_ == TypeCategory::Character && charLength_) { 108 if (auto length{charLength_->GetExplicit()}) { 109 return ConvertToType<SubscriptInteger>(std::move(*length)); 110 } 111 } 112 return std::nullopt; 113 } 114 115 static constexpr int RealKindBytes(int kind) { 116 switch (kind) { 117 case 3: // non-IEEE 16-bit format (truncated 32-bit) 118 return 2; 119 case 10: // 80387 80-bit extended precision 120 case 12: // possible variant spelling 121 return 16; 122 default: 123 return kind; 124 } 125 } 126 127 std::optional<Expr<SubscriptInteger>> DynamicType::MeasureSizeInBytes( 128 FoldingContext *context) const { 129 switch (category_) { 130 case TypeCategory::Integer: 131 return Expr<SubscriptInteger>{kind_}; 132 case TypeCategory::Real: 133 return Expr<SubscriptInteger>{RealKindBytes(kind_)}; 134 case TypeCategory::Complex: 135 return Expr<SubscriptInteger>{2 * RealKindBytes(kind_)}; 136 case TypeCategory::Character: 137 if (auto len{GetCharLength()}) { 138 auto result{Expr<SubscriptInteger>{kind_} * std::move(*len)}; 139 if (context) { 140 return Fold(*context, std::move(result)); 141 } else { 142 return std::move(result); 143 } 144 } 145 break; 146 case TypeCategory::Logical: 147 return Expr<SubscriptInteger>{kind_}; 148 case TypeCategory::Derived: 149 if (derived_ && derived_->scope()) { 150 return Expr<SubscriptInteger>{ 151 static_cast<common::ConstantSubscript>(derived_->scope()->size())}; 152 } 153 break; 154 } 155 return std::nullopt; 156 } 157 158 bool DynamicType::IsAssumedLengthCharacter() const { 159 return category_ == TypeCategory::Character && charLength_ && 160 charLength_->isAssumed(); 161 } 162 163 bool DynamicType::IsNonConstantLengthCharacter() const { 164 if (category_ != TypeCategory::Character) { 165 return false; 166 } else if (!charLength_) { 167 return true; 168 } else if (const auto &expr{charLength_->GetExplicit()}) { 169 return !IsConstantExpr(*expr); 170 } else { 171 return true; 172 } 173 } 174 175 bool DynamicType::IsTypelessIntrinsicArgument() const { 176 return category_ == TypeCategory::Integer && kind_ == TypelessKind; 177 } 178 179 const semantics::DerivedTypeSpec *GetDerivedTypeSpec( 180 const std::optional<DynamicType> &type) { 181 return type ? GetDerivedTypeSpec(*type) : nullptr; 182 } 183 184 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(const DynamicType &type) { 185 if (type.category() == TypeCategory::Derived && 186 !type.IsUnlimitedPolymorphic()) { 187 return &type.GetDerivedTypeSpec(); 188 } else { 189 return nullptr; 190 } 191 } 192 193 static const semantics::Symbol *FindParentComponent( 194 const semantics::DerivedTypeSpec &derived) { 195 const semantics::Symbol &typeSymbol{derived.typeSymbol()}; 196 if (const semantics::Scope * scope{typeSymbol.scope()}) { 197 const auto &dtDetails{typeSymbol.get<semantics::DerivedTypeDetails>()}; 198 if (auto extends{dtDetails.GetParentComponentName()}) { 199 if (auto iter{scope->find(*extends)}; iter != scope->cend()) { 200 if (const Symbol & symbol{*iter->second}; 201 symbol.test(Symbol::Flag::ParentComp)) { 202 return &symbol; 203 } 204 } 205 } 206 } 207 return nullptr; 208 } 209 210 const semantics::DerivedTypeSpec *GetParentTypeSpec( 211 const semantics::DerivedTypeSpec &derived) { 212 if (const semantics::Symbol * parent{FindParentComponent(derived)}) { 213 return &parent->get<semantics::ObjectEntityDetails>() 214 .type() 215 ->derivedTypeSpec(); 216 } else { 217 return nullptr; 218 } 219 } 220 221 // Compares two derived type representations to see whether they both 222 // represent the "same type" in the sense of section 7.5.2.4. 223 using SetOfDerivedTypePairs = 224 std::set<std::pair<const semantics::DerivedTypeSpec *, 225 const semantics::DerivedTypeSpec *>>; 226 227 static bool AreSameComponent(const semantics::Symbol &, 228 const semantics::Symbol &, SetOfDerivedTypePairs &inProgress); 229 230 static bool AreSameDerivedType(const semantics::DerivedTypeSpec &x, 231 const semantics::DerivedTypeSpec &y, SetOfDerivedTypePairs &inProgress) { 232 const auto &xSymbol{x.typeSymbol()}; 233 const auto &ySymbol{y.typeSymbol()}; 234 if (&x == &y || xSymbol == ySymbol) { 235 return true; 236 } 237 auto thisQuery{std::make_pair(&x, &y)}; 238 if (inProgress.find(thisQuery) != inProgress.end()) { 239 return true; // recursive use of types in components 240 } 241 inProgress.insert(thisQuery); 242 const auto &xDetails{xSymbol.get<semantics::DerivedTypeDetails>()}; 243 const auto &yDetails{ySymbol.get<semantics::DerivedTypeDetails>()}; 244 if (xSymbol.name() != ySymbol.name()) { 245 return false; 246 } 247 if (!(xDetails.sequence() && yDetails.sequence()) && 248 !(xSymbol.attrs().test(semantics::Attr::BIND_C) && 249 ySymbol.attrs().test(semantics::Attr::BIND_C))) { 250 // PGI does not enforce this requirement; all other Fortran 251 // processors do with a hard error when violations are caught. 252 return false; 253 } 254 // Compare the component lists in their orders of declaration. 255 auto xEnd{xDetails.componentNames().cend()}; 256 auto yComponentName{yDetails.componentNames().cbegin()}; 257 auto yEnd{yDetails.componentNames().cend()}; 258 for (auto xComponentName{xDetails.componentNames().cbegin()}; 259 xComponentName != xEnd; ++xComponentName, ++yComponentName) { 260 if (yComponentName == yEnd || *xComponentName != *yComponentName || 261 !xSymbol.scope() || !ySymbol.scope()) { 262 return false; 263 } 264 const auto xLookup{xSymbol.scope()->find(*xComponentName)}; 265 const auto yLookup{ySymbol.scope()->find(*yComponentName)}; 266 if (xLookup == xSymbol.scope()->end() || 267 yLookup == ySymbol.scope()->end() || 268 !AreSameComponent(*xLookup->second, *yLookup->second, inProgress)) { 269 return false; 270 } 271 } 272 return yComponentName == yEnd; 273 } 274 275 static bool AreSameComponent(const semantics::Symbol &x, 276 const semantics::Symbol &y, 277 SetOfDerivedTypePairs & /* inProgress - not yet used */) { 278 if (x.attrs() != y.attrs()) { 279 return false; 280 } 281 if (x.attrs().test(semantics::Attr::PRIVATE)) { 282 return false; 283 } 284 // TODO: compare types, parameters, bounds, &c. 285 return x.has<semantics::ObjectEntityDetails>() == 286 y.has<semantics::ObjectEntityDetails>(); 287 } 288 289 static bool AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec *x, 290 const semantics::DerivedTypeSpec *y, bool isPolymorphic) { 291 if (!x || !y) { 292 return false; 293 } else { 294 SetOfDerivedTypePairs inProgress; 295 if (AreSameDerivedType(*x, *y, inProgress)) { 296 return true; 297 } else { 298 return isPolymorphic && 299 AreCompatibleDerivedTypes(x, GetParentTypeSpec(*y), true); 300 } 301 } 302 } 303 304 bool IsKindTypeParameter(const semantics::Symbol &symbol) { 305 const auto *param{symbol.detailsIf<semantics::TypeParamDetails>()}; 306 return param && param->attr() == common::TypeParamAttr::Kind; 307 } 308 309 // Do the kind type parameters of type1 have the same values as the 310 // corresponding kind type parameters of type2? 311 static bool AreKindCompatible(const semantics::DerivedTypeSpec &type1, 312 const semantics::DerivedTypeSpec &type2) { 313 for (const auto &[name, param1] : type1.parameters()) { 314 if (param1.isKind()) { 315 const semantics::ParamValue *param2{type2.FindParameter(name)}; 316 if (!PointeeComparison(¶m1, param2)) { 317 return false; 318 } 319 } 320 } 321 return true; 322 } 323 324 // See 7.3.2.3 (5) & 15.5.2.4 325 bool DynamicType::IsTkCompatibleWith(const DynamicType &that) const { 326 if (IsUnlimitedPolymorphic()) { 327 return true; 328 } else if (that.IsUnlimitedPolymorphic()) { 329 return false; 330 } else if (category_ != that.category_) { 331 return false; 332 } else if (derived_) { 333 return that.derived_ && 334 AreCompatibleDerivedTypes(derived_, that.derived_, IsPolymorphic()) && 335 AreKindCompatible(*derived_, *that.derived_); 336 } else { 337 return kind_ == that.kind_; 338 } 339 } 340 341 std::optional<DynamicType> DynamicType::From( 342 const semantics::DeclTypeSpec &type) { 343 if (const auto *intrinsic{type.AsIntrinsic()}) { 344 if (auto kind{ToInt64(intrinsic->kind())}) { 345 TypeCategory category{intrinsic->category()}; 346 if (IsValidKindOfIntrinsicType(category, *kind)) { 347 if (category == TypeCategory::Character) { 348 const auto &charType{type.characterTypeSpec()}; 349 return DynamicType{static_cast<int>(*kind), charType.length()}; 350 } else { 351 return DynamicType{category, static_cast<int>(*kind)}; 352 } 353 } 354 } 355 } else if (const auto *derived{type.AsDerived()}) { 356 return DynamicType{ 357 *derived, type.category() == semantics::DeclTypeSpec::ClassDerived}; 358 } else if (type.category() == semantics::DeclTypeSpec::ClassStar) { 359 return DynamicType::UnlimitedPolymorphic(); 360 } else if (type.category() == semantics::DeclTypeSpec::TypeStar) { 361 return DynamicType::AssumedType(); 362 } else { 363 common::die("DynamicType::From(DeclTypeSpec): failed"); 364 } 365 return std::nullopt; 366 } 367 368 std::optional<DynamicType> DynamicType::From(const semantics::Symbol &symbol) { 369 return From(symbol.GetType()); // Symbol -> DeclTypeSpec -> DynamicType 370 } 371 372 DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const { 373 switch (category_) { 374 case TypeCategory::Integer: 375 switch (that.category_) { 376 case TypeCategory::Integer: 377 return DynamicType{TypeCategory::Integer, std::max(kind_, that.kind_)}; 378 case TypeCategory::Real: 379 case TypeCategory::Complex: 380 return that; 381 default: 382 CRASH_NO_CASE; 383 } 384 break; 385 case TypeCategory::Real: 386 switch (that.category_) { 387 case TypeCategory::Integer: 388 return *this; 389 case TypeCategory::Real: 390 return DynamicType{TypeCategory::Real, std::max(kind_, that.kind_)}; 391 case TypeCategory::Complex: 392 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 393 default: 394 CRASH_NO_CASE; 395 } 396 break; 397 case TypeCategory::Complex: 398 switch (that.category_) { 399 case TypeCategory::Integer: 400 return *this; 401 case TypeCategory::Real: 402 case TypeCategory::Complex: 403 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)}; 404 default: 405 CRASH_NO_CASE; 406 } 407 break; 408 case TypeCategory::Logical: 409 switch (that.category_) { 410 case TypeCategory::Logical: 411 return DynamicType{TypeCategory::Logical, std::max(kind_, that.kind_)}; 412 default: 413 CRASH_NO_CASE; 414 } 415 break; 416 default: 417 CRASH_NO_CASE; 418 } 419 return *this; 420 } 421 422 bool DynamicType::RequiresDescriptor() const { 423 return IsPolymorphic() || IsNonConstantLengthCharacter() || 424 (derived_ && CountNonConstantLenParameters(*derived_) > 0); 425 } 426 427 bool DynamicType::HasDeferredTypeParameter() const { 428 if (derived_) { 429 for (const auto &pair : derived_->parameters()) { 430 if (pair.second.isDeferred()) { 431 return true; 432 } 433 } 434 } 435 return charLength_ && charLength_->isDeferred(); 436 } 437 438 bool SomeKind<TypeCategory::Derived>::operator==( 439 const SomeKind<TypeCategory::Derived> &that) const { 440 return PointeeComparison(derivedTypeSpec_, that.derivedTypeSpec_); 441 } 442 443 int SelectedCharKind(const std::string &s, int defaultKind) { // 16.9.168 444 auto lower{parser::ToLowerCaseLetters(s)}; 445 auto n{lower.size()}; 446 while (n > 0 && lower[0] == ' ') { 447 lower.erase(0, 1); 448 --n; 449 } 450 while (n > 0 && lower[n - 1] == ' ') { 451 lower.erase(--n, 1); 452 } 453 if (lower == "ascii") { 454 return 1; 455 } else if (lower == "ucs-2") { 456 return 2; 457 } else if (lower == "iso_10646" || lower == "ucs-4") { 458 return 4; 459 } else if (lower == "default") { 460 return defaultKind; 461 } else { 462 return -1; 463 } 464 } 465 466 class SelectedIntKindVisitor { 467 public: 468 explicit SelectedIntKindVisitor(std::int64_t p) : precision_{p} {} 469 using Result = std::optional<int>; 470 using Types = IntegerTypes; 471 template <typename T> Result Test() const { 472 if (Scalar<T>::RANGE >= precision_) { 473 return T::kind; 474 } else { 475 return std::nullopt; 476 } 477 } 478 479 private: 480 std::int64_t precision_; 481 }; 482 483 int SelectedIntKind(std::int64_t precision) { 484 if (auto kind{common::SearchTypes(SelectedIntKindVisitor{precision})}) { 485 return *kind; 486 } else { 487 return -1; 488 } 489 } 490 491 class SelectedRealKindVisitor { 492 public: 493 explicit SelectedRealKindVisitor(std::int64_t p, std::int64_t r) 494 : precision_{p}, range_{r} {} 495 using Result = std::optional<int>; 496 using Types = RealTypes; 497 template <typename T> Result Test() const { 498 if (Scalar<T>::PRECISION >= precision_ && Scalar<T>::RANGE >= range_) { 499 return {T::kind}; 500 } else { 501 return std::nullopt; 502 } 503 } 504 505 private: 506 std::int64_t precision_, range_; 507 }; 508 509 int SelectedRealKind( 510 std::int64_t precision, std::int64_t range, std::int64_t radix) { 511 if (radix != 2) { 512 return -5; 513 } 514 if (auto kind{ 515 common::SearchTypes(SelectedRealKindVisitor{precision, range})}) { 516 return *kind; 517 } 518 // No kind has both sufficient precision and sufficient range. 519 // The negative return value encodes whether any kinds exist that 520 // could satisfy either constraint independently. 521 bool pOK{common::SearchTypes(SelectedRealKindVisitor{precision, 0})}; 522 bool rOK{common::SearchTypes(SelectedRealKindVisitor{0, range})}; 523 if (pOK) { 524 if (rOK) { 525 return -4; 526 } else { 527 return -2; 528 } 529 } else { 530 if (rOK) { 531 return -1; 532 } else { 533 return -3; 534 } 535 } 536 } 537 } // namespace Fortran::evaluate 538