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