2018-05-01 21:50:34 +02:00
|
|
|
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
//
|
|
|
|
// 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"
|
2018-06-22 17:21:19 +02:00
|
|
|
#include "../common/enum-set.h"
|
2018-09-04 19:28:27 +02:00
|
|
|
#include "../common/fortran.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;
|
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_} {}
|
|
|
|
|
|
|
|
bool isFunction() const { return result_.has_value(); }
|
2018-05-14 22:51:13 +02:00
|
|
|
bool isInterface() const { return isInterface_; }
|
|
|
|
void set_isInterface(bool value = true) { isInterface_ = value; }
|
2018-05-02 23:06:02 +02:00
|
|
|
const Symbol &result() const {
|
|
|
|
CHECK(isFunction());
|
|
|
|
return **result_;
|
|
|
|
}
|
2018-04-17 23:16:42 +02:00
|
|
|
void set_result(Symbol &result) {
|
|
|
|
CHECK(!result_.has_value());
|
|
|
|
result_ = &result;
|
|
|
|
}
|
|
|
|
const std::list<Symbol *> &dummyArgs() const { return dummyArgs_; }
|
|
|
|
void add_dummyArg(Symbol &symbol) { dummyArgs_.push_back(&symbol); }
|
2018-03-23 01:08:20 +01:00
|
|
|
|
|
|
|
private:
|
2018-04-17 23:16:42 +02:00
|
|
|
std::list<Symbol *> dummyArgs_;
|
|
|
|
std::optional<Symbol *> result_;
|
2018-05-14 22:51:13 +02:00
|
|
|
bool isInterface_{false}; // true if this represents an interface-body
|
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:
|
|
|
|
EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type() const { return type_; }
|
2018-04-12 21:59:42 +02:00
|
|
|
void set_type(const DeclTypeSpec &type);
|
2018-06-05 21:18:35 +02:00
|
|
|
bool isDummy() const { return isDummy_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool isDummy_;
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type_{nullptr};
|
2018-06-05 21:18:35 +02:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const EntityDetails &);
|
|
|
|
};
|
|
|
|
|
|
|
|
// An entity known to be an object.
|
|
|
|
class ObjectEntityDetails {
|
|
|
|
public:
|
|
|
|
ObjectEntityDetails(const EntityDetails &);
|
|
|
|
ObjectEntityDetails(bool isDummy = false) : isDummy_{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); }
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type() const { return type_; }
|
2018-06-05 21:18:35 +02:00
|
|
|
void set_type(const DeclTypeSpec &type);
|
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_; }
|
|
|
|
void set_shape(const ArraySpec &shape);
|
2018-03-23 01:08:20 +01:00
|
|
|
bool isDummy() const { return isDummy_; }
|
2018-12-11 23:03:55 +01:00
|
|
|
bool IsArray() const { return !shape_.empty(); }
|
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:
|
|
|
|
bool isDummy_;
|
2018-12-06 15:59:37 +01:00
|
|
|
MaybeExpr init_;
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type_{nullptr};
|
2018-04-12 21:59:42 +02:00
|
|
|
ArraySpec shape_;
|
2018-06-05 21:18:35 +02:00
|
|
|
friend std::ostream &operator<<(std::ostream &, const ObjectEntityDetails &);
|
|
|
|
};
|
|
|
|
|
|
|
|
// A procedure pointer, dummy procedure, or external procedure
|
|
|
|
class ProcEntityDetails {
|
|
|
|
public:
|
|
|
|
ProcEntityDetails() = default;
|
|
|
|
ProcEntityDetails(const EntityDetails &d);
|
|
|
|
|
|
|
|
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; }
|
2018-06-05 21:18:35 +02:00
|
|
|
bool HasExplicitInterface() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
ProcInterface interface_;
|
|
|
|
friend std::ostream &operator<<(std::ostream &, const ProcEntityDetails &);
|
2018-03-23 01:08:20 +01:00
|
|
|
};
|
|
|
|
|
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_; }
|
2018-09-06 17:01:49 +02:00
|
|
|
const Symbol *extends() const { return extends_; }
|
|
|
|
bool sequence() const { return sequence_; }
|
2018-12-07 02:52:43 +01:00
|
|
|
void add_paramName(const SourceName &name) { paramNames_.emplace_back(name); }
|
2018-09-06 17:01:49 +02:00
|
|
|
void set_extends(const Symbol *extends) { extends_ = extends; }
|
|
|
|
void set_sequence(bool x = true) { sequence_ = x; }
|
2018-09-04 19:28:27 +02:00
|
|
|
|
|
|
|
private:
|
2018-12-07 02:52:43 +01:00
|
|
|
std::list<SourceName> paramNames_;
|
2018-09-06 17:01:49 +02:00
|
|
|
const Symbol *extends_{nullptr};
|
|
|
|
bool sequence_{false};
|
2018-09-04 19:28:27 +02:00
|
|
|
};
|
2018-06-22 17:21:19 +02:00
|
|
|
|
2018-09-01 01:20:00 +02:00
|
|
|
class ProcBindingDetails {
|
|
|
|
public:
|
|
|
|
ProcBindingDetails(const Symbol &symbol) : symbol_{&symbol} {}
|
|
|
|
const Symbol &symbol() const { return *symbol_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
const Symbol *symbol_; // procedure bound to
|
|
|
|
};
|
|
|
|
|
2018-12-26 22:31:13 +01:00
|
|
|
class GenericBindingDetails {
|
|
|
|
public:
|
|
|
|
GenericBindingDetails() {}
|
|
|
|
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:
|
|
|
|
SymbolList specificProcs_;
|
|
|
|
};
|
2018-09-01 01:20:00 +02:00
|
|
|
|
|
|
|
class FinalProcDetails {};
|
|
|
|
|
2018-09-25 17:53:53 +02:00
|
|
|
class MiscDetails {
|
|
|
|
public:
|
2018-11-16 21:43:08 +01:00
|
|
|
ENUM_CLASS(Kind, ConstructName, ScopeName);
|
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:
|
2018-09-06 01:02:41 +02:00
|
|
|
TypeParamDetails(common::TypeParamAttr attr) : attr_{attr} {}
|
|
|
|
common::TypeParamAttr attr() const { return attr_; }
|
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); }
|
2018-12-11 23:51:08 +01:00
|
|
|
const DeclTypeSpec *type() const { return type_; }
|
2018-09-04 19:28:27 +02:00
|
|
|
void set_type(const DeclTypeSpec &type) {
|
|
|
|
CHECK(!type_);
|
2018-12-11 23:51:08 +01:00
|
|
|
type_ = &type;
|
2018-09-04 19:28:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2018-09-06 01:02:41 +02:00
|
|
|
common::TypeParamAttr attr_;
|
2018-12-06 15:59:37 +01:00
|
|
|
MaybeExpr 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
|
|
|
|
2018-12-26 22:31:13 +01:00
|
|
|
const SymbolList specificProcs() const { return specificProcs_; }
|
2018-07-20 19:46:11 +02:00
|
|
|
|
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_; }
|
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;
|
2018-05-14 22:51:13 +02:00
|
|
|
|
|
|
|
private:
|
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,
|
2018-06-22 17:21:19 +02:00
|
|
|
ObjectEntityDetails, ProcEntityDetails, DerivedTypeDetails, UseDetails,
|
2018-10-18 16:55:48 +02:00
|
|
|
UseErrorDetails, HostAssocDetails, GenericDetails, ProcBindingDetails,
|
|
|
|
GenericBindingDetails, 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,
|
|
|
|
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() {
|
|
|
|
return const_cast<D &>(static_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 {
|
2018-07-17 16:02:30 +02:00
|
|
|
if (const auto p{detailsIf<D>()}) {
|
2018-04-17 23:16:42 +02:00
|
|
|
return *p;
|
|
|
|
} else {
|
2018-06-18 20:03:43 +02:00
|
|
|
common::die("unexpected %s details at %s(%d)", GetDetailsName().c_str(),
|
|
|
|
__FILE__, __LINE__);
|
2018-04-17 23:16:42 +02:00
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
2018-11-07 02:18:06 +01:00
|
|
|
DeclTypeSpec *GetType();
|
2018-06-27 00:01:42 +02:00
|
|
|
const DeclTypeSpec *GetType() const;
|
|
|
|
void SetType(const DeclTypeSpec &);
|
|
|
|
|
2018-10-26 20:57:08 +02:00
|
|
|
bool IsSubprogram() const;
|
2018-06-05 21:18:35 +02:00
|
|
|
bool HasExplicitInterface() const;
|
2018-10-26 20:57:08 +02:00
|
|
|
bool IsSeparateModuleProc() const;
|
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; }
|
|
|
|
|
2018-09-18 18:34:59 +02:00
|
|
|
int Rank() const;
|
|
|
|
|
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-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;
|
|
|
|
}
|
|
|
|
};
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|
2018-03-23 01:08:20 +01:00
|
|
|
#endif // FORTRAN_SEMANTICS_SYMBOL_H_
|