4c99dc2a94
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
106 lines
3.4 KiB
C++
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_
|