llvm/flang/lib/semantics/scope.h
Tim Keith 9727b06813 [flang] Support for USE statements.
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
2018-05-03 15:57:56 -07:00

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_