llvm/flang/lib/semantics/scope.h
Tim Keith 4c99dc2a94 [flang] Support interface blocks.
Add subprogram symbols for each interface-body and set isInterface on
them. Create a symbol with GenericDetails for each generic interface
block and add interface specifications to the specific procedures of
the generic. InterfaceVisitor takes care of this.

Before processing the specification part of modules and subprograms,
collect the names of module subprograms and internal subprograms and add
them to the symbol table with SubprogramNameDetails. This allows us to
reference them from interface blocks in the specification part.
SubprogramNameDetails is converted to SubprogramDetails when the real
subprogram is visited.

This is achieved by setting subpNamesOnly_ and then walking the
ModuleSubprogramPart or InternalSubprogramPart. Creating the symbol and
scope for a module or subprogram now happens when the Module,
SubroutineSubprogram, or FunctionSubprogram node is encountered so
this can happen in the right order.

Add BeginSubprogram and EndSubprogram to handle the parts in common
between subprograms and interface specifications.

Add GenericSpec to type.h to represent all possible generic specs.
Only generic names are resolved so far.

Add tests for new error messages. Change resolve02.f90 to reflect the
new errors reported.

Original-commit: flang-compiler/f18@03148b49dd
Reviewed-on: https://github.com/flang-compiler/f18/pull/88
Tree-same-pre-rewrite: false
2018-05-14 13:53:02 -07:00

106 lines
3.4 KiB
C++

// 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.
#ifndef FORTRAN_SEMANTICS_SCOPE_H_
#define FORTRAN_SEMANTICS_SCOPE_H_
#include "attr.h"
#include "symbol.h"
#include "../parser/idioms.h"
#include "../parser/parse-tree.h"
#include <list>
#include <map>
#include <string>
namespace Fortran::semantics {
class Scope {
using mapType = std::map<SourceName, Symbol>;
public:
// root of the scope tree; contains intrinsics:
static const Scope systemScope;
static Scope globalScope; // contains program-units
ENUM_CLASS(Kind, System, Global, Module, MainProgram, Subprogram)
Scope(const Scope &parent, Kind kind, Symbol *symbol)
: parent_{parent}, kind_{kind}, symbol_{symbol} {}
const Scope &parent() const {
CHECK(kind_ != Kind::System);
return parent_;
}
Kind kind() const { return kind_; }
Symbol *symbol() { return symbol_; }
const Symbol *symbol() const { return symbol_; }
const SourceName &name() const {
CHECK(symbol_); // must only be called for Scopes known to have a symbol
return symbol_->name();
}
/// Make a scope nested in this one
Scope &MakeScope(Kind kind, Symbol *symbol = nullptr);
using size_type = mapType::size_type;
using iterator = mapType::iterator;
using const_iterator = mapType::const_iterator;
iterator begin() { return symbols_.begin(); }
iterator end() { return symbols_.end(); }
const_iterator begin() const { return symbols_.begin(); }
const_iterator end() const { return symbols_.end(); }
const_iterator cbegin() const { return symbols_.cbegin(); }
const_iterator cend() const { return symbols_.cend(); }
iterator find(const SourceName &name) { return symbols_.find(name); }
const_iterator find(const SourceName &name) const {
return symbols_.find(name);
}
size_type erase(const SourceName &name) { return symbols_.erase(name); }
/// Make a Symbol with unknown details.
std::pair<iterator, bool> try_emplace(
const SourceName &name, Attrs attrs = Attrs()) {
return try_emplace(name, attrs, UnknownDetails());
}
/// Make a Symbol with provided details.
template<typename D>
std::pair<iterator, bool> try_emplace(const SourceName &name, D &&details) {
return try_emplace(name, Attrs(), details);
}
/// Make a Symbol with attrs and details
template<typename D>
std::pair<iterator, bool> try_emplace(
const SourceName &name, Attrs attrs, D &&details) {
return symbols_.try_emplace(name, *this, name, attrs, details);
}
std::list<Scope> &children() { return children_; }
const std::list<Scope> &children() const { return children_; }
private:
const Scope &parent_;
const Kind kind_;
Symbol *const symbol_;
std::list<Scope> children_;
mapType symbols_;
friend std::ostream &operator<<(std::ostream &, const Scope &);
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_SCOPE_H_