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