llvm/flang/lib/semantics/attr.cc
Tim Keith a3de9d789c [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@1cd2fbc04d
Reviewed-on: https://github.com/flang-compiler/f18/pull/30
Tree-same-pre-rewrite: false
2018-03-22 17:25:34 -07:00

94 lines
2.5 KiB
C++

#include "../parser/idioms.h"
#include "attr.h"
#include <stddef.h>
namespace Fortran {
namespace semantics {
constexpr static size_t toInt(Attr attr) { return static_cast<size_t>(attr); }
static const char *attrToString[] = {
[toInt(Attr::ABSTRACT)] = "ABSTRACT",
[toInt(Attr::ALLOCATABLE)] = "ALLOCATABLE",
[toInt(Attr::ASYNCHRONOUS)] = "ASYNCHRONOUS",
[toInt(Attr::BIND_C)] = "BIND_C",
[toInt(Attr::CONTIGUOUS)] = "CONTIGUOUS",
[toInt(Attr::DEFERRED)] = "DEFERRED",
[toInt(Attr::ELEMENTAL)] = "ELEMENTAL",
[toInt(Attr::EXTERNAL)] = "EXTERNAL",
[toInt(Attr::IMPURE)] = "IMPURE",
[toInt(Attr::INTENT_IN)] = "INTENT_IN",
[toInt(Attr::INTENT_OUT)] = "INTENT_OUT",
[toInt(Attr::INTRINSIC)] = "INTRINSIC",
[toInt(Attr::MODULE)] = "MODULE",
[toInt(Attr::NON_OVERRIDABLE)] = "NON_OVERRIDABLE",
[toInt(Attr::NON_RECURSIVE)] = "NON_RECURSIVE",
[toInt(Attr::NOPASS)] = "NOPASS",
[toInt(Attr::OPTIONAL)] = "OPTIONAL",
[toInt(Attr::PARAMETER)] = "PARAMETER",
[toInt(Attr::PASS)] = "PASS",
[toInt(Attr::POINTER)] = "POINTER",
[toInt(Attr::PRIVATE)] = "PRIVATE",
[toInt(Attr::PROTECTED)] = "PROTECTED",
[toInt(Attr::PUBLIC)] = "PUBLIC",
[toInt(Attr::PURE)] = "PURE",
[toInt(Attr::RECURSIVE)] = "RECURSIVE",
[toInt(Attr::SAVE)] = "SAVE",
[toInt(Attr::TARGET)] = "TARGET",
[toInt(Attr::VALUE)] = "VALUE",
[toInt(Attr::VOLATILE)] = "VOLATILE",
};
const Attrs Attrs::EMPTY;
Attrs::Attrs(std::initializer_list<Attr> attrs) {
bits_ = 0;
for (auto attr : attrs) {
Set(attr);
}
}
Attrs &Attrs::Set(Attr attr) {
bits_ |= 1u << toInt(attr);
return *this;
}
Attrs &Attrs::Add(const Attrs &attrs) {
bits_ |= attrs.bits_;
return *this;
}
bool Attrs::Has(Attr attr) const { return (bits_ & (1u << toInt(attr))) != 0; }
bool Attrs::HasAny(const Attrs &attrs) const {
return (bits_ & attrs.bits_) != 0;
}
bool Attrs::HasAll(const Attrs &attrs) const {
return (bits_ & attrs.bits_) == attrs.bits_;
}
void Attrs::CheckValid(const Attrs &allowed) const {
if (!allowed.HasAll(*this)) {
parser::die("invalid attribute");
}
}
std::ostream &operator<<(std::ostream &o, Attr attr) {
return o << attrToString[toInt(attr)];
}
std::ostream &operator<<(std::ostream &o, const Attrs &attrs) {
int i = 0, n = 0;
for (std::uint64_t bits = attrs.bits_; bits != 0; bits >>= 1, ++i) {
if (bits & 1) {
if (n++) {
o << ", ";
}
o << attrToString[i];
}
}
return o;
}
} // namespace semantics
} // namespace Fortran