2019-01-08 00:42:36 +01:00
|
|
|
// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
|
2018-05-01 21:50:34 +02:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
#ifndef FORTRAN_SEMANTICS_SYMBOL_H_
|
|
|
|
#define FORTRAN_SEMANTICS_SYMBOL_H_
|
|
|
|
|
|
|
|
#include "type.h"
|
2019-02-28 19:48:41 +01:00
|
|
|
#include "../common/Fortran.h"
|
2018-06-22 17:21:19 +02:00
|
|
|
#include "../common/enum-set.h"
|
2018-03-23 01:08:20 +01:00
|
|
|
#include <functional>
|
2018-11-16 21:43:08 +01:00
|
|
|
#include <list>
|
|
|
|
#include <optional>
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
namespace Fortran::semantics {
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
/// A Symbol consists of common information (name, owner, and attributes)
|
|
|
|
/// and details information specific to the kind of symbol, represented by the
|
|
|
|
/// *Details classes.
|
|
|
|
|
|
|
|
class Scope;
|
2019-01-31 18:58:40 +01:00
|
|
|
class SemanticsContext;
|
2018-04-17 23:16:42 +02:00
|
|
|
class Symbol;
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-12-26 22:31:13 +01:00
|
|
|
using SymbolList = std::list<const Symbol *>;
|
|
|
|
|
2018-08-03 01:21:27 +02:00
|
|
|
// A module or submodule.
|
2018-03-23 01:08:20 +01:00
|
|
|
class ModuleDetails {
|
|
|
|
public:
|
2018-08-03 01:21:27 +02:00
|
|
|
ModuleDetails(bool isSubmodule = false) : isSubmodule_{isSubmodule} {}
|
|
|
|
bool isSubmodule() const { return isSubmodule_; }
|
2018-05-04 00:57:56 +02:00
|
|
|
const Scope *scope() const { return scope_; }
|
2018-08-03 01:21:27 +02:00
|
|
|
const Scope *ancestor() const; // for submodule; nullptr for module
|
|
|
|
const Scope *parent() const; // for submodule; nullptr for module
|
|
|
|
void set_scope(const Scope *);
|
2018-05-04 00:57:56 +02:00
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
private:
|
2018-08-03 01:21:27 +02:00
|
|
|
bool isSubmodule_;
|
2018-05-04 00:57:56 +02:00
|
|
|
const Scope *scope_{nullptr};
|
2018-03-23 01:08:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class MainProgramDetails {
|
|
|
|
public:
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
|
|
class SubprogramDetails {
|
|
|
|
public:
|
2018-04-11 22:11:42 +02:00
|
|
|
SubprogramDetails() {}
|
2018-04-17 23:16:42 +02:00
|
|
|
SubprogramDetails(const SubprogramDetails &that)
|
|
|
|
: dummyArgs_{that.dummyArgs_}, result_{that.result_} {}
|
|
|
|
|
2019-03-20 21:52:33 +01:00
|
|
|
bool isFunction() const { return result_ != nullptr; }
|
2018-05-14 22:51:13 +02:00
|
|
|
bool isInterface() const { return isInterface_; }
|
|
|
|
void set_isInterface(bool value = true) { isInterface_ = value; }
|
2019-01-05 02:10:31 +01:00
|
|
|
MaybeExpr bindName() const { return bindName_; }
|
|
|
|
void set_bindName(MaybeExpr &&expr) { bindName_ = std::move(expr); }
|
2018-05-02 23:06:02 +02:00
|
|
|
const Symbol &result() const {
|
|
|
|
CHECK(isFunction());
|
2019-03-20 21:52:33 +01:00
|
|
|
return *result_;
|
2018-05-02 23:06:02 +02:00
|
|
|
}
|
2018-04-17 23:16:42 +02:00
|
|
|
void set_result(Symbol &result) {
|
2019-03-20 21:52:33 +01:00
|
|
|
CHECK(result_ == nullptr);
|
2018-04-17 23:16:42 +02:00
|
|
|
result_ = &result;
|
|
|
|
}
|
|
|
|
const std::list<Symbol *> &dummyArgs() const { return dummyArgs_; }
|
|
|
|
void add_dummyArg(Symbol &symbol) { dummyArgs_.push_back(&symbol); }
|
2019-06-03 22:36:47 +02:00
|
|
|
void add_alternateReturn() { dummyArgs_.push_back(nullptr); }
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
private:
|
2019-01-05 02:10:31 +01:00
|
|
|
bool isInterface_{false}; // true if this represents an interface-body
|
|
|
|
MaybeExpr bindName_;
|
2019-06-03 22:36:47 +02:00
|
|
|
std::list<Symbol *> dummyArgs_; // nullptr -> alternate return indicator
|
2019-03-20 21:52:33 +01:00
|
|
|
Symbol *result_{nullptr};
|
2018-03-23 01:08:20 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const SubprogramDetails &);
|
|
|
|
};
|
|
|
|
|
2018-05-14 22:51:13 +02:00
|
|
|
// For SubprogramNameDetails, the kind indicates whether it is the name
|
|
|
|
// of a module subprogram or internal subprogram.
|
|
|
|
ENUM_CLASS(SubprogramKind, Module, Internal)
|
|
|
|
|
|
|
|
// Symbol with SubprogramNameDetails is created when we scan for module and
|
|
|
|
// internal procedure names, to record that there is a subprogram with this
|
|
|
|
// name. Later they are replaced by SubprogramDetails with dummy and result
|
|
|
|
// type information.
|
|
|
|
class SubprogramNameDetails {
|
|
|
|
public:
|
|
|
|
SubprogramNameDetails(SubprogramKind kind) : kind_{kind} {}
|
|
|
|
SubprogramNameDetails() = delete;
|
|
|
|
SubprogramKind kind() const { return kind_; }
|
2018-06-14 22:43:02 +02:00
|
|
|
|
2018-05-14 22:51:13 +02:00
|
|
|
private:
|
|
|
|
SubprogramKind kind_;
|
|
|
|
};
|
|
|
|
|
2018-06-05 21:18:35 +02:00
|
|
|
// A name from an entity-decl -- could be object or function.
|
2018-03-23 01:08:20 +01:00
|
|
|
class EntityDetails {
|
|
|
|
public:
|
2019-01-18 01:14:36 +01:00
|
|
|
explicit EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type() const { return type_; }
|
2019-01-05 02:10:31 +01:00
|
|
|
void set_type(const DeclTypeSpec &);
|
|
|
|
void ReplaceType(const DeclTypeSpec &);
|
2018-06-05 21:18:35 +02:00
|
|
|
bool isDummy() const { return isDummy_; }
|
2019-02-21 02:45:39 +01:00
|
|
|
bool isFuncResult() const { return isFuncResult_; }
|
|
|
|
void set_funcResult(bool x) { isFuncResult_ = x; }
|
2019-01-05 02:10:31 +01:00
|
|
|
MaybeExpr bindName() const { return bindName_; }
|
|
|
|
void set_bindName(MaybeExpr &&expr) { bindName_ = std::move(expr); }
|
2018-06-05 21:18:35 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool isDummy_;
|
2019-02-21 02:45:39 +01:00
|
|
|
bool isFuncResult_{false};
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type_{nullptr};
|
2019-01-05 02:10:31 +01:00
|
|
|
MaybeExpr bindName_;
|
2018-06-05 21:18:35 +02:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const EntityDetails &);
|
|
|
|
};
|
|
|
|
|
2019-01-16 01:59:20 +01:00
|
|
|
// Symbol is associated with a name or expression in a SELECT TYPE or ASSOCIATE.
|
|
|
|
class AssocEntityDetails : public EntityDetails {
|
|
|
|
public:
|
2019-01-18 01:14:36 +01:00
|
|
|
AssocEntityDetails() {}
|
|
|
|
explicit AssocEntityDetails(SomeExpr &&expr) : expr_{std::move(expr)} {}
|
|
|
|
AssocEntityDetails(const AssocEntityDetails &) = default;
|
|
|
|
AssocEntityDetails(AssocEntityDetails &&) = default;
|
|
|
|
AssocEntityDetails &operator=(const AssocEntityDetails &) = default;
|
|
|
|
AssocEntityDetails &operator=(AssocEntityDetails &&) = default;
|
|
|
|
const MaybeExpr &expr() const { return expr_; }
|
2019-01-16 01:59:20 +01:00
|
|
|
|
|
|
|
private:
|
2019-01-18 01:14:36 +01:00
|
|
|
MaybeExpr expr_;
|
2019-01-16 01:59:20 +01:00
|
|
|
};
|
|
|
|
|
2018-06-05 21:18:35 +02:00
|
|
|
// An entity known to be an object.
|
2019-01-05 02:10:31 +01:00
|
|
|
class ObjectEntityDetails : public EntityDetails {
|
2018-06-05 21:18:35 +02:00
|
|
|
public:
|
2019-01-05 02:10:31 +01:00
|
|
|
explicit ObjectEntityDetails(EntityDetails &&);
|
2019-01-08 00:05:53 +01:00
|
|
|
ObjectEntityDetails(const ObjectEntityDetails &) = default;
|
|
|
|
ObjectEntityDetails &operator=(const ObjectEntityDetails &) = default;
|
2019-01-05 02:10:31 +01:00
|
|
|
ObjectEntityDetails(bool isDummy = false) : EntityDetails(isDummy) {}
|
2018-12-06 15:59:37 +01:00
|
|
|
MaybeExpr &init() { return init_; }
|
|
|
|
const MaybeExpr &init() const { return init_; }
|
|
|
|
void set_init(MaybeExpr &&expr) { init_ = std::move(expr); }
|
2019-05-22 01:58:46 +02:00
|
|
|
bool initWasValidated() const { return initWasValidated_; }
|
|
|
|
void set_initWasValidated(bool yes = true) { initWasValidated_ = yes; }
|
2018-11-07 02:18:06 +01:00
|
|
|
ArraySpec &shape() { return shape_; }
|
2018-04-12 21:59:42 +02:00
|
|
|
const ArraySpec &shape() const { return shape_; }
|
2019-04-04 23:46:40 +02:00
|
|
|
ArraySpec &coshape() { return coshape_; }
|
|
|
|
const ArraySpec &coshape() const { return coshape_; }
|
|
|
|
void set_shape(const ArraySpec &);
|
|
|
|
void set_coshape(const ArraySpec &);
|
2019-04-12 00:20:14 +02:00
|
|
|
const Symbol *commonBlock() const { return commonBlock_; }
|
|
|
|
void set_commonBlock(const Symbol &commonBlock) {
|
|
|
|
commonBlock_ = &commonBlock;
|
|
|
|
}
|
2018-12-11 23:03:55 +01:00
|
|
|
bool IsArray() const { return !shape_.empty(); }
|
2019-04-04 23:46:40 +02:00
|
|
|
bool IsCoarray() const { return !coshape_.empty(); }
|
2019-01-08 00:05:53 +01:00
|
|
|
bool IsAssumedShape() const {
|
|
|
|
return isDummy() && IsArray() && shape_.back().ubound().isDeferred() &&
|
|
|
|
!shape_.back().lbound().isDeferred();
|
|
|
|
}
|
|
|
|
bool IsDeferredShape() const {
|
|
|
|
return !isDummy() && IsArray() && shape_.back().ubound().isDeferred() &&
|
|
|
|
shape_.back().lbound().isDeferred();
|
|
|
|
}
|
2018-10-29 23:25:35 +01:00
|
|
|
bool IsAssumedSize() const {
|
2018-12-11 23:03:55 +01:00
|
|
|
return isDummy() && IsArray() && shape_.back().ubound().isAssumed() &&
|
2018-09-18 20:59:25 +02:00
|
|
|
!shape_.back().lbound().isAssumed();
|
|
|
|
}
|
2018-10-29 23:25:35 +01:00
|
|
|
bool IsAssumedRank() const {
|
2018-12-11 23:03:55 +01:00
|
|
|
return isDummy() && IsArray() && shape_.back().ubound().isAssumed() &&
|
2018-10-29 23:25:35 +01:00
|
|
|
shape_.back().lbound().isAssumed();
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
private:
|
2018-12-06 15:59:37 +01:00
|
|
|
MaybeExpr init_;
|
2019-05-22 01:58:46 +02:00
|
|
|
bool initWasValidated_{false};
|
2018-04-12 21:59:42 +02:00
|
|
|
ArraySpec shape_;
|
2019-04-04 23:46:40 +02:00
|
|
|
ArraySpec coshape_;
|
2019-03-29 23:04:17 +01:00
|
|
|
const Symbol *commonBlock_{nullptr}; // common block this object is in
|
2018-06-05 21:18:35 +02:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const ObjectEntityDetails &);
|
|
|
|
};
|
|
|
|
|
2019-06-22 19:00:18 +02:00
|
|
|
// Mixin for details with passed-object dummy argument.
|
|
|
|
class WithPassArg {
|
|
|
|
public:
|
|
|
|
const SourceName *passName() const { return passName_; }
|
|
|
|
void set_passName(const SourceName &passName) { passName_ = &passName; }
|
|
|
|
const Symbol *passArg() const { return passArg_; }
|
|
|
|
void set_passArg(const Symbol *passArg) { passArg_ = passArg; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
const SourceName *passName_{nullptr};
|
|
|
|
const Symbol *passArg_{nullptr};
|
|
|
|
};
|
|
|
|
|
2018-06-05 21:18:35 +02:00
|
|
|
// A procedure pointer, dummy procedure, or external procedure
|
2019-06-22 19:00:18 +02:00
|
|
|
class ProcEntityDetails : public EntityDetails, public WithPassArg {
|
2018-06-05 21:18:35 +02:00
|
|
|
public:
|
|
|
|
ProcEntityDetails() = default;
|
2019-01-18 01:14:36 +01:00
|
|
|
explicit ProcEntityDetails(EntityDetails &&d);
|
2018-06-05 21:18:35 +02:00
|
|
|
|
|
|
|
const ProcInterface &interface() const { return interface_; }
|
|
|
|
ProcInterface &interface() { return interface_; }
|
2018-07-28 23:10:34 +02:00
|
|
|
void set_interface(const ProcInterface &interface) { interface_ = interface; }
|
2019-01-19 00:53:11 +01:00
|
|
|
inline bool HasExplicitInterface() const;
|
2018-06-05 21:18:35 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
ProcInterface interface_;
|
|
|
|
friend std::ostream &operator<<(std::ostream &, const ProcEntityDetails &);
|
2018-03-23 01:08:20 +01:00
|
|
|
};
|
|
|
|
|
2019-02-05 19:48:26 +01:00
|
|
|
// These derived type details represent the characteristics of a derived
|
|
|
|
// type definition that are shared by all instantiations of that type.
|
|
|
|
// The DerivedTypeSpec instances whose type symbols share these details
|
|
|
|
// each own a scope into which the components' symbols have been cloned
|
|
|
|
// and specialized for each distinct set of type parameter values.
|
2018-09-04 19:28:27 +02:00
|
|
|
class DerivedTypeDetails {
|
|
|
|
public:
|
2018-12-07 02:52:43 +01:00
|
|
|
const std::list<SourceName> ¶mNames() const { return paramNames_; }
|
2019-02-05 19:48:26 +01:00
|
|
|
const SymbolList ¶mDecls() const { return paramDecls_; }
|
2018-09-06 17:01:49 +02:00
|
|
|
bool sequence() const { return sequence_; }
|
2019-02-05 19:48:26 +01:00
|
|
|
void add_paramName(const SourceName &name) { paramNames_.push_back(name); }
|
|
|
|
void add_paramDecl(const Symbol &symbol) { paramDecls_.push_back(&symbol); }
|
|
|
|
void add_component(const Symbol &);
|
2018-09-06 17:01:49 +02:00
|
|
|
void set_sequence(bool x = true) { sequence_ = x; }
|
2018-09-04 19:28:27 +02:00
|
|
|
|
2019-01-08 00:05:53 +01:00
|
|
|
// Returns the complete list of derived type parameter names in the
|
|
|
|
// order defined by 7.5.3.2.
|
|
|
|
std::list<SourceName> OrderParameterNames(const Symbol &) const;
|
|
|
|
|
|
|
|
// Returns the complete list of derived type parameter symbols in
|
|
|
|
// the order in which their declarations appear in the derived type
|
|
|
|
// definitions (parents first).
|
2019-02-05 19:48:26 +01:00
|
|
|
SymbolList OrderParameterDeclarations(const Symbol &) const;
|
|
|
|
|
|
|
|
// Returns the complete list of derived type components in the order
|
|
|
|
// in which their declarations appear in the derived type definitions
|
|
|
|
// (parents first). Parent components appear in the list immediately
|
|
|
|
// after the components that belong to them.
|
|
|
|
SymbolList OrderComponents(const Scope &) const;
|
|
|
|
|
2019-03-11 23:39:11 +01:00
|
|
|
// If this derived type extends another, locate the parent component's symbol.
|
2019-02-05 19:48:26 +01:00
|
|
|
const Symbol *GetParentComponent(const Scope &) const;
|
2019-01-08 00:05:53 +01:00
|
|
|
|
2019-05-03 20:29:15 +02:00
|
|
|
std::optional<SourceName> GetParentComponentName() const {
|
|
|
|
if (componentNames_.empty()) {
|
|
|
|
return std::nullopt;
|
|
|
|
} else {
|
|
|
|
return componentNames_.front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-04 19:28:27 +02:00
|
|
|
private:
|
2019-02-04 21:24:25 +01:00
|
|
|
// These are (1) the names of the derived type parameters in the order
|
|
|
|
// in which they appear on the type definition statement(s), and (2) the
|
|
|
|
// symbols that correspond to those names in the order in which their
|
|
|
|
// declarations appear in the derived type definition(s).
|
2018-12-07 02:52:43 +01:00
|
|
|
std::list<SourceName> paramNames_;
|
2019-02-05 19:48:26 +01:00
|
|
|
SymbolList paramDecls_;
|
|
|
|
// These are the names of the derived type's components in component
|
2019-02-04 21:24:25 +01:00
|
|
|
// order. A parent component, if any, appears first in this list.
|
2019-02-18 22:47:34 +01:00
|
|
|
std::list<SourceName> componentNames_;
|
2018-09-06 17:01:49 +02:00
|
|
|
bool sequence_{false};
|
2019-02-05 19:48:26 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const DerivedTypeDetails &);
|
2018-09-04 19:28:27 +02:00
|
|
|
};
|
2018-06-22 17:21:19 +02:00
|
|
|
|
2019-06-22 19:00:18 +02:00
|
|
|
class ProcBindingDetails : public WithPassArg {
|
2018-09-01 01:20:00 +02:00
|
|
|
public:
|
2019-01-08 00:05:53 +01:00
|
|
|
explicit ProcBindingDetails(const Symbol &symbol) : symbol_{&symbol} {}
|
2018-09-01 01:20:00 +02:00
|
|
|
const Symbol &symbol() const { return *symbol_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
const Symbol *symbol_; // procedure bound to
|
|
|
|
};
|
|
|
|
|
2019-04-12 00:20:14 +02:00
|
|
|
ENUM_CLASS(GenericKind, // Kinds of generic-spec
|
2019-03-18 19:48:02 +01:00
|
|
|
Name, DefinedOp, // these have a Name associated with them
|
|
|
|
Assignment, // user-defined assignment
|
|
|
|
OpPower, OpMultiply, OpDivide, OpAdd, OpSubtract, OpConcat, OpLT, OpLE,
|
|
|
|
OpEQ, OpNE, OpGE, OpGT, OpNOT, OpAND, OpOR, OpXOR, OpEQV, OpNEQV,
|
|
|
|
ReadFormatted, ReadUnformatted, WriteFormatted, WriteUnformatted)
|
|
|
|
|
2018-12-26 22:31:13 +01:00
|
|
|
class GenericBindingDetails {
|
|
|
|
public:
|
|
|
|
GenericBindingDetails() {}
|
2019-03-18 19:48:02 +01:00
|
|
|
GenericKind kind() const { return kind_; }
|
|
|
|
void set_kind(GenericKind kind) { kind_ = kind; }
|
2018-12-26 22:31:13 +01:00
|
|
|
const SymbolList &specificProcs() const { return specificProcs_; }
|
|
|
|
void add_specificProc(const Symbol &proc) { specificProcs_.push_back(&proc); }
|
|
|
|
void add_specificProcs(const SymbolList &procs) {
|
|
|
|
specificProcs_.insert(specificProcs_.end(), procs.begin(), procs.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-03-18 19:48:02 +01:00
|
|
|
GenericKind kind_{GenericKind::Name};
|
2018-12-26 22:31:13 +01:00
|
|
|
SymbolList specificProcs_;
|
|
|
|
};
|
2018-09-01 01:20:00 +02:00
|
|
|
|
2019-02-05 23:43:00 +01:00
|
|
|
class NamelistDetails {
|
|
|
|
public:
|
|
|
|
const SymbolList &objects() const { return objects_; }
|
|
|
|
void add_object(const Symbol &object) { objects_.push_back(&object); }
|
|
|
|
void add_objects(const SymbolList &objects) {
|
|
|
|
objects_.insert(objects_.end(), objects.begin(), objects.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SymbolList objects_;
|
|
|
|
};
|
|
|
|
|
2019-02-14 16:59:20 +01:00
|
|
|
class CommonBlockDetails {
|
|
|
|
public:
|
2019-02-21 02:45:39 +01:00
|
|
|
std::list<Symbol *> &objects() { return objects_; }
|
|
|
|
const std::list<Symbol *> &objects() const { return objects_; }
|
2019-02-14 16:59:20 +01:00
|
|
|
void add_object(Symbol &object) { objects_.push_back(&object); }
|
2019-02-18 20:39:46 +01:00
|
|
|
MaybeExpr bindName() const { return bindName_; }
|
|
|
|
void set_bindName(MaybeExpr &&expr) { bindName_ = std::move(expr); }
|
2019-02-14 16:59:20 +01:00
|
|
|
|
|
|
|
private:
|
2019-02-21 02:45:39 +01:00
|
|
|
std::list<Symbol *> objects_;
|
2019-02-18 20:39:46 +01:00
|
|
|
MaybeExpr bindName_;
|
2019-02-14 16:59:20 +01:00
|
|
|
};
|
|
|
|
|
2018-09-01 01:20:00 +02:00
|
|
|
class FinalProcDetails {};
|
|
|
|
|
2018-09-25 17:53:53 +02:00
|
|
|
class MiscDetails {
|
|
|
|
public:
|
2019-01-07 22:31:50 +01:00
|
|
|
ENUM_CLASS(Kind, None, ConstructName, ScopeName, PassName, ComplexPartRe,
|
2019-02-23 00:45:30 +01:00
|
|
|
ComplexPartIm, KindParamInquiry, LenParamInquiry, SelectTypeAssociateName,
|
|
|
|
SpecificIntrinsic);
|
2018-09-25 17:53:53 +02:00
|
|
|
MiscDetails(Kind kind) : kind_{kind} {}
|
|
|
|
Kind kind() const { return kind_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Kind kind_;
|
|
|
|
};
|
|
|
|
|
2018-09-04 19:28:27 +02:00
|
|
|
class TypeParamDetails {
|
|
|
|
public:
|
2019-01-08 00:05:53 +01:00
|
|
|
explicit TypeParamDetails(common::TypeParamAttr attr) : attr_{attr} {}
|
|
|
|
TypeParamDetails(const TypeParamDetails &) = default;
|
2018-09-06 01:02:41 +02:00
|
|
|
common::TypeParamAttr attr() const { return attr_; }
|
2019-01-08 00:05:53 +01:00
|
|
|
MaybeIntExpr &init() { return init_; }
|
|
|
|
const MaybeIntExpr &init() const { return init_; }
|
|
|
|
void set_init(MaybeIntExpr &&expr) { init_ = std::move(expr); }
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type() const { return type_; }
|
2019-01-08 00:05:53 +01:00
|
|
|
void set_type(const DeclTypeSpec &);
|
2019-01-05 02:10:31 +01:00
|
|
|
void ReplaceType(const DeclTypeSpec &);
|
2018-09-04 19:28:27 +02:00
|
|
|
|
|
|
|
private:
|
2018-09-06 01:02:41 +02:00
|
|
|
common::TypeParamAttr attr_;
|
2019-01-08 00:05:53 +01:00
|
|
|
MaybeIntExpr init_;
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type_{nullptr};
|
2018-09-04 19:28:27 +02:00
|
|
|
};
|
|
|
|
|
2018-05-04 00:57:56 +02:00
|
|
|
// Record the USE of a symbol: location is where (USE statement or renaming);
|
|
|
|
// symbol is the USEd module.
|
|
|
|
class UseDetails {
|
|
|
|
public:
|
|
|
|
UseDetails(const SourceName &location, const Symbol &symbol)
|
2018-11-16 21:43:08 +01:00
|
|
|
: location_{location}, symbol_{&symbol} {}
|
|
|
|
const SourceName &location() const { return location_; }
|
2018-05-04 00:57:56 +02:00
|
|
|
const Symbol &symbol() const { return *symbol_; }
|
|
|
|
const Symbol &module() const;
|
|
|
|
|
|
|
|
private:
|
2018-11-16 21:43:08 +01:00
|
|
|
SourceName location_;
|
2018-05-04 00:57:56 +02:00
|
|
|
const Symbol *symbol_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A symbol with ambiguous use-associations. Record where they were so
|
|
|
|
// we can report the error if it is used.
|
|
|
|
class UseErrorDetails {
|
|
|
|
public:
|
2018-08-29 20:38:12 +02:00
|
|
|
UseErrorDetails(const UseDetails &);
|
|
|
|
UseErrorDetails &add_occurrence(const SourceName &, const Scope &);
|
2018-11-16 21:43:08 +01:00
|
|
|
using listType = std::list<std::pair<SourceName, const Scope *>>;
|
2018-05-04 00:57:56 +02:00
|
|
|
const listType occurrences() const { return occurrences_; };
|
|
|
|
|
|
|
|
private:
|
|
|
|
listType occurrences_;
|
|
|
|
};
|
|
|
|
|
2018-10-18 16:55:48 +02:00
|
|
|
// A symbol host-associated from an enclosing scope.
|
|
|
|
class HostAssocDetails {
|
|
|
|
public:
|
|
|
|
HostAssocDetails(const Symbol &symbol) : symbol_{&symbol} {}
|
|
|
|
const Symbol &symbol() const { return *symbol_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
const Symbol *symbol_;
|
|
|
|
};
|
|
|
|
|
2018-05-14 22:51:13 +02:00
|
|
|
class GenericDetails {
|
|
|
|
public:
|
2018-05-23 01:12:56 +02:00
|
|
|
GenericDetails() {}
|
2018-12-26 22:31:13 +01:00
|
|
|
GenericDetails(const SymbolList &specificProcs);
|
2018-06-20 01:06:41 +02:00
|
|
|
GenericDetails(Symbol *specific) : specific_{specific} {}
|
2018-05-14 22:51:13 +02:00
|
|
|
|
2019-03-18 19:48:02 +01:00
|
|
|
GenericKind kind() const { return kind_; }
|
|
|
|
void set_kind(GenericKind kind) { kind_ = kind; }
|
2018-07-20 19:46:11 +02:00
|
|
|
|
2019-03-18 19:48:02 +01:00
|
|
|
const SymbolList specificProcs() const { return specificProcs_; }
|
2018-12-26 22:31:13 +01:00
|
|
|
void add_specificProc(const Symbol &proc) { specificProcs_.push_back(&proc); }
|
2018-05-14 22:51:13 +02:00
|
|
|
|
2018-06-20 01:06:41 +02:00
|
|
|
Symbol *specific() { return specific_; }
|
2019-02-26 22:08:59 +01:00
|
|
|
const Symbol *specific() const { return specific_; }
|
2018-06-22 17:21:19 +02:00
|
|
|
void set_specific(Symbol &specific);
|
|
|
|
|
|
|
|
// Derived type with same name as generic, if any.
|
|
|
|
Symbol *derivedType() { return derivedType_; }
|
|
|
|
const Symbol *derivedType() const { return derivedType_; }
|
|
|
|
void set_derivedType(Symbol &derivedType);
|
2018-05-23 01:12:56 +02:00
|
|
|
|
|
|
|
// Check that specific is one of the specificProcs. If not, return the
|
|
|
|
// specific as a raw pointer.
|
|
|
|
const Symbol *CheckSpecific() const;
|
2019-04-25 22:18:33 +02:00
|
|
|
Symbol *CheckSpecific();
|
2018-05-14 22:51:13 +02:00
|
|
|
|
|
|
|
private:
|
2019-03-18 19:48:02 +01:00
|
|
|
GenericKind kind_{GenericKind::Name};
|
2018-05-23 01:12:56 +02:00
|
|
|
// all of the specific procedures for this generic
|
2018-12-26 22:31:13 +01:00
|
|
|
SymbolList specificProcs_;
|
2018-05-23 01:12:56 +02:00
|
|
|
// a specific procedure with the same name as this generic, if any
|
2018-06-20 01:06:41 +02:00
|
|
|
Symbol *specific_{nullptr};
|
2018-06-22 17:21:19 +02:00
|
|
|
// a derived type with the same name as this generic, if any
|
|
|
|
Symbol *derivedType_{nullptr};
|
2018-05-14 22:51:13 +02:00
|
|
|
};
|
|
|
|
|
2018-03-23 20:24:29 +01:00
|
|
|
class UnknownDetails {};
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-05-04 00:57:56 +02:00
|
|
|
using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
|
2018-06-14 22:43:02 +02:00
|
|
|
SubprogramDetails, SubprogramNameDetails, EntityDetails,
|
2019-01-16 01:59:20 +01:00
|
|
|
ObjectEntityDetails, ProcEntityDetails, AssocEntityDetails,
|
|
|
|
DerivedTypeDetails, UseDetails, UseErrorDetails, HostAssocDetails,
|
2019-02-05 23:43:00 +01:00
|
|
|
GenericDetails, ProcBindingDetails, GenericBindingDetails, NamelistDetails,
|
2019-02-14 16:59:20 +01:00
|
|
|
CommonBlockDetails, FinalProcDetails, TypeParamDetails, MiscDetails>;
|
2018-05-04 00:57:56 +02:00
|
|
|
std::ostream &operator<<(std::ostream &, const Details &);
|
2018-07-19 22:28:24 +02:00
|
|
|
std::string DetailsToString(const Details &);
|
2018-05-04 00:57:56 +02:00
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
class Symbol {
|
|
|
|
public:
|
2018-09-20 23:08:59 +02:00
|
|
|
ENUM_CLASS(Flag,
|
2019-04-25 22:18:33 +02:00
|
|
|
Error, // an error has been reported on this symbol
|
2018-09-20 23:08:59 +02:00
|
|
|
Function, // symbol is a function
|
|
|
|
Subroutine, // symbol is a subroutine
|
2018-09-20 23:21:04 +02:00
|
|
|
Implicit, // symbol is implicitly typed
|
2018-09-20 23:08:59 +02:00
|
|
|
ModFile, // symbol came from .mod file
|
2018-10-18 16:55:48 +02:00
|
|
|
ParentComp, // symbol is the "parent component" of an extended type
|
|
|
|
LocalityLocal, // named in LOCAL locality-spec
|
|
|
|
LocalityLocalInit, // named in LOCAL_INIT locality-spec
|
|
|
|
LocalityShared // named in SHARED locality-spec
|
2018-09-20 23:08:59 +02:00
|
|
|
);
|
2018-06-14 22:43:02 +02:00
|
|
|
using Flags = common::EnumSet<Flag, Flag_enumSize>;
|
2018-06-05 21:18:35 +02:00
|
|
|
|
2018-06-20 01:06:41 +02:00
|
|
|
const Scope &owner() const { return *owner_; }
|
2018-11-16 21:43:08 +01:00
|
|
|
const SourceName &name() const { return name_; }
|
2018-03-30 22:57:23 +02:00
|
|
|
Attrs &attrs() { return attrs_; }
|
2018-03-23 01:08:20 +01:00
|
|
|
const Attrs &attrs() const { return attrs_; }
|
2018-06-05 21:18:35 +02:00
|
|
|
Flags &flags() { return flags_; }
|
|
|
|
const Flags &flags() const { return flags_; }
|
|
|
|
bool test(Flag flag) const { return flags_.test(flag); }
|
|
|
|
void set(Flag flag, bool value = true) { flags_.set(flag, value); }
|
2018-06-22 17:21:19 +02:00
|
|
|
// The Scope introduced by this symbol, if any.
|
|
|
|
Scope *scope() { return scope_; }
|
|
|
|
const Scope *scope() const { return scope_; }
|
|
|
|
void set_scope(Scope *scope) { scope_ = scope; }
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
// Does symbol have this type of details?
|
|
|
|
template<typename D> bool has() const {
|
|
|
|
return std::holds_alternative<D>(details_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return a non-owning pointer to details if it is type D, else nullptr.
|
|
|
|
template<typename D> D *detailsIf() { return std::get_if<D>(&details_); }
|
2018-04-11 22:11:42 +02:00
|
|
|
template<typename D> const D *detailsIf() const {
|
|
|
|
return std::get_if<D>(&details_);
|
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
// Return a reference to the details which must be of type D.
|
2018-07-17 01:23:18 +02:00
|
|
|
template<typename D> D &get() {
|
2019-01-19 00:53:11 +01:00
|
|
|
return const_cast<D &>(const_cast<const Symbol *>(this)->get<D>());
|
2018-03-23 01:08:20 +01:00
|
|
|
}
|
2018-07-17 01:23:18 +02:00
|
|
|
template<typename D> const D &get() const {
|
2019-01-19 00:53:11 +01:00
|
|
|
const auto *p{detailsIf<D>()};
|
|
|
|
CHECK(p != nullptr);
|
|
|
|
return *p;
|
2018-03-23 01:08:20 +01:00
|
|
|
}
|
|
|
|
|
2019-01-05 02:10:31 +01:00
|
|
|
Details &details() { return details_; }
|
2018-07-17 01:23:18 +02:00
|
|
|
const Details &details() const { return details_; }
|
2018-03-23 01:08:20 +01:00
|
|
|
// Assign the details of the symbol from one of the variants.
|
2018-05-04 00:57:56 +02:00
|
|
|
// Only allowed in certain cases.
|
2018-11-05 23:36:11 +01:00
|
|
|
void set_details(Details &&);
|
2018-05-14 22:51:13 +02:00
|
|
|
|
|
|
|
// Can the details of this symbol be replaced with the given details?
|
|
|
|
bool CanReplaceDetails(const Details &details) const;
|
2018-03-23 01:08:20 +01:00
|
|
|
|
2018-05-04 00:57:56 +02:00
|
|
|
// Follow use-associations to get the ultimate entity.
|
2018-05-23 01:12:56 +02:00
|
|
|
Symbol &GetUltimate();
|
2018-05-04 00:57:56 +02:00
|
|
|
const Symbol &GetUltimate() const;
|
|
|
|
|
2019-01-19 00:53:11 +01:00
|
|
|
DeclTypeSpec *GetType() {
|
|
|
|
return const_cast<DeclTypeSpec *>(
|
|
|
|
const_cast<const Symbol *>(this)->GetType());
|
|
|
|
}
|
|
|
|
const DeclTypeSpec *GetType() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](const EntityDetails &x) { return x.type(); },
|
|
|
|
[](const ObjectEntityDetails &x) { return x.type(); },
|
|
|
|
[](const AssocEntityDetails &x) { return x.type(); },
|
2019-04-17 16:42:16 +02:00
|
|
|
[](const SubprogramDetails &x) {
|
|
|
|
return x.isFunction() ? x.result().GetType() : nullptr;
|
|
|
|
},
|
2019-03-11 23:39:11 +01:00
|
|
|
[](const ProcEntityDetails &x) {
|
|
|
|
if (const Symbol * symbol{x.interface().symbol()}) {
|
|
|
|
return symbol->GetType();
|
|
|
|
} else {
|
|
|
|
return x.interface().type();
|
|
|
|
}
|
|
|
|
},
|
2019-01-19 00:53:11 +01:00
|
|
|
[](const TypeParamDetails &x) { return x.type(); },
|
2019-01-31 22:18:30 +01:00
|
|
|
[](const UseDetails &x) { return x.symbol().GetType(); },
|
2019-01-19 00:53:11 +01:00
|
|
|
[](const auto &) -> const DeclTypeSpec * { return nullptr; },
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2018-06-27 00:01:42 +02:00
|
|
|
void SetType(const DeclTypeSpec &);
|
|
|
|
|
2019-02-21 02:45:39 +01:00
|
|
|
bool IsDummy() const;
|
|
|
|
bool IsFuncResult() const;
|
2019-02-07 21:25:59 +01:00
|
|
|
bool IsObjectArray() const;
|
2018-10-26 20:57:08 +02:00
|
|
|
bool IsSubprogram() const;
|
|
|
|
bool IsSeparateModuleProc() const;
|
2019-01-19 00:53:11 +01:00
|
|
|
bool HasExplicitInterface() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](const SubprogramDetails &) { return true; },
|
|
|
|
[](const SubprogramNameDetails &) { return true; },
|
|
|
|
[](const ProcEntityDetails &x) { return x.HasExplicitInterface(); },
|
|
|
|
[](const UseDetails &x) {
|
|
|
|
return x.symbol().HasExplicitInterface();
|
|
|
|
},
|
2019-02-23 00:45:30 +01:00
|
|
|
[](const MiscDetails &x) {
|
|
|
|
return x.kind() == MiscDetails::Kind::SpecificIntrinsic;
|
|
|
|
},
|
2019-01-19 00:53:11 +01:00
|
|
|
[](const auto &) { return false; },
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
2018-05-14 22:51:13 +02:00
|
|
|
|
2018-05-04 00:57:56 +02:00
|
|
|
bool operator==(const Symbol &that) const { return this == &that; }
|
|
|
|
bool operator!=(const Symbol &that) const { return this != &that; }
|
|
|
|
|
2019-01-19 00:53:11 +01:00
|
|
|
int Rank() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](const SubprogramDetails &sd) {
|
2019-04-04 23:46:40 +02:00
|
|
|
return sd.isFunction() ? sd.result().Rank() : 0;
|
2019-01-19 00:53:11 +01:00
|
|
|
},
|
|
|
|
[](const GenericDetails &) {
|
|
|
|
return 0; /*TODO*/
|
|
|
|
},
|
|
|
|
[](const UseDetails &x) { return x.symbol().Rank(); },
|
|
|
|
[](const HostAssocDetails &x) { return x.symbol().Rank(); },
|
|
|
|
[](const ObjectEntityDetails &oed) {
|
|
|
|
return static_cast<int>(oed.shape().size());
|
|
|
|
},
|
2019-05-13 18:33:18 +02:00
|
|
|
[](const AssocEntityDetails &aed) {
|
|
|
|
if (const auto &expr{aed.expr()}) {
|
|
|
|
return expr->Rank();
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
},
|
2019-01-19 00:53:11 +01:00
|
|
|
[](const auto &) { return 0; },
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
2018-09-18 18:34:59 +02:00
|
|
|
|
2019-04-04 23:46:40 +02:00
|
|
|
int Corank() const {
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](const SubprogramDetails &sd) {
|
|
|
|
return sd.isFunction() ? sd.result().Corank() : 0;
|
|
|
|
},
|
|
|
|
[](const GenericDetails &) {
|
|
|
|
return 0; /*TODO*/
|
|
|
|
},
|
|
|
|
[](const UseDetails &x) { return x.symbol().Corank(); },
|
|
|
|
[](const HostAssocDetails &x) { return x.symbol().Corank(); },
|
|
|
|
[](const ObjectEntityDetails &oed) {
|
|
|
|
return static_cast<int>(oed.coshape().size());
|
|
|
|
},
|
|
|
|
[](const auto &) { return 0; },
|
|
|
|
},
|
|
|
|
details_);
|
|
|
|
}
|
|
|
|
|
2019-01-08 00:05:53 +01:00
|
|
|
// Clones the Symbol in the context of a parameterized derived type instance
|
2019-01-31 18:58:40 +01:00
|
|
|
Symbol &Instantiate(Scope &, SemanticsContext &) const;
|
2019-01-08 00:05:53 +01:00
|
|
|
|
2019-03-11 23:39:11 +01:00
|
|
|
// If there is a parent component, return a pointer to its derived type spec.
|
2018-12-04 19:55:32 +01:00
|
|
|
// The Scope * argument defaults to this->scope_ but should be overridden
|
|
|
|
// for a parameterized derived type instantiation with the instance's scope.
|
|
|
|
const DerivedTypeSpec *GetParentTypeSpec(const Scope * = nullptr) const;
|
2019-01-08 00:05:53 +01:00
|
|
|
|
2018-03-23 01:08:20 +01:00
|
|
|
private:
|
2018-06-20 01:06:41 +02:00
|
|
|
const Scope *owner_;
|
2018-11-16 21:43:08 +01:00
|
|
|
SourceName name_;
|
2018-03-30 22:57:23 +02:00
|
|
|
Attrs attrs_;
|
2018-06-05 21:18:35 +02:00
|
|
|
Flags flags_;
|
2018-06-22 17:21:19 +02:00
|
|
|
Scope *scope_{nullptr};
|
2018-03-23 01:08:20 +01:00
|
|
|
Details details_;
|
2018-04-17 23:16:42 +02:00
|
|
|
|
2018-06-20 01:06:41 +02:00
|
|
|
Symbol() {} // only created in class Symbols
|
2018-04-17 23:16:42 +02:00
|
|
|
const std::string GetDetailsName() const;
|
2018-03-23 01:08:20 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const Symbol &);
|
2018-06-27 00:01:42 +02:00
|
|
|
friend std::ostream &DumpForUnparse(std::ostream &, const Symbol &, bool);
|
2018-12-04 19:55:32 +01:00
|
|
|
|
2019-03-11 23:39:11 +01:00
|
|
|
// If a derived type's symbol refers to an extended derived type,
|
|
|
|
// return the parent component's symbol. The scope of the derived type
|
|
|
|
// can be overridden.
|
2018-12-04 19:55:32 +01:00
|
|
|
const Symbol *GetParentComponent(const Scope * = nullptr) const;
|
|
|
|
|
2018-06-20 01:06:41 +02:00
|
|
|
template<std::size_t> friend class Symbols;
|
2018-06-22 23:08:04 +02:00
|
|
|
template<class, std::size_t> friend struct std::array;
|
2018-03-23 01:08:20 +01:00
|
|
|
};
|
|
|
|
|
2018-06-05 21:18:35 +02:00
|
|
|
std::ostream &operator<<(std::ostream &, Symbol::Flag);
|
|
|
|
|
2018-06-20 01:06:41 +02:00
|
|
|
// Manage memory for all symbols. BLOCK_SIZE symbols at a time are allocated.
|
|
|
|
// Make() returns a reference to the next available one. They are never
|
|
|
|
// deleted.
|
|
|
|
template<std::size_t BLOCK_SIZE> class Symbols {
|
|
|
|
public:
|
|
|
|
Symbol &Make(const Scope &owner, const SourceName &name, const Attrs &attrs,
|
2018-11-05 23:36:11 +01:00
|
|
|
Details &&details) {
|
2018-06-20 01:06:41 +02:00
|
|
|
Symbol &symbol = Get();
|
|
|
|
symbol.owner_ = &owner;
|
2018-11-16 21:43:08 +01:00
|
|
|
symbol.name_ = name;
|
2018-06-20 01:06:41 +02:00
|
|
|
symbol.attrs_ = attrs;
|
2018-11-05 23:36:11 +01:00
|
|
|
symbol.details_ = std::move(details);
|
2018-06-20 01:06:41 +02:00
|
|
|
return symbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
using blockType = std::array<Symbol, BLOCK_SIZE>;
|
|
|
|
std::list<blockType *> blocks_;
|
|
|
|
std::size_t nextIndex_{0};
|
|
|
|
blockType *currBlock_{nullptr};
|
|
|
|
|
|
|
|
Symbol &Get() {
|
|
|
|
if (nextIndex_ == 0) {
|
|
|
|
blocks_.push_back(new blockType());
|
|
|
|
currBlock_ = blocks_.back();
|
|
|
|
}
|
|
|
|
Symbol &result = (*currBlock_)[nextIndex_];
|
|
|
|
if (++nextIndex_ >= BLOCK_SIZE) {
|
|
|
|
nextIndex_ = 0; // allocate a new block next time
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
2019-01-19 00:53:11 +01:00
|
|
|
|
|
|
|
// Define a few member functions here in the header so that they
|
|
|
|
// can be used by lib/evaluate without inducing a dependence cycle
|
|
|
|
// between the two shared libraries.
|
|
|
|
|
|
|
|
inline bool ProcEntityDetails::HasExplicitInterface() const {
|
|
|
|
if (auto *symbol{interface_.symbol()}) {
|
|
|
|
return symbol->HasExplicitInterface();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
#endif // FORTRAN_SEMANTICS_SYMBOL_H_
|