9727b06813
When a USE statement is encountered, find the scope corresponding to the module. This is now stored in the ModuleDetails of the module symbol. useModuleScope_ tracks this while processing the USE. Currently only modules defined in the same file work because we don't have module files. At the end of a USE that isn't a use-only, add all public names that were not renamed. AddUse() handles recording of a USE by creating a local symbol with UseDetails that tracks the use-symbol in the module and the location of the USE (for error messages). If an ambiguous USE is detected, the UseDetails are replaced by UseErrorDetails. This tracks the locations of all the uses so that they can be referenced in a diagnostic. Detect attempts to re-declare use-associated symbols as well as changing their attributes (except for ASYNCHRONOUS and VOLATILE). Add missing checks for access-stmt in scoping units other than modules. Add tests for the new errors. Reorganize the MessageHandler::Say() overloadings to prevent them from becoming too numerous. Original-commit: flang-compiler/f18@cc0523134c Reviewed-on: https://github.com/flang-compiler/f18/pull/79
105 lines
3.4 KiB
C++
105 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, const Symbol *symbol)
|
|
: parent_{parent}, kind_{kind}, symbol_{symbol} {}
|
|
|
|
const Scope &parent() const {
|
|
CHECK(kind_ != Kind::System);
|
|
return parent_;
|
|
}
|
|
Kind kind() const { return kind_; }
|
|
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, const 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_;
|
|
const 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_
|