llvm/flang/lib/semantics/symbol.h
Tim Keith 86726d8ee4 [flang] Continue work on name resolution
Enhance DeclTypeSpecVisitor to find derived-type-specs, including with
type parameter values.

Change DerivedTypeSpec so it only needs the name of the derived type,
not the definition, as that isn't necessarily known when we encounter
it.

Fix how memory is managed in DeclTypeSpec: Intrinsic type specs aren't a
problem -- they are one of a few types that live throughout the program.
Derived type specs are dynamically allocated and the memory is owned by
the DeclTypeSpec -- it allocates it when a DeclTypeSpec for a derived
type is created and deletes it when it is destroyed. Pass around
references to TypeSpecs rather than pointers as they can never be null.

In AttrsVisitor, DeclTypeSpecVisitor, ResolveNamesVisitor: make most
functions out-of-line to clean up the class declaration.

In AttrsVisitor, use preprocessor to simplify the simple case of
encountering a parse-tree class causing an attribute to be set.
Handle all such attributes.

Remove old testing code from type.cc.

Remove some of the declarations for IntExpr and IntConst -- they are
only placeholder classes anyway. Don't distinguish kind and length
parameter values.

Original-commit: flang-compiler/f18@e172b51212
Reviewed-on: https://github.com/flang-compiler/f18/pull/36
Tree-same-pre-rewrite: false
2018-04-02 10:49:22 -07:00

110 lines
3.1 KiB
C++

#ifndef FORTRAN_SEMANTICS_SYMBOL_H_
#define FORTRAN_SEMANTICS_SYMBOL_H_
#include "type.h"
#include <functional>
#include <memory>
namespace Fortran::semantics {
/// 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 ModuleDetails {
public:
private:
};
class MainProgramDetails {
public:
private:
};
class SubprogramDetails {
public:
SubprogramDetails(const std::list<Name> &dummyNames)
: isFunction_{false}, dummyNames_{dummyNames} {}
SubprogramDetails(
const std::list<Name> &dummyNames, const std::optional<Name> &resultName)
: isFunction_{true}, dummyNames_{dummyNames}, resultName_{resultName} {}
bool isFunction() const { return isFunction_; }
const std::list<Name> &dummyNames() const { return dummyNames_; }
const std::optional<Name> &resultName() const { return resultName_; }
private:
bool isFunction_;
std::list<Name> dummyNames_;
std::optional<Name> resultName_;
friend std::ostream &operator<<(std::ostream &, const SubprogramDetails &);
};
class EntityDetails {
public:
EntityDetails(bool isDummy = false) : isDummy_{isDummy} {}
const std::optional<DeclTypeSpec> &type() const { return type_; }
void set_type(const DeclTypeSpec &type) { type_ = type; };
bool isDummy() const { return isDummy_; }
private:
bool isDummy_;
std::optional<DeclTypeSpec> type_;
friend std::ostream &operator<<(std::ostream &, const EntityDetails &);
};
class UnknownDetails {};
class Symbol {
public:
// TODO: more kinds of details
using Details = std::variant<UnknownDetails, MainProgramDetails,
ModuleDetails, SubprogramDetails, EntityDetails>;
Symbol(const Scope &owner, const Name &name, const Attrs &attrs,
Details &&details)
: owner_{owner}, name_{name}, attrs_{attrs}, details_{std::move(details)} {}
const Scope &owner() const { return owner_; }
const Name &name() const { return name_; }
Attrs &attrs() { return attrs_; }
const Attrs &attrs() const { return attrs_; }
// 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_); }
// Return a reference to the details which must be of type D.
template<typename D> D &details() {
auto p = detailsIf<D>();
CHECK(p && "unexpected type");
return *p;
}
template<typename D> const D &details() const {
const auto p = detailsIf<D>();
CHECK(p && "unexpected type");
return *p;
}
// Assign the details of the symbol from one of the variants.
// Only allowed if unknown.
void set_details(Details &&details) {
CHECK(has<UnknownDetails>());
details_.swap(details);
}
private:
const Scope &owner_;
const Name name_;
Attrs attrs_;
Details details_;
friend std::ostream &operator<<(std::ostream &, const Symbol &);
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SYMBOL_H_