2020-02-25 15:11:52 +00:00
|
|
|
//===-- lib/Semantics/symbol.cpp ------------------------------------------===//
|
2018-05-01 12:50:34 -07:00
|
|
|
//
|
2019-12-20 12:52:07 -08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-05-01 12:50:34 -07:00
|
|
|
//
|
2020-01-10 12:12:03 -08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2018-05-01 12:50:34 -07:00
|
|
|
|
2020-02-25 15:11:52 +00:00
|
|
|
#include "flang/Semantics/symbol.h"
|
|
|
|
#include "flang/Common/idioms.h"
|
|
|
|
#include "flang/Evaluate/expression.h"
|
|
|
|
#include "flang/Semantics/scope.h"
|
|
|
|
#include "flang/Semantics/semantics.h"
|
|
|
|
#include "flang/Semantics/tools.h"
|
2020-02-28 15:11:03 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2022-02-11 09:44:47 -08:00
|
|
|
#include <cstring>
|
2018-11-16 12:43:08 -08:00
|
|
|
#include <string>
|
2021-03-24 11:25:22 -07:00
|
|
|
#include <type_traits>
|
2018-03-22 17:08:20 -07:00
|
|
|
|
2018-03-23 12:24:29 -07:00
|
|
|
namespace Fortran::semantics {
|
2018-03-22 17:08:20 -07:00
|
|
|
|
2020-03-28 21:00:16 -07:00
|
|
|
template <typename T>
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpOptional(llvm::raw_ostream &os, const char *label, const T &x) {
|
2019-04-04 14:46:40 -07:00
|
|
|
if (x) {
|
|
|
|
os << ' ' << label << ':' << *x;
|
|
|
|
}
|
|
|
|
}
|
2020-03-28 21:00:16 -07:00
|
|
|
template <typename T>
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpExpr(llvm::raw_ostream &os, const char *label,
|
2020-01-14 17:31:25 -08:00
|
|
|
const std::optional<evaluate::Expr<T>> &x) {
|
|
|
|
if (x) {
|
|
|
|
x->AsFortran(os << ' ' << label << ':');
|
|
|
|
}
|
|
|
|
}
|
2019-04-04 14:46:40 -07:00
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpBool(llvm::raw_ostream &os, const char *label, bool x) {
|
2019-04-04 14:46:40 -07:00
|
|
|
if (x) {
|
|
|
|
os << ' ' << label;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpSymbolVector(llvm::raw_ostream &os, const SymbolVector &list) {
|
2019-04-04 14:46:40 -07:00
|
|
|
char sep{' '};
|
2019-10-22 16:53:29 -07:00
|
|
|
for (const Symbol &elem : list) {
|
|
|
|
os << sep << elem.name();
|
2019-04-04 14:46:40 -07:00
|
|
|
sep = ',';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpType(llvm::raw_ostream &os, const Symbol &symbol) {
|
2019-04-04 14:46:40 -07:00
|
|
|
if (const auto *type{symbol.GetType()}) {
|
|
|
|
os << *type << ' ';
|
|
|
|
}
|
|
|
|
}
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpType(llvm::raw_ostream &os, const DeclTypeSpec *type) {
|
2019-04-04 14:46:40 -07:00
|
|
|
if (type) {
|
|
|
|
os << ' ' << *type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-28 21:00:16 -07:00
|
|
|
template <typename T>
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpList(llvm::raw_ostream &os, const char *label, const T &list) {
|
2019-04-04 14:46:40 -07:00
|
|
|
if (!list.empty()) {
|
|
|
|
os << ' ' << label << ':';
|
|
|
|
char sep{' '};
|
|
|
|
for (const auto &elem : list) {
|
|
|
|
os << sep << elem;
|
|
|
|
sep = ',';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-18 14:58:12 -08:00
|
|
|
void SubprogramDetails::set_moduleInterface(Symbol &symbol) {
|
|
|
|
CHECK(!moduleInterface_);
|
|
|
|
moduleInterface_ = &symbol;
|
|
|
|
}
|
|
|
|
|
2018-08-02 16:21:27 -07:00
|
|
|
const Scope *ModuleDetails::parent() const {
|
2018-11-16 12:43:08 -08:00
|
|
|
return isSubmodule_ && scope_ ? &scope_->parent() : nullptr;
|
2018-08-02 16:21:27 -07:00
|
|
|
}
|
|
|
|
const Scope *ModuleDetails::ancestor() const {
|
2020-03-02 16:43:01 -08:00
|
|
|
return isSubmodule_ && scope_ ? FindModuleContaining(*scope_) : nullptr;
|
2018-08-02 16:21:27 -07:00
|
|
|
}
|
|
|
|
void ModuleDetails::set_scope(const Scope *scope) {
|
|
|
|
CHECK(!scope_);
|
|
|
|
bool scopeIsSubmodule{scope->parent().kind() == Scope::Kind::Module};
|
|
|
|
CHECK(isSubmodule_ == scopeIsSubmodule);
|
|
|
|
scope_ = scope;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &os, const SubprogramDetails &x) {
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpBool(os, "isInterface", x.isInterface_);
|
2021-07-22 14:53:50 -07:00
|
|
|
DumpBool(os, "dummy", x.isDummy_);
|
2021-03-24 11:25:22 -07:00
|
|
|
DumpOptional(os, "bindName", x.bindName());
|
2019-01-04 17:10:31 -08:00
|
|
|
if (x.result_) {
|
2020-03-17 14:48:36 -07:00
|
|
|
DumpType(os << " result:", x.result());
|
|
|
|
os << x.result_->name();
|
2019-03-20 13:52:33 -07:00
|
|
|
if (!x.result_->attrs().empty()) {
|
|
|
|
os << ", " << x.result_->attrs();
|
|
|
|
}
|
2019-01-04 17:10:31 -08:00
|
|
|
}
|
2020-03-19 16:31:10 -07:00
|
|
|
if (x.entryScope_) {
|
|
|
|
os << " entry";
|
|
|
|
if (x.entryScope_->symbol()) {
|
|
|
|
os << " in " << x.entryScope_->symbol()->name();
|
|
|
|
}
|
|
|
|
}
|
2020-03-17 14:48:36 -07:00
|
|
|
char sep{'('};
|
|
|
|
os << ' ';
|
|
|
|
for (const Symbol *arg : x.dummyArgs_) {
|
|
|
|
os << sep;
|
|
|
|
sep = ',';
|
|
|
|
if (arg) {
|
|
|
|
DumpType(os, *arg);
|
|
|
|
os << arg->name();
|
|
|
|
} else {
|
|
|
|
os << '*';
|
2019-01-04 17:10:31 -08:00
|
|
|
}
|
|
|
|
}
|
2020-03-17 14:48:36 -07:00
|
|
|
os << (sep == '(' ? "()" : ")");
|
2020-07-23 17:15:33 -07:00
|
|
|
if (x.stmtFunction_) {
|
|
|
|
os << " -> " << x.stmtFunction_->AsFortran();
|
|
|
|
}
|
2022-02-18 14:58:12 -08:00
|
|
|
if (x.moduleInterface_) {
|
|
|
|
os << " moduleInterface: " << *x.moduleInterface_;
|
|
|
|
}
|
2023-04-10 11:05:03 -07:00
|
|
|
if (x.defaultIgnoreTKR_) {
|
|
|
|
os << " defaultIgnoreTKR";
|
|
|
|
}
|
2023-05-06 15:03:39 -07:00
|
|
|
if (x.cudaSubprogramAttrs_) {
|
|
|
|
os << " cudaSubprogramAttrs: "
|
|
|
|
<< common::EnumToString(*x.cudaSubprogramAttrs_);
|
|
|
|
}
|
|
|
|
if (!x.cudaLaunchBounds_.empty()) {
|
|
|
|
os << " cudaLaunchBounds:";
|
|
|
|
for (auto x : x.cudaLaunchBounds_) {
|
|
|
|
os << ' ' << x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!x.cudaClusterDims_.empty()) {
|
|
|
|
os << " cudaClusterDims:";
|
|
|
|
for (auto x : x.cudaClusterDims_) {
|
|
|
|
os << ' ' << x;
|
|
|
|
}
|
|
|
|
}
|
2019-01-04 17:10:31 -08:00
|
|
|
return os;
|
2018-04-12 12:59:42 -07:00
|
|
|
}
|
|
|
|
|
2019-01-04 17:10:31 -08:00
|
|
|
void EntityDetails::set_type(const DeclTypeSpec &type) {
|
2018-06-05 12:18:35 -07:00
|
|
|
CHECK(!type_);
|
2018-12-11 14:51:08 -08:00
|
|
|
type_ = &type;
|
2018-06-05 12:18:35 -07:00
|
|
|
}
|
|
|
|
|
[flang]Semantics for SELECT RANK.
Summary:
Initially on github I worked on semantic checks.Then I tried some compile-time
test of the rank value, they were failing as there were no symbols
generated for them inside SELECT RANK's scope.So I went further to
add new symbol in each scope, also added the respective 'rank: '
field for a symbol when we dump the symboltable. I added a field to
keep track of the rank in AssocEntityDetails class.This caused shape
analysis framework to become inconsistent. So shape analysis framework
was updated to handle this new representation.
* I added more tests for above changes.
* On phabricator I addressed some minor changes.
* Lastly I worked on review comments.
Reviewers: klausler,sscalpone,DavidTruby,kiranchandramohan,tskeith,anchu-rajendran,kiranktp
Reviewed By:klausler, DavidTruby, tskeith
Subscribers:#flang-commits, #llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78623
2020-04-22 14:46:37 +05:30
|
|
|
void AssocEntityDetails::set_rank(int rank) { rank_ = rank; }
|
2023-09-13 16:13:31 -07:00
|
|
|
void AssocEntityDetails::set_IsAssumedSize() { rank_ = isAssumedSize; }
|
|
|
|
void AssocEntityDetails::set_IsAssumedRank() { rank_ = isAssumedRank; }
|
2019-01-15 16:59:20 -08:00
|
|
|
void EntityDetails::ReplaceType(const DeclTypeSpec &type) { type_ = &type; }
|
2019-01-07 15:05:53 -08:00
|
|
|
|
2022-10-12 12:59:48 -07:00
|
|
|
ObjectEntityDetails::ObjectEntityDetails(EntityDetails &&d)
|
2022-12-16 09:54:55 -08:00
|
|
|
: EntityDetails(std::move(d)) {}
|
2022-10-12 12:59:48 -07:00
|
|
|
|
2018-06-05 12:18:35 -07:00
|
|
|
void ObjectEntityDetails::set_shape(const ArraySpec &shape) {
|
2018-04-12 12:59:42 -07:00
|
|
|
CHECK(shape_.empty());
|
|
|
|
for (const auto &shapeSpec : shape) {
|
2019-01-07 15:05:53 -08:00
|
|
|
shape_.push_back(shapeSpec);
|
2018-04-12 12:59:42 -07:00
|
|
|
}
|
|
|
|
}
|
2019-04-04 14:46:40 -07:00
|
|
|
void ObjectEntityDetails::set_coshape(const ArraySpec &coshape) {
|
|
|
|
CHECK(coshape_.empty());
|
|
|
|
for (const auto &shapeSpec : coshape) {
|
|
|
|
coshape_.push_back(shapeSpec);
|
|
|
|
}
|
|
|
|
}
|
2018-04-12 12:59:42 -07:00
|
|
|
|
2022-12-16 09:54:55 -08:00
|
|
|
ProcEntityDetails::ProcEntityDetails(EntityDetails &&d)
|
|
|
|
: EntityDetails(std::move(d)) {}
|
2018-06-05 12:18:35 -07:00
|
|
|
|
2018-08-29 11:38:12 -07:00
|
|
|
UseErrorDetails::UseErrorDetails(const UseDetails &useDetails) {
|
[flang][NFC] Remove link-time dependency of Evaluate on Semantics
Summary:
Some Symbol-related functions used in Evaluate were moved to
Evaluate/tools.h. This includes changing some member functions that were
replaced by non-member functions `IsDummy`, `GetUsedModule`, and
`CountLenParameters`.
Some member functions were made inline in `Scope`, `Symbol`,
`ArraySpec`, and `DeclTypeSpec`. The definitions were preceded by a
comment explaining why they are inline.
`IsConstantShape` was expanded inline in `IsDescriptor` because it isn't
used anywhere else
After this change, at least when compiling with clang on macos,
`libFortranEvaluate.a` has no undefined symbols that are satisfied by
`libFortranSemantics.a`.
Reviewers: klausler, PeteSteinfeld, sscalpone, jdoerfert, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D80762
2020-05-29 16:39:13 -07:00
|
|
|
add_occurrence(useDetails.location(), *GetUsedModule(useDetails).scope());
|
2018-08-29 11:38:12 -07:00
|
|
|
}
|
|
|
|
UseErrorDetails &UseErrorDetails::add_occurrence(
|
|
|
|
const SourceName &location, const Scope &module) {
|
2018-11-16 12:43:08 -08:00
|
|
|
occurrences_.push_back(std::make_pair(location, &module));
|
2018-08-29 11:38:12 -07:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-11-22 12:52:23 -08:00
|
|
|
void GenericDetails::AddSpecificProc(
|
|
|
|
const Symbol &proc, SourceName bindingName) {
|
|
|
|
specificProcs_.push_back(proc);
|
|
|
|
bindingNames_.push_back(bindingName);
|
|
|
|
}
|
2018-06-22 08:21:19 -07:00
|
|
|
void GenericDetails::set_specific(Symbol &specific) {
|
2018-05-22 16:12:56 -07:00
|
|
|
CHECK(!specific_);
|
2019-07-30 15:29:50 -07:00
|
|
|
CHECK(!derivedType_);
|
2018-06-22 08:21:19 -07:00
|
|
|
specific_ = &specific;
|
|
|
|
}
|
2022-09-21 12:15:09 -07:00
|
|
|
void GenericDetails::clear_specific() { specific_ = nullptr; }
|
2018-06-22 08:21:19 -07:00
|
|
|
void GenericDetails::set_derivedType(Symbol &derivedType) {
|
2019-07-30 15:29:50 -07:00
|
|
|
CHECK(!specific_);
|
2018-06-22 08:21:19 -07:00
|
|
|
CHECK(!derivedType_);
|
|
|
|
derivedType_ = &derivedType;
|
2018-05-22 16:12:56 -07:00
|
|
|
}
|
2022-10-07 12:58:43 -07:00
|
|
|
void GenericDetails::clear_derivedType() { derivedType_ = nullptr; }
|
2020-12-02 15:13:49 -08:00
|
|
|
void GenericDetails::AddUse(const Symbol &use) {
|
|
|
|
CHECK(use.has<UseDetails>());
|
|
|
|
uses_.push_back(use);
|
|
|
|
}
|
2018-05-22 16:12:56 -07:00
|
|
|
|
|
|
|
const Symbol *GenericDetails::CheckSpecific() const {
|
2019-04-25 13:18:33 -07:00
|
|
|
return const_cast<GenericDetails *>(this)->CheckSpecific();
|
|
|
|
}
|
|
|
|
Symbol *GenericDetails::CheckSpecific() {
|
2018-06-19 16:06:41 -07:00
|
|
|
if (specific_) {
|
2019-10-22 16:53:29 -07:00
|
|
|
for (const Symbol &proc : specificProcs_) {
|
|
|
|
if (&proc == specific_) {
|
2018-05-22 16:12:56 -07:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
2018-06-19 16:06:41 -07:00
|
|
|
return specific_;
|
2018-05-22 16:12:56 -07:00
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 13:06:25 -07:00
|
|
|
void GenericDetails::CopyFrom(const GenericDetails &from) {
|
2020-07-09 09:38:22 -07:00
|
|
|
CHECK(specificProcs_.size() == bindingNames_.size());
|
|
|
|
CHECK(from.specificProcs_.size() == from.bindingNames_.size());
|
2020-12-02 15:13:49 -08:00
|
|
|
kind_ = from.kind_;
|
2019-08-01 13:06:25 -07:00
|
|
|
if (from.derivedType_) {
|
2019-09-12 17:38:40 -07:00
|
|
|
CHECK(!derivedType_ || derivedType_ == from.derivedType_);
|
2019-08-01 13:06:25 -07:00
|
|
|
derivedType_ = from.derivedType_;
|
|
|
|
}
|
2020-07-09 09:38:22 -07:00
|
|
|
for (std::size_t i{0}; i < from.specificProcs_.size(); ++i) {
|
2019-10-22 16:53:29 -07:00
|
|
|
if (std::find_if(specificProcs_.begin(), specificProcs_.end(),
|
2020-07-09 09:38:22 -07:00
|
|
|
[&](const Symbol &mySymbol) {
|
2022-03-30 11:51:50 -07:00
|
|
|
return &mySymbol.GetUltimate() ==
|
|
|
|
&from.specificProcs_[i]->GetUltimate();
|
2020-07-09 09:38:22 -07:00
|
|
|
}) == specificProcs_.end()) {
|
|
|
|
specificProcs_.push_back(from.specificProcs_[i]);
|
|
|
|
bindingNames_.push_back(from.bindingNames_[i]);
|
2019-09-12 17:38:40 -07:00
|
|
|
}
|
|
|
|
}
|
2019-07-18 16:58:45 -07:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:16:42 -07:00
|
|
|
// The name of the kind of details for this symbol.
|
|
|
|
// This is primarily for debugging.
|
2018-07-19 13:28:24 -07:00
|
|
|
std::string DetailsToString(const Details &details) {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2018-06-18 11:03:43 -07:00
|
|
|
common::visitors{
|
2018-05-22 16:12:56 -07:00
|
|
|
[](const UnknownDetails &) { return "Unknown"; },
|
|
|
|
[](const MainProgramDetails &) { return "MainProgram"; },
|
|
|
|
[](const ModuleDetails &) { return "Module"; },
|
|
|
|
[](const SubprogramDetails &) { return "Subprogram"; },
|
|
|
|
[](const SubprogramNameDetails &) { return "SubprogramName"; },
|
|
|
|
[](const EntityDetails &) { return "Entity"; },
|
2018-06-05 12:18:35 -07:00
|
|
|
[](const ObjectEntityDetails &) { return "ObjectEntity"; },
|
|
|
|
[](const ProcEntityDetails &) { return "ProcEntity"; },
|
2018-06-22 08:21:19 -07:00
|
|
|
[](const DerivedTypeDetails &) { return "DerivedType"; },
|
2018-05-22 16:12:56 -07:00
|
|
|
[](const UseDetails &) { return "Use"; },
|
|
|
|
[](const UseErrorDetails &) { return "UseError"; },
|
2018-10-18 07:55:48 -07:00
|
|
|
[](const HostAssocDetails &) { return "HostAssoc"; },
|
2018-05-22 16:12:56 -07:00
|
|
|
[](const GenericDetails &) { return "Generic"; },
|
2018-08-31 16:20:00 -07:00
|
|
|
[](const ProcBindingDetails &) { return "ProcBinding"; },
|
2019-02-05 14:43:00 -08:00
|
|
|
[](const NamelistDetails &) { return "Namelist"; },
|
2019-02-14 07:59:20 -08:00
|
|
|
[](const CommonBlockDetails &) { return "CommonBlockDetails"; },
|
2018-09-04 10:28:27 -07:00
|
|
|
[](const TypeParamDetails &) { return "TypeParam"; },
|
2018-09-25 08:53:53 -07:00
|
|
|
[](const MiscDetails &) { return "Misc"; },
|
2019-01-15 16:59:20 -08:00
|
|
|
[](const AssocEntityDetails &) { return "AssocEntity"; },
|
2018-04-17 14:16:42 -07:00
|
|
|
},
|
2018-05-03 15:57:56 -07:00
|
|
|
details);
|
|
|
|
}
|
|
|
|
|
2022-11-30 16:11:20 -08:00
|
|
|
std::string Symbol::GetDetailsName() const { return DetailsToString(details_); }
|
2018-05-03 15:57:56 -07:00
|
|
|
|
2018-11-05 14:36:11 -08:00
|
|
|
void Symbol::set_details(Details &&details) {
|
2018-05-14 13:51:13 -07:00
|
|
|
CHECK(CanReplaceDetails(details));
|
2018-11-05 14:36:11 -08:00
|
|
|
details_ = std::move(details);
|
2018-05-14 13:51:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Symbol::CanReplaceDetails(const Details &details) const {
|
|
|
|
if (has<UnknownDetails>()) {
|
2020-03-28 21:00:16 -07:00
|
|
|
return true; // can always replace UnknownDetails
|
2018-05-14 13:51:13 -07:00
|
|
|
} else {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2018-06-18 11:03:43 -07:00
|
|
|
common::visitors{
|
2018-06-05 12:18:35 -07:00
|
|
|
[](const UseErrorDetails &) { return true; },
|
2019-11-22 08:15:02 -08:00
|
|
|
[&](const ObjectEntityDetails &) { return has<EntityDetails>(); },
|
|
|
|
[&](const ProcEntityDetails &) { return has<EntityDetails>(); },
|
|
|
|
[&](const SubprogramDetails &) {
|
2019-06-14 15:04:13 -07:00
|
|
|
return has<SubprogramNameDetails>() || has<EntityDetails>();
|
2018-06-05 12:18:35 -07:00
|
|
|
},
|
2019-11-22 08:15:02 -08:00
|
|
|
[&](const DerivedTypeDetails &) {
|
2021-02-04 16:25:59 -06:00
|
|
|
const auto *derived{this->detailsIf<DerivedTypeDetails>()};
|
2019-11-22 08:15:02 -08:00
|
|
|
return derived && derived->isForwardReferenced();
|
|
|
|
},
|
2020-12-02 15:13:49 -08:00
|
|
|
[&](const UseDetails &x) {
|
2021-02-04 16:25:59 -06:00
|
|
|
const auto *use{this->detailsIf<UseDetails>()};
|
2020-12-02 15:13:49 -08:00
|
|
|
return use && use->symbol() == x.symbol();
|
|
|
|
},
|
2022-12-02 07:19:49 -08:00
|
|
|
[&](const HostAssocDetails &) {
|
|
|
|
return this->has<HostAssocDetails>();
|
|
|
|
},
|
2018-06-05 12:18:35 -07:00
|
|
|
[](const auto &) { return false; },
|
|
|
|
},
|
|
|
|
details);
|
2018-05-14 13:51:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-12 13:50:45 -07:00
|
|
|
// Usually a symbol's name is the first occurrence in the source, but sometimes
|
|
|
|
// we want to replace it with one at a different location (but same characters).
|
|
|
|
void Symbol::ReplaceName(const SourceName &name) {
|
|
|
|
CHECK(name == name_);
|
|
|
|
name_ = name;
|
|
|
|
}
|
|
|
|
|
2018-06-26 15:01:42 -07:00
|
|
|
void Symbol::SetType(const DeclTypeSpec &type) {
|
2022-03-23 14:05:50 -07:00
|
|
|
common::visit(common::visitors{
|
|
|
|
[&](EntityDetails &x) { x.set_type(type); },
|
|
|
|
[&](ObjectEntityDetails &x) { x.set_type(type); },
|
|
|
|
[&](AssocEntityDetails &x) { x.set_type(type); },
|
2022-12-16 09:54:55 -08:00
|
|
|
[&](ProcEntityDetails &x) { x.set_type(type); },
|
2022-03-23 14:05:50 -07:00
|
|
|
[&](TypeParamDetails &x) { x.set_type(type); },
|
|
|
|
[](auto &) {},
|
|
|
|
},
|
2018-06-26 15:01:42 -07:00
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2021-03-24 11:25:22 -07:00
|
|
|
template <typename T>
|
|
|
|
constexpr bool HasBindName{std::is_convertible_v<T, const WithBindName *>};
|
|
|
|
|
|
|
|
const std::string *Symbol::GetBindName() const {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2021-03-24 11:25:22 -07:00
|
|
|
[&](auto &x) -> const std::string * {
|
|
|
|
if constexpr (HasBindName<decltype(&x)>) {
|
|
|
|
return x.bindName();
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Symbol::SetBindName(std::string &&name) {
|
2022-03-23 14:05:50 -07:00
|
|
|
common::visit(
|
2021-03-24 11:25:22 -07:00
|
|
|
[&](auto &x) {
|
|
|
|
if constexpr (HasBindName<decltype(&x)>) {
|
|
|
|
x.set_bindName(std::move(name));
|
|
|
|
} else {
|
|
|
|
DIE("bind name not allowed on this kind of symbol");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2023-02-28 11:58:30 -08:00
|
|
|
bool Symbol::GetIsExplicitBindName() const {
|
|
|
|
return common::visit(
|
|
|
|
[&](auto &x) -> bool {
|
|
|
|
if constexpr (HasBindName<decltype(&x)>) {
|
|
|
|
return x.isExplicitBindName();
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Symbol::SetIsExplicitBindName(bool yes) {
|
|
|
|
common::visit(
|
|
|
|
[&](auto &x) {
|
|
|
|
if constexpr (HasBindName<decltype(&x)>) {
|
|
|
|
x.set_isExplicitBindName(yes);
|
|
|
|
} else {
|
|
|
|
DIE("bind name not allowed on this kind of symbol");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2019-02-20 17:45:39 -08:00
|
|
|
bool Symbol::IsFuncResult() const {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2019-02-20 17:45:39 -08:00
|
|
|
common::visitors{[](const EntityDetails &x) { return x.isFuncResult(); },
|
|
|
|
[](const ObjectEntityDetails &x) { return x.isFuncResult(); },
|
|
|
|
[](const ProcEntityDetails &x) { return x.isFuncResult(); },
|
|
|
|
[](const HostAssocDetails &x) { return x.symbol().IsFuncResult(); },
|
|
|
|
[](const auto &) { return false; }},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2019-02-07 12:25:59 -08:00
|
|
|
bool Symbol::IsObjectArray() const {
|
2019-02-06 10:28:31 -08:00
|
|
|
const auto *details{std::get_if<ObjectEntityDetails>(&details_)};
|
|
|
|
return details && details->IsArray();
|
|
|
|
}
|
|
|
|
|
2018-10-26 11:57:08 -07:00
|
|
|
bool Symbol::IsSubprogram() const {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2018-06-18 11:03:43 -07:00
|
|
|
common::visitors{
|
2018-06-05 12:18:35 -07:00
|
|
|
[](const SubprogramDetails &) { return true; },
|
|
|
|
[](const SubprogramNameDetails &) { return true; },
|
|
|
|
[](const GenericDetails &) { return true; },
|
2018-10-26 11:57:08 -07:00
|
|
|
[](const UseDetails &x) { return x.symbol().IsSubprogram(); },
|
2018-06-05 12:18:35 -07:00
|
|
|
[](const auto &) { return false; },
|
2018-05-14 13:51:13 -07:00
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2019-07-02 14:00:44 -07:00
|
|
|
bool Symbol::IsFromModFile() const {
|
|
|
|
return test(Flag::ModFile) ||
|
2022-01-26 09:54:58 -08:00
|
|
|
(!owner_->IsTopLevel() && owner_->symbol()->IsFromModFile());
|
2019-07-02 14:00:44 -07:00
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const EntityDetails &x) {
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpBool(os, "dummy", x.isDummy());
|
|
|
|
DumpBool(os, "funcResult", x.isFuncResult());
|
2018-06-05 12:18:35 -07:00
|
|
|
if (x.type()) {
|
|
|
|
os << " type: " << *x.type();
|
|
|
|
}
|
2021-03-24 11:25:22 -07:00
|
|
|
DumpOptional(os, "bindName", x.bindName());
|
2018-06-05 12:18:35 -07:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &os, const ObjectEntityDetails &x) {
|
2019-01-04 17:10:31 -08:00
|
|
|
os << *static_cast<const EntityDetails *>(&x);
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpList(os, "shape", x.shape());
|
|
|
|
DumpList(os, "coshape", x.coshape());
|
2020-01-14 17:31:25 -08:00
|
|
|
DumpExpr(os, "init", x.init_);
|
2022-04-13 10:39:16 -07:00
|
|
|
if (x.unanalyzedPDTComponentInit()) {
|
|
|
|
os << " (has unanalyzedPDTComponentInit)";
|
|
|
|
}
|
2023-04-10 11:05:03 -07:00
|
|
|
if (!x.ignoreTKR_.empty()) {
|
2023-05-17 11:19:14 -07:00
|
|
|
x.ignoreTKR_.Dump(os << ' ', common::EnumToString);
|
2023-04-10 11:05:03 -07:00
|
|
|
}
|
2023-05-06 15:03:39 -07:00
|
|
|
if (x.cudaDataAttr()) {
|
|
|
|
os << " cudaDataAttr: " << common::EnumToString(*x.cudaDataAttr());
|
|
|
|
}
|
2018-04-12 12:59:42 -07:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &os, const AssocEntityDetails &x) {
|
2019-01-15 16:59:20 -08:00
|
|
|
os << *static_cast<const EntityDetails *>(&x);
|
2023-09-13 16:13:31 -07:00
|
|
|
if (x.IsAssumedSize()) {
|
|
|
|
os << " RANK(*)";
|
|
|
|
} else if (x.IsAssumedRank()) {
|
|
|
|
os << " RANK DEFAULT";
|
|
|
|
} else if (auto assocRank{x.rank()}) {
|
|
|
|
os << " RANK(" << *assocRank << ')';
|
[flang]Semantics for SELECT RANK.
Summary:
Initially on github I worked on semantic checks.Then I tried some compile-time
test of the rank value, they were failing as there were no symbols
generated for them inside SELECT RANK's scope.So I went further to
add new symbol in each scope, also added the respective 'rank: '
field for a symbol when we dump the symboltable. I added a field to
keep track of the rank in AssocEntityDetails class.This caused shape
analysis framework to become inconsistent. So shape analysis framework
was updated to handle this new representation.
* I added more tests for above changes.
* On phabricator I addressed some minor changes.
* Lastly I worked on review comments.
Reviewers: klausler,sscalpone,DavidTruby,kiranchandramohan,tskeith,anchu-rajendran,kiranktp
Reviewed By:klausler, DavidTruby, tskeith
Subscribers:#flang-commits, #llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78623
2020-04-22 14:46:37 +05:30
|
|
|
}
|
2020-01-14 17:31:25 -08:00
|
|
|
DumpExpr(os, "expr", x.expr());
|
2019-01-15 16:59:20 -08:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &os, const ProcEntityDetails &x) {
|
2022-12-16 09:54:55 -08:00
|
|
|
if (x.procInterface_) {
|
|
|
|
os << ' ' << x.procInterface_->name();
|
2019-04-04 14:46:40 -07:00
|
|
|
} else {
|
2022-12-16 09:54:55 -08:00
|
|
|
DumpType(os, x.type());
|
2019-01-04 17:10:31 -08:00
|
|
|
}
|
2021-03-24 11:25:22 -07:00
|
|
|
DumpOptional(os, "bindName", x.bindName());
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpOptional(os, "passName", x.passName());
|
2019-08-06 11:49:47 -07:00
|
|
|
if (x.init()) {
|
|
|
|
if (const Symbol * target{*x.init()}) {
|
|
|
|
os << " => " << target->name();
|
|
|
|
} else {
|
|
|
|
os << " => NULL()";
|
|
|
|
}
|
2019-08-06 10:22:10 -07:00
|
|
|
}
|
2023-05-06 15:03:39 -07:00
|
|
|
if (x.isCUDAKernel()) {
|
|
|
|
os << " isCUDAKernel";
|
|
|
|
}
|
2018-06-05 12:18:35 -07:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &os, const DerivedTypeDetails &x) {
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpBool(os, "sequence", x.sequence_);
|
|
|
|
DumpList(os, "components", x.componentNames_);
|
2018-04-17 14:16:42 -07:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-12-02 15:13:49 -08:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const GenericDetails &x) {
|
|
|
|
os << ' ' << x.kind().ToString();
|
|
|
|
DumpBool(os, "(specific)", x.specific() != nullptr);
|
|
|
|
DumpBool(os, "(derivedType)", x.derivedType() != nullptr);
|
|
|
|
if (const auto &uses{x.uses()}; !uses.empty()) {
|
|
|
|
os << " (uses:";
|
|
|
|
char sep{' '};
|
|
|
|
for (const Symbol &use : uses) {
|
|
|
|
const Symbol &ultimate{use.GetUltimate()};
|
|
|
|
os << sep << ultimate.name() << "->"
|
|
|
|
<< ultimate.owner().GetName().value();
|
|
|
|
sep = ',';
|
|
|
|
}
|
|
|
|
os << ')';
|
|
|
|
}
|
|
|
|
os << " procs:";
|
|
|
|
DumpSymbolVector(os, x.specificProcs());
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
|
2018-05-03 15:57:56 -07:00
|
|
|
os << DetailsToString(details);
|
2022-03-23 14:05:50 -07:00
|
|
|
common::visit( //
|
2018-06-18 11:03:43 -07:00
|
|
|
common::visitors{
|
2019-08-15 13:50:27 -07:00
|
|
|
[&](const UnknownDetails &) {},
|
|
|
|
[&](const MainProgramDetails &) {},
|
2018-08-02 16:21:27 -07:00
|
|
|
[&](const ModuleDetails &x) {
|
|
|
|
if (x.isSubmodule()) {
|
2018-11-16 12:43:08 -08:00
|
|
|
os << " (";
|
|
|
|
if (x.ancestor()) {
|
2019-08-21 06:29:11 -07:00
|
|
|
auto ancestor{x.ancestor()->GetName().value()};
|
2018-11-16 12:43:08 -08:00
|
|
|
os << ancestor;
|
|
|
|
if (x.parent()) {
|
2019-08-21 06:29:11 -07:00
|
|
|
auto parent{x.parent()->GetName().value()};
|
2018-11-16 12:43:08 -08:00
|
|
|
if (ancestor != parent) {
|
|
|
|
os << ':' << parent;
|
|
|
|
}
|
|
|
|
}
|
2018-08-02 16:21:27 -07:00
|
|
|
}
|
|
|
|
os << ")";
|
|
|
|
}
|
2023-05-10 13:26:01 -07:00
|
|
|
if (x.isDefaultPrivate()) {
|
|
|
|
os << " isDefaultPrivate";
|
|
|
|
}
|
2018-08-02 16:21:27 -07:00
|
|
|
},
|
2018-05-14 13:51:13 -07:00
|
|
|
[&](const SubprogramNameDetails &x) {
|
|
|
|
os << ' ' << EnumToString(x.kind());
|
2018-03-22 17:08:20 -07:00
|
|
|
},
|
2018-05-03 15:57:56 -07:00
|
|
|
[&](const UseDetails &x) {
|
[flang][NFC] Remove link-time dependency of Evaluate on Semantics
Summary:
Some Symbol-related functions used in Evaluate were moved to
Evaluate/tools.h. This includes changing some member functions that were
replaced by non-member functions `IsDummy`, `GetUsedModule`, and
`CountLenParameters`.
Some member functions were made inline in `Scope`, `Symbol`,
`ArraySpec`, and `DeclTypeSpec`. The definitions were preceded by a
comment explaining why they are inline.
`IsConstantShape` was expanded inline in `IsDescriptor` because it isn't
used anywhere else
After this change, at least when compiling with clang on macos,
`libFortranEvaluate.a` has no undefined symbols that are satisfied by
`libFortranSemantics.a`.
Reviewers: klausler, PeteSteinfeld, sscalpone, jdoerfert, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D80762
2020-05-29 16:39:13 -07:00
|
|
|
os << " from " << x.symbol().name() << " in "
|
|
|
|
<< GetUsedModule(x).name();
|
2018-05-03 15:57:56 -07:00
|
|
|
},
|
|
|
|
[&](const UseErrorDetails &x) {
|
|
|
|
os << " uses:";
|
2020-12-15 16:11:58 -08:00
|
|
|
char sep{':'};
|
2018-11-16 12:43:08 -08:00
|
|
|
for (const auto &[location, module] : x.occurrences()) {
|
2020-12-15 16:11:58 -08:00
|
|
|
os << sep << " from " << module->GetName().value() << " at "
|
|
|
|
<< location;
|
|
|
|
sep = ',';
|
2018-05-03 15:57:56 -07:00
|
|
|
}
|
|
|
|
},
|
2018-10-18 07:55:48 -07:00
|
|
|
[](const HostAssocDetails &) {},
|
2018-08-31 16:20:00 -07:00
|
|
|
[&](const ProcBindingDetails &x) {
|
|
|
|
os << " => " << x.symbol().name();
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpOptional(os, "passName", x.passName());
|
2023-05-16 12:33:29 -07:00
|
|
|
if (x.numPrivatesNotOverridden() > 0) {
|
|
|
|
os << " numPrivatesNotOverridden: "
|
|
|
|
<< x.numPrivatesNotOverridden();
|
|
|
|
}
|
2018-08-31 16:20:00 -07:00
|
|
|
},
|
2019-02-05 14:43:00 -08:00
|
|
|
[&](const NamelistDetails &x) {
|
2019-02-18 11:39:46 -08:00
|
|
|
os << ':';
|
2019-07-02 14:00:44 -07:00
|
|
|
DumpSymbolVector(os, x.objects());
|
2019-02-14 07:59:20 -08:00
|
|
|
},
|
|
|
|
[&](const CommonBlockDetails &x) {
|
2021-03-24 11:25:22 -07:00
|
|
|
DumpOptional(os, "bindName", x.bindName());
|
2020-05-06 15:00:14 -07:00
|
|
|
if (x.alignment()) {
|
|
|
|
os << " alignment=" << x.alignment();
|
2020-05-06 11:43:06 -07:00
|
|
|
}
|
2019-02-18 11:39:46 -08:00
|
|
|
os << ':';
|
2020-05-06 12:20:07 -07:00
|
|
|
for (const auto &object : x.objects()) {
|
|
|
|
os << ' ' << object->name();
|
2019-02-05 14:43:00 -08:00
|
|
|
}
|
|
|
|
},
|
2018-09-04 10:28:27 -07:00
|
|
|
[&](const TypeParamDetails &x) {
|
2019-06-22 10:00:18 -07:00
|
|
|
DumpOptional(os, "type", x.type());
|
2018-09-05 16:02:41 -07:00
|
|
|
os << ' ' << common::EnumToString(x.attr());
|
2020-01-14 17:31:25 -08:00
|
|
|
DumpExpr(os, "init", x.init());
|
2018-09-04 10:28:27 -07:00
|
|
|
},
|
2018-09-25 08:53:53 -07:00
|
|
|
[&](const MiscDetails &x) {
|
|
|
|
os << ' ' << MiscDetails::EnumToString(x.kind());
|
|
|
|
},
|
2019-01-15 16:59:20 -08:00
|
|
|
[&](const auto &x) { os << x; },
|
2018-03-22 17:08:20 -07:00
|
|
|
},
|
2018-05-03 15:57:56 -07:00
|
|
|
details);
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &o, Symbol::Flag flag) {
|
2018-06-05 12:18:35 -07:00
|
|
|
return o << Symbol::EnumToString(flag);
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(
|
|
|
|
llvm::raw_ostream &o, const Symbol::Flags &flags) {
|
2018-06-05 12:18:35 -07:00
|
|
|
std::size_t n{flags.count()};
|
|
|
|
std::size_t seen{0};
|
|
|
|
for (std::size_t j{0}; seen < n; ++j) {
|
|
|
|
Symbol::Flag flag{static_cast<Symbol::Flag>(j)};
|
|
|
|
if (flags.test(flag)) {
|
|
|
|
if (seen++ > 0) {
|
|
|
|
o << ", ";
|
|
|
|
}
|
|
|
|
o << flag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Symbol &symbol) {
|
2018-05-03 15:57:56 -07:00
|
|
|
os << symbol.name();
|
|
|
|
if (!symbol.attrs().empty()) {
|
|
|
|
os << ", " << symbol.attrs();
|
|
|
|
}
|
2018-06-05 12:18:35 -07:00
|
|
|
if (!symbol.flags().empty()) {
|
|
|
|
os << " (" << symbol.flags() << ')';
|
|
|
|
}
|
2020-04-22 15:39:24 -07:00
|
|
|
if (symbol.size_) {
|
|
|
|
os << " size=" << symbol.size_ << " offset=" << symbol.offset_;
|
|
|
|
}
|
2018-05-03 15:57:56 -07:00
|
|
|
os << ": " << symbol.details_;
|
2018-03-22 17:08:20 -07:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2021-09-30 23:16:29 +02:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
|
|
void Symbol::dump() const { llvm::errs() << *this << '\n'; }
|
|
|
|
#endif
|
|
|
|
|
2018-06-26 15:01:42 -07:00
|
|
|
// Output a unique name for a scope by qualifying it with the names of
|
2018-08-27 11:48:49 -07:00
|
|
|
// parent scopes. For scopes without corresponding symbols, use the kind
|
|
|
|
// with an index (e.g. Block1, Block2, etc.).
|
2020-02-28 15:11:03 +00:00
|
|
|
static void DumpUniqueName(llvm::raw_ostream &os, const Scope &scope) {
|
2022-01-26 09:54:58 -08:00
|
|
|
if (!scope.IsTopLevel()) {
|
2018-06-26 15:01:42 -07:00
|
|
|
DumpUniqueName(os, scope.parent());
|
|
|
|
os << '/';
|
2019-05-06 07:26:43 -07:00
|
|
|
if (auto *scopeSymbol{scope.symbol()};
|
|
|
|
scopeSymbol && !scopeSymbol->name().empty()) {
|
2019-01-04 17:10:31 -08:00
|
|
|
os << scopeSymbol->name();
|
2018-06-26 15:01:42 -07:00
|
|
|
} else {
|
2018-08-27 11:48:49 -07:00
|
|
|
int index{1};
|
|
|
|
for (auto &child : scope.parent().children()) {
|
|
|
|
if (child == scope) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (child.kind() == scope.kind()) {
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os << Scope::EnumToString(scope.kind()) << index;
|
2018-06-26 15:01:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dump a symbol for UnparseWithSymbols. This will be used for tests so the
|
|
|
|
// format should be reasonably stable.
|
2020-02-28 15:11:03 +00:00
|
|
|
llvm::raw_ostream &DumpForUnparse(
|
|
|
|
llvm::raw_ostream &os, const Symbol &symbol, bool isDef) {
|
2018-06-26 15:01:42 -07:00
|
|
|
DumpUniqueName(os, symbol.owner());
|
2019-01-04 17:10:31 -08:00
|
|
|
os << '/' << symbol.name();
|
2018-06-26 15:01:42 -07:00
|
|
|
if (isDef) {
|
|
|
|
if (!symbol.attrs().empty()) {
|
|
|
|
os << ' ' << symbol.attrs();
|
|
|
|
}
|
2019-09-12 23:03:06 -07:00
|
|
|
if (!symbol.flags().empty()) {
|
|
|
|
os << " (" << symbol.flags() << ')';
|
|
|
|
}
|
2018-06-26 15:01:42 -07:00
|
|
|
os << ' ' << symbol.GetDetailsName();
|
2019-04-04 14:46:40 -07:00
|
|
|
DumpType(os, symbol.GetType());
|
2018-06-26 15:01:42 -07:00
|
|
|
}
|
|
|
|
return os;
|
|
|
|
}
|
2019-01-07 15:05:53 -08:00
|
|
|
|
2018-12-04 10:55:32 -08:00
|
|
|
const DerivedTypeSpec *Symbol::GetParentTypeSpec(const Scope *scope) const {
|
|
|
|
if (const Symbol * parentComponent{GetParentComponent(scope)}) {
|
|
|
|
const auto &object{parentComponent->get<ObjectEntityDetails>()};
|
2019-02-18 13:47:34 -08:00
|
|
|
return &object.type()->derivedTypeSpec();
|
2018-12-04 10:55:32 -08:00
|
|
|
} else {
|
|
|
|
return nullptr;
|
2019-01-07 15:05:53 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 15:39:11 -07:00
|
|
|
const Symbol *Symbol::GetParentComponent(const Scope *scope) const {
|
|
|
|
if (const auto *dtDetails{detailsIf<DerivedTypeDetails>()}) {
|
2020-09-11 11:02:04 -07:00
|
|
|
if (const Scope * localScope{scope ? scope : scope_}) {
|
|
|
|
return dtDetails->GetParentComponent(DEREF(localScope));
|
2019-03-11 15:39:11 -07:00
|
|
|
}
|
|
|
|
}
|
2020-09-11 11:02:04 -07:00
|
|
|
return nullptr;
|
2019-03-11 15:39:11 -07:00
|
|
|
}
|
|
|
|
|
2019-02-05 10:48:26 -08:00
|
|
|
void DerivedTypeDetails::add_component(const Symbol &symbol) {
|
|
|
|
if (symbol.test(Symbol::Flag::ParentComp)) {
|
2019-02-18 13:47:34 -08:00
|
|
|
CHECK(componentNames_.empty());
|
2019-02-05 10:48:26 -08:00
|
|
|
}
|
2019-02-18 13:47:34 -08:00
|
|
|
componentNames_.push_back(symbol.name());
|
2019-02-05 10:48:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
const Symbol *DerivedTypeDetails::GetParentComponent(const Scope &scope) const {
|
2019-03-11 15:39:11 -07:00
|
|
|
if (auto extends{GetParentComponentName()}) {
|
|
|
|
if (auto iter{scope.find(*extends)}; iter != scope.cend()) {
|
|
|
|
if (const Symbol & symbol{*iter->second};
|
|
|
|
symbol.test(Symbol::Flag::ParentComp)) {
|
2019-02-05 10:48:26 -08:00
|
|
|
return &symbol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-10-30 13:30:42 -07:00
|
|
|
const Symbol *DerivedTypeDetails::GetFinalForRank(int rank) const {
|
|
|
|
for (const auto &pair : finals_) {
|
|
|
|
const Symbol &symbol{*pair.second};
|
|
|
|
if (const auto *details{symbol.detailsIf<SubprogramDetails>()}) {
|
|
|
|
if (details->dummyArgs().size() == 1) {
|
|
|
|
if (const Symbol * arg{details->dummyArgs().at(0)}) {
|
|
|
|
if (const auto *object{arg->detailsIf<ObjectEntityDetails>()}) {
|
|
|
|
if (rank == object->shape().Rank() || object->IsAssumedRank() ||
|
2022-06-30 15:27:28 -07:00
|
|
|
IsElementalProcedure(symbol)) {
|
2020-10-30 13:30:42 -07:00
|
|
|
return &symbol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-07 15:05:53 -08:00
|
|
|
void TypeParamDetails::set_type(const DeclTypeSpec &type) {
|
2019-11-09 09:29:31 -08:00
|
|
|
CHECK(!type_);
|
2019-01-07 15:05:53 -08:00
|
|
|
type_ = &type;
|
|
|
|
}
|
2019-04-04 14:46:40 -07:00
|
|
|
|
2019-11-22 12:40:37 -08:00
|
|
|
bool GenericKind::IsIntrinsicOperator() const {
|
|
|
|
return Is(OtherKind::Concat) || Has<common::LogicalOperator>() ||
|
|
|
|
Has<common::NumericOperator>() || Has<common::RelationalOperator>();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GenericKind::IsOperator() const {
|
|
|
|
return IsDefinedOperator() || IsIntrinsicOperator();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GenericKind::ToString() const {
|
2022-03-23 14:05:50 -07:00
|
|
|
return common::visit(
|
2019-12-02 15:56:00 -08:00
|
|
|
common::visitors {
|
2022-11-10 17:29:29 -08:00
|
|
|
[](const OtherKind &x) { return std::string{EnumToString(x)}; },
|
2023-04-13 10:28:19 -07:00
|
|
|
[](const common::DefinedIo &x) { return AsFortran(x).ToString(); },
|
2019-12-02 15:56:00 -08:00
|
|
|
#if !__clang__ && __GNUC__ == 7 && __GNUC_MINOR__ == 2
|
|
|
|
[](const common::NumericOperator &x) {
|
2022-11-10 17:29:29 -08:00
|
|
|
return std::string{common::EnumToString(x)};
|
2019-12-02 15:56:00 -08:00
|
|
|
},
|
|
|
|
[](const common::LogicalOperator &x) {
|
2022-11-10 17:29:29 -08:00
|
|
|
return std::string{common::EnumToString(x)};
|
2019-12-02 15:56:00 -08:00
|
|
|
},
|
|
|
|
[](const common::RelationalOperator &x) {
|
2022-11-10 17:29:29 -08:00
|
|
|
return std::string{common::EnumToString(x)};
|
2019-12-02 15:56:00 -08:00
|
|
|
},
|
|
|
|
#else
|
2022-11-10 17:29:29 -08:00
|
|
|
[](const auto &x) { return std::string{common::EnumToString(x)}; },
|
2019-12-02 15:56:00 -08:00
|
|
|
#endif
|
2019-11-22 12:40:37 -08:00
|
|
|
},
|
|
|
|
u);
|
|
|
|
}
|
|
|
|
|
2023-04-13 10:28:19 -07:00
|
|
|
SourceName GenericKind::AsFortran(common::DefinedIo x) {
|
|
|
|
const char *name{common::AsFortran(x)};
|
2022-02-11 09:44:47 -08:00
|
|
|
return {name, std::strlen(name)};
|
|
|
|
}
|
|
|
|
|
2019-11-22 12:40:37 -08:00
|
|
|
bool GenericKind::Is(GenericKind::OtherKind x) const {
|
|
|
|
const OtherKind *y{std::get_if<OtherKind>(&u)};
|
|
|
|
return y && *y == x;
|
|
|
|
}
|
|
|
|
|
2023-08-24 04:10:02 -05:00
|
|
|
std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) {
|
|
|
|
std::string clauseName;
|
|
|
|
switch (ompFlag) {
|
|
|
|
case Symbol::Flag::OmpShared:
|
|
|
|
clauseName = "SHARED";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpPrivate:
|
|
|
|
clauseName = "PRIVATE";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpLinear:
|
|
|
|
clauseName = "LINEAR";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpFirstPrivate:
|
|
|
|
clauseName = "FIRSTPRIVATE";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpLastPrivate:
|
|
|
|
clauseName = "LASTPRIVATE";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpMapTo:
|
|
|
|
case Symbol::Flag::OmpMapFrom:
|
|
|
|
case Symbol::Flag::OmpMapToFrom:
|
|
|
|
case Symbol::Flag::OmpMapAlloc:
|
|
|
|
case Symbol::Flag::OmpMapRelease:
|
|
|
|
case Symbol::Flag::OmpMapDelete:
|
|
|
|
clauseName = "MAP";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpUseDevicePtr:
|
|
|
|
clauseName = "USE_DEVICE_PTR";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpUseDeviceAddr:
|
|
|
|
clauseName = "USE_DEVICE_ADDR";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpCopyIn:
|
|
|
|
clauseName = "COPYIN";
|
|
|
|
break;
|
|
|
|
case Symbol::Flag::OmpCopyPrivate:
|
|
|
|
clauseName = "COPYPRIVATE";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
clauseName = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return clauseName;
|
|
|
|
}
|
|
|
|
|
2022-11-02 14:31:14 -07:00
|
|
|
bool SymbolOffsetCompare::operator()(
|
|
|
|
const SymbolRef &x, const SymbolRef &y) const {
|
2021-08-10 10:22:39 -07:00
|
|
|
const Symbol *xCommon{FindCommonBlockContaining(*x)};
|
|
|
|
const Symbol *yCommon{FindCommonBlockContaining(*y)};
|
|
|
|
if (xCommon) {
|
|
|
|
if (yCommon) {
|
|
|
|
const SymbolSourcePositionCompare sourceCmp;
|
|
|
|
if (sourceCmp(*xCommon, *yCommon)) {
|
|
|
|
return true;
|
|
|
|
} else if (sourceCmp(*yCommon, *xCommon)) {
|
|
|
|
return false;
|
|
|
|
} else if (x->offset() == y->offset()) {
|
|
|
|
return x->size() > y->size();
|
|
|
|
} else {
|
|
|
|
return x->offset() < y->offset();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (yCommon) {
|
|
|
|
return true;
|
|
|
|
} else if (x->offset() == y->offset()) {
|
|
|
|
return x->size() > y->size();
|
|
|
|
} else {
|
|
|
|
return x->offset() < y->offset();
|
|
|
|
}
|
|
|
|
return x->GetSemanticsContext().allCookedSources().Precedes(
|
|
|
|
x->name(), y->name());
|
|
|
|
}
|
2022-02-11 09:44:47 -08:00
|
|
|
|
2021-08-10 10:22:39 -07:00
|
|
|
bool SymbolOffsetCompare::operator()(
|
|
|
|
const MutableSymbolRef &x, const MutableSymbolRef &y) const {
|
|
|
|
return (*this)(SymbolRef{*x}, SymbolRef{*y});
|
|
|
|
}
|
|
|
|
|
2020-03-28 21:00:16 -07:00
|
|
|
} // namespace Fortran::semantics
|