llvm/flang/lib/semantics/symbol.h

322 lines
10 KiB
C
Raw Normal View History

// 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.
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
#ifndef FORTRAN_SEMANTICS_SYMBOL_H_
#define FORTRAN_SEMANTICS_SYMBOL_H_
#include "type.h"
#include <functional>
#include <memory>
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
namespace Fortran::semantics {
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
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;
class Symbol;
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
class ModuleDetails {
public:
const Scope *scope() const { return scope_; }
void set_scope(const Scope *scope) {
CHECK(!scope_);
scope_ = scope;
}
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
private:
const Scope *scope_{nullptr};
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
};
class MainProgramDetails {
public:
private:
};
class SubprogramDetails {
public:
SubprogramDetails() {}
SubprogramDetails(const SubprogramDetails &that)
: dummyArgs_{that.dummyArgs_}, result_{that.result_} {}
bool isFunction() const { return result_.has_value(); }
bool isInterface() const { return isInterface_; }
void set_isInterface(bool value = true) { isInterface_ = value; }
const Symbol &result() const {
CHECK(isFunction());
return **result_;
}
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); }
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
private:
std::list<Symbol *> dummyArgs_;
std::optional<Symbol *> result_;
bool isInterface_{false}; // true if this represents an interface-body
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
friend std::ostream &operator<<(std::ostream &, const SubprogramDetails &);
};
// 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_; }
private:
SubprogramKind kind_;
};
// A name from an entity-decl -- could be object or function.
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
class EntityDetails {
public:
EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
const std::optional<DeclTypeSpec> &type() const { return type_; }
void set_type(const DeclTypeSpec &type);
bool isDummy() const { return isDummy_; }
private:
bool isDummy_;
std::optional<DeclTypeSpec> type_;
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} {}
const std::optional<DeclTypeSpec> &type() const { return type_; }
void set_type(const DeclTypeSpec &type);
const ArraySpec &shape() const { return shape_; }
void set_shape(const ArraySpec &shape);
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
bool isDummy() const { return isDummy_; }
bool isArray() const { return !shape_.empty(); }
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
private:
bool isDummy_;
std::optional<DeclTypeSpec> type_;
ArraySpec shape_;
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_; }
void set_interface(ProcInterface &&interface) {
interface_ = std::move(interface);
}
bool HasExplicitInterface() const;
private:
ProcInterface interface_;
friend std::ostream &operator<<(std::ostream &, const ProcEntityDetails &);
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01: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)
: location_{&location}, symbol_{&symbol} {}
const SourceName &location() const { return *location_; }
const Symbol &symbol() const { return *symbol_; }
const Symbol &module() const;
private:
const SourceName *location_;
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:
UseErrorDetails(const SourceName &location, const Scope &module) {
add_occurrence(location, module);
}
UseErrorDetails &add_occurrence(
const SourceName &location, const Scope &module) {
occurrences_.push_back(std::make_pair(&location, &module));
return *this;
}
using listType = std::list<std::pair<const SourceName *, const Scope *>>;
const listType occurrences() const { return occurrences_; };
private:
listType occurrences_;
};
class GenericDetails {
public:
using listType = std::list<const Symbol *>;
GenericDetails() {}
GenericDetails(const listType &specificProcs);
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
GenericDetails(Symbol *specific) : specific_{specific} {}
const listType specificProcs() const { return specificProcs_; }
void add_specificProc(const Symbol *proc) { specificProcs_.push_back(proc); }
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
Symbol *specific() { return specific_; }
void set_specific(Symbol *specific);
// Check that specific is one of the specificProcs. If not, return the
// specific as a raw pointer.
const Symbol *CheckSpecific() const;
private:
// all of the specific procedures for this generic
listType specificProcs_;
// a specific procedure with the same name as this generic, if any
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
Symbol *specific_{nullptr};
};
class UnknownDetails {};
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
using Details = std::variant<UnknownDetails, MainProgramDetails, ModuleDetails,
SubprogramDetails, SubprogramNameDetails, EntityDetails,
ObjectEntityDetails, ProcEntityDetails, UseDetails, UseErrorDetails,
GenericDetails>;
std::ostream &operator<<(std::ostream &, const Details &);
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
class Symbol {
public:
ENUM_CLASS(Flag, Function, Subroutine);
using Flags = common::EnumSet<Flag, Flag_enumSize>;
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
const Scope &owner() const { return *owner_; }
const SourceName &name() const { return occurrences_.front(); }
Attrs &attrs() { return attrs_; }
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
const Attrs &attrs() const { return attrs_; }
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); }
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
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_); }
template<typename D> const D *detailsIf() const {
return std::get_if<D>(&details_);
}
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
// Return a reference to the details which must be of type D.
template<typename D> D &details() {
return const_cast<D &>(static_cast<const Symbol *>(this)->details<D>());
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
}
template<typename D> const D &details() const {
if (const auto p = detailsIf<D>()) {
return *p;
} else {
common::die("unexpected %s details at %s(%d)", GetDetailsName().c_str(),
__FILE__, __LINE__);
}
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
}
// Assign the details of the symbol from one of the variants.
// Only allowed in certain cases.
void set_details(Details &&details);
// Can the details of this symbol be replaced with the given details?
bool CanReplaceDetails(const Details &details) const;
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
const std::list<SourceName> &occurrences() const { return occurrences_; }
void add_occurrence(const SourceName &name) { occurrences_.push_back(name); }
// Follow use-associations to get the ultimate entity.
Symbol &GetUltimate();
const Symbol &GetUltimate() const;
bool isSubprogram() const;
bool HasExplicitInterface() const;
bool operator==(const Symbol &that) const { return this == &that; }
bool operator!=(const Symbol &that) const { return this != &that; }
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
private:
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
const Scope *owner_;
std::list<SourceName> occurrences_;
Attrs attrs_;
Flags flags_;
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
Details details_;
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
Symbol() {} // only created in class Symbols
const std::string GetDetailsName() const;
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
friend std::ostream &operator<<(std::ostream &, const Symbol &);
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
2018-06-20 01:06:41 +02:00
template<std::size_t> friend class Symbols;
template<class, std::size_t> friend class std::array;
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
};
std::ostream &operator<<(std::ostream &, Symbol::Flag);
[flang] Change how memory for Symbol instances is managed. With this change, all instances Symbol are stored in class Symbols. Scope.symbols_, which used to own the symbol memory, now maps names to Symbol* instead. This causes a bunch of reference-to-pointer changes because of the change in type of key-value pairs. It also requires a default constructor for Symbol, which means owner_ can't be a reference. Symbols manages Symbol instances by allocating a block of them at a time and returning the next one when needed. They are never freed. The reason for the change is that there are a few cases where we need to have a two symbols with the same name, so they can't both live in the map in Scope. Those are: 1. When there is an erroneous redeclaration of a name we may delete the first symbol and replace it with a new one. If we have saved a pointer to the first one it is now dangling. This can be seen by running `f18 -fdebug-dump-symbols -fparse-only test/semantics/resolve19.f90` under valgrind. Subroutine s is declared twice: each results in a scope that contains a pointer back to the symbol for the subroutine. After the second symbol for s is created the first is gone so the pointer in the scope is invalid. 2. A generic and one of its specifics can have the same name. We currently handle that by moving the symbol for the specific into a unique_ptr in the generic. So in that case the symbol is owned by another symbol instead of by the scope. It is simpler if we only have to deal with moving the raw pointer around. 3. A generic and a derived type can have the same name. This case isn't handled yet, but it can be done like flang-compiler/f18#2 above. It's more complicated because the derived type and the generic can be declared in either order. Original-commit: flang-compiler/f18@55a68cf0235c8a3ac855de7dc0e2b08690866be0 Reviewed-on: https://github.com/flang-compiler/f18/pull/107
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,
Details &&details) {
Symbol &symbol = Get();
symbol.owner_ = &owner;
symbol.occurrences_.push_back(name);
symbol.attrs_ = attrs;
symbol.details_ = std::move(details);
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;
}
};
} // namespace Fortran::semantics
[flang] Partial implementation of Symbols and Scopes. A Symbol consists of a common part (in class Symbol) containing name, owner, attributes. Information for a specific kind of symbol is in a variant containing one of the *Details classes. So the kind of symbol is determined by the type of details class stored in the details_ variant. For scopes there is a single Scope class with an enum indicating the kind. So far there isn't a need for extra kind-specific details as with Symbols but that could change. Symbols defined in a Scope are stored there in a simple map. resolve-names.cc is a partial implementation of a parse-tree walker that resolves names to Symbols. Currently is only handles functions (which introduce a new Scope) and entity-decls. The test-type executable was reused as a driver for this to avoid the need for a new one. Sample output is below. When each "end function" is encountered the scope is dumped, which shows the symbols defined in it. $ cat a.f90 pure integer(8) function foo(arg1, arg2) result(res) integer :: arg1 real :: arg2 contains function bar(arg1) real :: bar real :: arg1 end function end function $ Debug/tools/f18/test-type a.f90 Subprogram scope: 0 children arg1: Entity type: REAL bar: Entity type: REAL Subprogram scope: 1 children arg1: Entity type: INTEGER arg2: Entity type: REAL bar: Subprogram (arg1) foo: Subprogram (arg1, arg2) result(res) res: Entity type: INTEGER(8) Original-commit: flang-compiler/f18@1cd2fbc04da1d6bb2ef5bc1cf07c808460ea7547 Reviewed-on: https://github.com/flang-compiler/f18/pull/30 Tree-same-pre-rewrite: false
2018-03-23 01:08:20 +01:00
#endif // FORTRAN_SEMANTICS_SYMBOL_H_