86726d8ee4
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
110 lines
3.1 KiB
C++
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_
|