Files
clang-p2996/flang/lib/Semantics/program-tree.h
Peter Klausler bed947f708 [flang] Accept ENTRY names in generic interfaces
ENTRY statement names in module subprograms were not acceptable for
use as a "module procedure" in a generic interface, but should be.
ENTRY statements need to have symbols with place-holding
SubprogramNameDetails created for them in order to be visible in
generic interfaces.  Those symbols are created from the "program
tree" data structure.  This patch adds ENTRY statement names to the
program tree data structure and uses them to generate SubprogramNameDetails
symbols.

Differential Revision: https://reviews.llvm.org/D117345
2022-01-14 15:43:21 -08:00

112 lines
4.2 KiB
C++

//===-- lib/Semantics/program-tree.h ----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_SEMANTICS_PROGRAM_TREE_H_
#define FORTRAN_SEMANTICS_PROGRAM_TREE_H_
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/symbol.h"
#include <list>
#include <variant>
// A ProgramTree represents a tree of program units and their contained
// subprograms. The root nodes represent: main program, function, subroutine,
// module subprogram, module, or submodule.
// Each node of the tree consists of:
// - the statement that introduces the program unit
// - the specification part
// - the execution part if applicable (not for module or submodule)
// - a child node for each contained subprogram
namespace Fortran::semantics {
class Scope;
class ProgramTree {
public:
using EntryStmtList = std::list<common::Reference<const parser::EntryStmt>>;
// Build the ProgramTree rooted at one of these program units.
static ProgramTree Build(const parser::ProgramUnit &);
static ProgramTree Build(const parser::MainProgram &);
static ProgramTree Build(const parser::FunctionSubprogram &);
static ProgramTree Build(const parser::SubroutineSubprogram &);
static ProgramTree Build(const parser::SeparateModuleSubprogram &);
static ProgramTree Build(const parser::Module &);
static ProgramTree Build(const parser::Submodule &);
static ProgramTree Build(const parser::BlockData &);
static ProgramTree Build(const parser::CompilerDirective &);
ENUM_CLASS(Kind, // kind of node
Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData)
using Stmt = std::variant< // the statement that introduces the program unit
const parser::Statement<parser::ProgramStmt> *,
const parser::Statement<parser::FunctionStmt> *,
const parser::Statement<parser::SubroutineStmt> *,
const parser::Statement<parser::MpSubprogramStmt> *,
const parser::Statement<parser::ModuleStmt> *,
const parser::Statement<parser::SubmoduleStmt> *,
const parser::Statement<parser::BlockDataStmt> *>;
ProgramTree(const parser::Name &name, const parser::SpecificationPart &spec,
const parser::ExecutionPart *exec = nullptr)
: name_{name}, spec_{spec}, exec_{exec} {}
const parser::Name &name() const { return name_; }
Kind GetKind() const;
const Stmt &stmt() const { return stmt_; }
bool isSpecificationPartResolved() const {
return isSpecificationPartResolved_;
}
void set_isSpecificationPartResolved(bool yes = true) {
isSpecificationPartResolved_ = yes;
}
const parser::ParentIdentifier &GetParentId() const; // only for Submodule
const parser::SpecificationPart &spec() const { return spec_; }
const parser::ExecutionPart *exec() const { return exec_; }
std::list<ProgramTree> &children() { return children_; }
const std::list<ProgramTree> &children() const { return children_; }
const std::list<common::Reference<const parser::EntryStmt>> &
entryStmts() const {
return entryStmts_;
}
Symbol::Flag GetSubpFlag() const;
bool IsModule() const; // Module or Submodule
bool HasModulePrefix() const; // in function or subroutine stmt
Scope *scope() const { return scope_; }
void set_scope(Scope &);
void AddChild(ProgramTree &&);
void AddEntry(const parser::EntryStmt &);
template <typename T>
ProgramTree &set_stmt(const parser::Statement<T> &stmt) {
stmt_ = &stmt;
return *this;
}
template <typename T>
ProgramTree &set_endStmt(const parser::Statement<T> &stmt) {
endStmt_ = &stmt.source;
return *this;
}
private:
const parser::Name &name_;
Stmt stmt_{
static_cast<const parser::Statement<parser::ProgramStmt> *>(nullptr)};
const parser::SpecificationPart &spec_;
const parser::ExecutionPart *exec_{nullptr};
std::list<ProgramTree> children_;
EntryStmtList entryStmts_;
Scope *scope_{nullptr};
const parser::CharBlock *endStmt_{nullptr};
bool isSpecificationPartResolved_{false};
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_PROGRAM_TREE_H_