1 //===-- lib/Semantics/symbol.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/Semantics/symbol.h" 10 #include "flang/Common/idioms.h" 11 #include "flang/Evaluate/expression.h" 12 #include "flang/Semantics/scope.h" 13 #include "flang/Semantics/semantics.h" 14 #include "flang/Semantics/tools.h" 15 #include "llvm/Support/raw_ostream.h" 16 #include <string> 17 #include <type_traits> 18 19 namespace Fortran::semantics { 20 21 template <typename T> 22 static void DumpOptional(llvm::raw_ostream &os, const char *label, const T &x) { 23 if (x) { 24 os << ' ' << label << ':' << *x; 25 } 26 } 27 template <typename T> 28 static void DumpExpr(llvm::raw_ostream &os, const char *label, 29 const std::optional<evaluate::Expr<T>> &x) { 30 if (x) { 31 x->AsFortran(os << ' ' << label << ':'); 32 } 33 } 34 35 static void DumpBool(llvm::raw_ostream &os, const char *label, bool x) { 36 if (x) { 37 os << ' ' << label; 38 } 39 } 40 41 static void DumpSymbolVector(llvm::raw_ostream &os, const SymbolVector &list) { 42 char sep{' '}; 43 for (const Symbol &elem : list) { 44 os << sep << elem.name(); 45 sep = ','; 46 } 47 } 48 49 static void DumpType(llvm::raw_ostream &os, const Symbol &symbol) { 50 if (const auto *type{symbol.GetType()}) { 51 os << *type << ' '; 52 } 53 } 54 static void DumpType(llvm::raw_ostream &os, const DeclTypeSpec *type) { 55 if (type) { 56 os << ' ' << *type; 57 } 58 } 59 60 template <typename T> 61 static void DumpList(llvm::raw_ostream &os, const char *label, const T &list) { 62 if (!list.empty()) { 63 os << ' ' << label << ':'; 64 char sep{' '}; 65 for (const auto &elem : list) { 66 os << sep << elem; 67 sep = ','; 68 } 69 } 70 } 71 72 const Scope *ModuleDetails::parent() const { 73 return isSubmodule_ && scope_ ? &scope_->parent() : nullptr; 74 } 75 const Scope *ModuleDetails::ancestor() const { 76 return isSubmodule_ && scope_ ? FindModuleContaining(*scope_) : nullptr; 77 } 78 void ModuleDetails::set_scope(const Scope *scope) { 79 CHECK(!scope_); 80 bool scopeIsSubmodule{scope->parent().kind() == Scope::Kind::Module}; 81 CHECK(isSubmodule_ == scopeIsSubmodule); 82 scope_ = scope; 83 } 84 85 llvm::raw_ostream &operator<<( 86 llvm::raw_ostream &os, const SubprogramDetails &x) { 87 DumpBool(os, "isInterface", x.isInterface_); 88 DumpOptional(os, "bindName", x.bindName()); 89 if (x.result_) { 90 DumpType(os << " result:", x.result()); 91 os << x.result_->name(); 92 if (!x.result_->attrs().empty()) { 93 os << ", " << x.result_->attrs(); 94 } 95 } 96 if (x.entryScope_) { 97 os << " entry"; 98 if (x.entryScope_->symbol()) { 99 os << " in " << x.entryScope_->symbol()->name(); 100 } 101 } 102 char sep{'('}; 103 os << ' '; 104 for (const Symbol *arg : x.dummyArgs_) { 105 os << sep; 106 sep = ','; 107 if (arg) { 108 DumpType(os, *arg); 109 os << arg->name(); 110 } else { 111 os << '*'; 112 } 113 } 114 os << (sep == '(' ? "()" : ")"); 115 if (x.stmtFunction_) { 116 os << " -> " << x.stmtFunction_->AsFortran(); 117 } 118 return os; 119 } 120 121 void EntityDetails::set_type(const DeclTypeSpec &type) { 122 CHECK(!type_); 123 type_ = &type; 124 } 125 126 void AssocEntityDetails::set_rank(int rank) { rank_ = rank; } 127 void EntityDetails::ReplaceType(const DeclTypeSpec &type) { type_ = &type; } 128 129 void ObjectEntityDetails::set_shape(const ArraySpec &shape) { 130 CHECK(shape_.empty()); 131 for (const auto &shapeSpec : shape) { 132 shape_.push_back(shapeSpec); 133 } 134 } 135 void ObjectEntityDetails::set_coshape(const ArraySpec &coshape) { 136 CHECK(coshape_.empty()); 137 for (const auto &shapeSpec : coshape) { 138 coshape_.push_back(shapeSpec); 139 } 140 } 141 142 ProcEntityDetails::ProcEntityDetails(EntityDetails &&d) : EntityDetails(d) { 143 if (type()) { 144 interface_.set_type(*type()); 145 } 146 } 147 148 UseErrorDetails::UseErrorDetails(const UseDetails &useDetails) { 149 add_occurrence(useDetails.location(), *GetUsedModule(useDetails).scope()); 150 } 151 UseErrorDetails &UseErrorDetails::add_occurrence( 152 const SourceName &location, const Scope &module) { 153 occurrences_.push_back(std::make_pair(location, &module)); 154 return *this; 155 } 156 157 void GenericDetails::AddSpecificProc( 158 const Symbol &proc, SourceName bindingName) { 159 specificProcs_.push_back(proc); 160 bindingNames_.push_back(bindingName); 161 } 162 void GenericDetails::set_specific(Symbol &specific) { 163 CHECK(!specific_); 164 CHECK(!derivedType_); 165 specific_ = &specific; 166 } 167 void GenericDetails::set_derivedType(Symbol &derivedType) { 168 CHECK(!specific_); 169 CHECK(!derivedType_); 170 derivedType_ = &derivedType; 171 } 172 void GenericDetails::AddUse(const Symbol &use) { 173 CHECK(use.has<UseDetails>()); 174 uses_.push_back(use); 175 } 176 177 const Symbol *GenericDetails::CheckSpecific() const { 178 return const_cast<GenericDetails *>(this)->CheckSpecific(); 179 } 180 Symbol *GenericDetails::CheckSpecific() { 181 if (specific_) { 182 for (const Symbol &proc : specificProcs_) { 183 if (&proc == specific_) { 184 return nullptr; 185 } 186 } 187 return specific_; 188 } else { 189 return nullptr; 190 } 191 } 192 193 void GenericDetails::CopyFrom(const GenericDetails &from) { 194 CHECK(specificProcs_.size() == bindingNames_.size()); 195 CHECK(from.specificProcs_.size() == from.bindingNames_.size()); 196 kind_ = from.kind_; 197 if (from.derivedType_) { 198 CHECK(!derivedType_ || derivedType_ == from.derivedType_); 199 derivedType_ = from.derivedType_; 200 } 201 for (std::size_t i{0}; i < from.specificProcs_.size(); ++i) { 202 if (std::find_if(specificProcs_.begin(), specificProcs_.end(), 203 [&](const Symbol &mySymbol) { 204 return &mySymbol == &*from.specificProcs_[i]; 205 }) == specificProcs_.end()) { 206 specificProcs_.push_back(from.specificProcs_[i]); 207 bindingNames_.push_back(from.bindingNames_[i]); 208 } 209 } 210 } 211 212 // The name of the kind of details for this symbol. 213 // This is primarily for debugging. 214 std::string DetailsToString(const Details &details) { 215 return std::visit( 216 common::visitors{ 217 [](const UnknownDetails &) { return "Unknown"; }, 218 [](const MainProgramDetails &) { return "MainProgram"; }, 219 [](const ModuleDetails &) { return "Module"; }, 220 [](const SubprogramDetails &) { return "Subprogram"; }, 221 [](const SubprogramNameDetails &) { return "SubprogramName"; }, 222 [](const EntityDetails &) { return "Entity"; }, 223 [](const ObjectEntityDetails &) { return "ObjectEntity"; }, 224 [](const ProcEntityDetails &) { return "ProcEntity"; }, 225 [](const DerivedTypeDetails &) { return "DerivedType"; }, 226 [](const UseDetails &) { return "Use"; }, 227 [](const UseErrorDetails &) { return "UseError"; }, 228 [](const HostAssocDetails &) { return "HostAssoc"; }, 229 [](const GenericDetails &) { return "Generic"; }, 230 [](const ProcBindingDetails &) { return "ProcBinding"; }, 231 [](const NamelistDetails &) { return "Namelist"; }, 232 [](const CommonBlockDetails &) { return "CommonBlockDetails"; }, 233 [](const TypeParamDetails &) { return "TypeParam"; }, 234 [](const MiscDetails &) { return "Misc"; }, 235 [](const AssocEntityDetails &) { return "AssocEntity"; }, 236 }, 237 details); 238 } 239 240 const std::string Symbol::GetDetailsName() const { 241 return DetailsToString(details_); 242 } 243 244 void Symbol::set_details(Details &&details) { 245 CHECK(CanReplaceDetails(details)); 246 details_ = std::move(details); 247 } 248 249 bool Symbol::CanReplaceDetails(const Details &details) const { 250 if (has<UnknownDetails>()) { 251 return true; // can always replace UnknownDetails 252 } else { 253 return std::visit( 254 common::visitors{ 255 [](const UseErrorDetails &) { return true; }, 256 [&](const ObjectEntityDetails &) { return has<EntityDetails>(); }, 257 [&](const ProcEntityDetails &) { return has<EntityDetails>(); }, 258 [&](const SubprogramDetails &) { 259 return has<SubprogramNameDetails>() || has<EntityDetails>(); 260 }, 261 [&](const DerivedTypeDetails &) { 262 const auto *derived{this->detailsIf<DerivedTypeDetails>()}; 263 return derived && derived->isForwardReferenced(); 264 }, 265 [&](const UseDetails &x) { 266 const auto *use{this->detailsIf<UseDetails>()}; 267 return use && use->symbol() == x.symbol(); 268 }, 269 [](const auto &) { return false; }, 270 }, 271 details); 272 } 273 } 274 275 // Usually a symbol's name is the first occurrence in the source, but sometimes 276 // we want to replace it with one at a different location (but same characters). 277 void Symbol::ReplaceName(const SourceName &name) { 278 CHECK(name == name_); 279 name_ = name; 280 } 281 282 void Symbol::SetType(const DeclTypeSpec &type) { 283 std::visit(common::visitors{ 284 [&](EntityDetails &x) { x.set_type(type); }, 285 [&](ObjectEntityDetails &x) { x.set_type(type); }, 286 [&](AssocEntityDetails &x) { x.set_type(type); }, 287 [&](ProcEntityDetails &x) { x.interface().set_type(type); }, 288 [&](TypeParamDetails &x) { x.set_type(type); }, 289 [](auto &) {}, 290 }, 291 details_); 292 } 293 294 template <typename T> 295 constexpr bool HasBindName{std::is_convertible_v<T, const WithBindName *>}; 296 297 const std::string *Symbol::GetBindName() const { 298 return std::visit( 299 [&](auto &x) -> const std::string * { 300 if constexpr (HasBindName<decltype(&x)>) { 301 return x.bindName(); 302 } else { 303 return nullptr; 304 } 305 }, 306 details_); 307 } 308 309 void Symbol::SetBindName(std::string &&name) { 310 std::visit( 311 [&](auto &x) { 312 if constexpr (HasBindName<decltype(&x)>) { 313 x.set_bindName(std::move(name)); 314 } else { 315 DIE("bind name not allowed on this kind of symbol"); 316 } 317 }, 318 details_); 319 } 320 321 bool Symbol::IsFuncResult() const { 322 return std::visit( 323 common::visitors{[](const EntityDetails &x) { return x.isFuncResult(); }, 324 [](const ObjectEntityDetails &x) { return x.isFuncResult(); }, 325 [](const ProcEntityDetails &x) { return x.isFuncResult(); }, 326 [](const HostAssocDetails &x) { return x.symbol().IsFuncResult(); }, 327 [](const auto &) { return false; }}, 328 details_); 329 } 330 331 bool Symbol::IsObjectArray() const { 332 const auto *details{std::get_if<ObjectEntityDetails>(&details_)}; 333 return details && details->IsArray(); 334 } 335 336 bool Symbol::IsSubprogram() const { 337 return std::visit( 338 common::visitors{ 339 [](const SubprogramDetails &) { return true; }, 340 [](const SubprogramNameDetails &) { return true; }, 341 [](const GenericDetails &) { return true; }, 342 [](const UseDetails &x) { return x.symbol().IsSubprogram(); }, 343 [](const auto &) { return false; }, 344 }, 345 details_); 346 } 347 348 bool Symbol::IsFromModFile() const { 349 return test(Flag::ModFile) || 350 (!owner_->IsGlobal() && owner_->symbol()->IsFromModFile()); 351 } 352 353 ObjectEntityDetails::ObjectEntityDetails(EntityDetails &&d) 354 : EntityDetails(d) {} 355 356 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const EntityDetails &x) { 357 DumpBool(os, "dummy", x.isDummy()); 358 DumpBool(os, "funcResult", x.isFuncResult()); 359 if (x.type()) { 360 os << " type: " << *x.type(); 361 } 362 DumpOptional(os, "bindName", x.bindName()); 363 return os; 364 } 365 366 llvm::raw_ostream &operator<<( 367 llvm::raw_ostream &os, const ObjectEntityDetails &x) { 368 os << *static_cast<const EntityDetails *>(&x); 369 DumpList(os, "shape", x.shape()); 370 DumpList(os, "coshape", x.coshape()); 371 DumpExpr(os, "init", x.init_); 372 return os; 373 } 374 375 llvm::raw_ostream &operator<<( 376 llvm::raw_ostream &os, const AssocEntityDetails &x) { 377 os << *static_cast<const EntityDetails *>(&x); 378 if (auto assocRank{x.rank()}) { 379 os << " rank: " << *assocRank; 380 } 381 DumpExpr(os, "expr", x.expr()); 382 return os; 383 } 384 385 llvm::raw_ostream &operator<<( 386 llvm::raw_ostream &os, const ProcEntityDetails &x) { 387 if (auto *symbol{x.interface_.symbol()}) { 388 os << ' ' << symbol->name(); 389 } else { 390 DumpType(os, x.interface_.type()); 391 } 392 DumpOptional(os, "bindName", x.bindName()); 393 DumpOptional(os, "passName", x.passName()); 394 if (x.init()) { 395 if (const Symbol * target{*x.init()}) { 396 os << " => " << target->name(); 397 } else { 398 os << " => NULL()"; 399 } 400 } 401 return os; 402 } 403 404 llvm::raw_ostream &operator<<( 405 llvm::raw_ostream &os, const DerivedTypeDetails &x) { 406 DumpBool(os, "sequence", x.sequence_); 407 DumpList(os, "components", x.componentNames_); 408 return os; 409 } 410 411 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const GenericDetails &x) { 412 os << ' ' << x.kind().ToString(); 413 DumpBool(os, "(specific)", x.specific() != nullptr); 414 DumpBool(os, "(derivedType)", x.derivedType() != nullptr); 415 if (const auto &uses{x.uses()}; !uses.empty()) { 416 os << " (uses:"; 417 char sep{' '}; 418 for (const Symbol &use : uses) { 419 const Symbol &ultimate{use.GetUltimate()}; 420 os << sep << ultimate.name() << "->" 421 << ultimate.owner().GetName().value(); 422 sep = ','; 423 } 424 os << ')'; 425 } 426 os << " procs:"; 427 DumpSymbolVector(os, x.specificProcs()); 428 return os; 429 } 430 431 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) { 432 os << DetailsToString(details); 433 std::visit( // 434 common::visitors{ 435 [&](const UnknownDetails &) {}, 436 [&](const MainProgramDetails &) {}, 437 [&](const ModuleDetails &x) { 438 if (x.isSubmodule()) { 439 os << " ("; 440 if (x.ancestor()) { 441 auto ancestor{x.ancestor()->GetName().value()}; 442 os << ancestor; 443 if (x.parent()) { 444 auto parent{x.parent()->GetName().value()}; 445 if (ancestor != parent) { 446 os << ':' << parent; 447 } 448 } 449 } 450 os << ")"; 451 } 452 }, 453 [&](const SubprogramNameDetails &x) { 454 os << ' ' << EnumToString(x.kind()); 455 }, 456 [&](const UseDetails &x) { 457 os << " from " << x.symbol().name() << " in " 458 << GetUsedModule(x).name(); 459 }, 460 [&](const UseErrorDetails &x) { 461 os << " uses:"; 462 char sep{':'}; 463 for (const auto &[location, module] : x.occurrences()) { 464 os << sep << " from " << module->GetName().value() << " at " 465 << location; 466 sep = ','; 467 } 468 }, 469 [](const HostAssocDetails &) {}, 470 [&](const ProcBindingDetails &x) { 471 os << " => " << x.symbol().name(); 472 DumpOptional(os, "passName", x.passName()); 473 }, 474 [&](const NamelistDetails &x) { 475 os << ':'; 476 DumpSymbolVector(os, x.objects()); 477 }, 478 [&](const CommonBlockDetails &x) { 479 DumpOptional(os, "bindName", x.bindName()); 480 if (x.alignment()) { 481 os << " alignment=" << x.alignment(); 482 } 483 os << ':'; 484 for (const auto &object : x.objects()) { 485 os << ' ' << object->name(); 486 } 487 }, 488 [&](const TypeParamDetails &x) { 489 DumpOptional(os, "type", x.type()); 490 os << ' ' << common::EnumToString(x.attr()); 491 DumpExpr(os, "init", x.init()); 492 }, 493 [&](const MiscDetails &x) { 494 os << ' ' << MiscDetails::EnumToString(x.kind()); 495 }, 496 [&](const auto &x) { os << x; }, 497 }, 498 details); 499 return os; 500 } 501 502 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, Symbol::Flag flag) { 503 return o << Symbol::EnumToString(flag); 504 } 505 506 llvm::raw_ostream &operator<<( 507 llvm::raw_ostream &o, const Symbol::Flags &flags) { 508 std::size_t n{flags.count()}; 509 std::size_t seen{0}; 510 for (std::size_t j{0}; seen < n; ++j) { 511 Symbol::Flag flag{static_cast<Symbol::Flag>(j)}; 512 if (flags.test(flag)) { 513 if (seen++ > 0) { 514 o << ", "; 515 } 516 o << flag; 517 } 518 } 519 return o; 520 } 521 522 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Symbol &symbol) { 523 os << symbol.name(); 524 if (!symbol.attrs().empty()) { 525 os << ", " << symbol.attrs(); 526 } 527 if (!symbol.flags().empty()) { 528 os << " (" << symbol.flags() << ')'; 529 } 530 if (symbol.size_) { 531 os << " size=" << symbol.size_ << " offset=" << symbol.offset_; 532 } 533 os << ": " << symbol.details_; 534 return os; 535 } 536 537 // Output a unique name for a scope by qualifying it with the names of 538 // parent scopes. For scopes without corresponding symbols, use the kind 539 // with an index (e.g. Block1, Block2, etc.). 540 static void DumpUniqueName(llvm::raw_ostream &os, const Scope &scope) { 541 if (!scope.IsGlobal()) { 542 DumpUniqueName(os, scope.parent()); 543 os << '/'; 544 if (auto *scopeSymbol{scope.symbol()}; 545 scopeSymbol && !scopeSymbol->name().empty()) { 546 os << scopeSymbol->name(); 547 } else { 548 int index{1}; 549 for (auto &child : scope.parent().children()) { 550 if (child == scope) { 551 break; 552 } 553 if (child.kind() == scope.kind()) { 554 ++index; 555 } 556 } 557 os << Scope::EnumToString(scope.kind()) << index; 558 } 559 } 560 } 561 562 // Dump a symbol for UnparseWithSymbols. This will be used for tests so the 563 // format should be reasonably stable. 564 llvm::raw_ostream &DumpForUnparse( 565 llvm::raw_ostream &os, const Symbol &symbol, bool isDef) { 566 DumpUniqueName(os, symbol.owner()); 567 os << '/' << symbol.name(); 568 if (isDef) { 569 if (!symbol.attrs().empty()) { 570 os << ' ' << symbol.attrs(); 571 } 572 if (!symbol.flags().empty()) { 573 os << " (" << symbol.flags() << ')'; 574 } 575 os << ' ' << symbol.GetDetailsName(); 576 DumpType(os, symbol.GetType()); 577 } 578 return os; 579 } 580 581 const DerivedTypeSpec *Symbol::GetParentTypeSpec(const Scope *scope) const { 582 if (const Symbol * parentComponent{GetParentComponent(scope)}) { 583 const auto &object{parentComponent->get<ObjectEntityDetails>()}; 584 return &object.type()->derivedTypeSpec(); 585 } else { 586 return nullptr; 587 } 588 } 589 590 const Symbol *Symbol::GetParentComponent(const Scope *scope) const { 591 if (const auto *dtDetails{detailsIf<DerivedTypeDetails>()}) { 592 if (const Scope * localScope{scope ? scope : scope_}) { 593 return dtDetails->GetParentComponent(DEREF(localScope)); 594 } 595 } 596 return nullptr; 597 } 598 599 void DerivedTypeDetails::add_component(const Symbol &symbol) { 600 if (symbol.test(Symbol::Flag::ParentComp)) { 601 CHECK(componentNames_.empty()); 602 } 603 componentNames_.push_back(symbol.name()); 604 } 605 606 const Symbol *DerivedTypeDetails::GetParentComponent(const Scope &scope) const { 607 if (auto extends{GetParentComponentName()}) { 608 if (auto iter{scope.find(*extends)}; iter != scope.cend()) { 609 if (const Symbol & symbol{*iter->second}; 610 symbol.test(Symbol::Flag::ParentComp)) { 611 return &symbol; 612 } 613 } 614 } 615 return nullptr; 616 } 617 618 const Symbol *DerivedTypeDetails::GetFinalForRank(int rank) const { 619 for (const auto &pair : finals_) { 620 const Symbol &symbol{*pair.second}; 621 if (const auto *details{symbol.detailsIf<SubprogramDetails>()}) { 622 if (details->dummyArgs().size() == 1) { 623 if (const Symbol * arg{details->dummyArgs().at(0)}) { 624 if (const auto *object{arg->detailsIf<ObjectEntityDetails>()}) { 625 if (rank == object->shape().Rank() || object->IsAssumedRank() || 626 symbol.attrs().test(Attr::ELEMENTAL)) { 627 return &symbol; 628 } 629 } 630 } 631 } 632 } 633 } 634 return nullptr; 635 } 636 637 void TypeParamDetails::set_type(const DeclTypeSpec &type) { 638 CHECK(!type_); 639 type_ = &type; 640 } 641 642 bool GenericKind::IsIntrinsicOperator() const { 643 return Is(OtherKind::Concat) || Has<common::LogicalOperator>() || 644 Has<common::NumericOperator>() || Has<common::RelationalOperator>(); 645 } 646 647 bool GenericKind::IsOperator() const { 648 return IsDefinedOperator() || IsIntrinsicOperator(); 649 } 650 651 std::string GenericKind::ToString() const { 652 return std::visit( 653 common::visitors { 654 [](const OtherKind &x) { return EnumToString(x); }, 655 [](const DefinedIo &x) { return EnumToString(x); }, 656 #if !__clang__ && __GNUC__ == 7 && __GNUC_MINOR__ == 2 657 [](const common::NumericOperator &x) { 658 return common::EnumToString(x); 659 }, 660 [](const common::LogicalOperator &x) { 661 return common::EnumToString(x); 662 }, 663 [](const common::RelationalOperator &x) { 664 return common::EnumToString(x); 665 }, 666 #else 667 [](const auto &x) { return common::EnumToString(x); }, 668 #endif 669 }, 670 u); 671 } 672 673 bool GenericKind::Is(GenericKind::OtherKind x) const { 674 const OtherKind *y{std::get_if<OtherKind>(&u)}; 675 return y && *y == x; 676 } 677 678 } // namespace Fortran::semantics 679