From cef802b1b40fd87d546baf96cc6263eca5725f20 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Wed, 28 Nov 2018 15:55:55 -0800 Subject: [PATCH] [flang] Add mapping of source location to Scope Each Scope now tracks the source locations that it and its nested scopes span. This is achieved by extending the source range of a scope for each statement encountered while it is the current scope. Semantics::FindScope maps a source location (from the cooked character stream) to the narrowest scope that contains it. Original-commit: flang-compiler/f18@7b4d2bb113e4a1018c5f6aa740b02e423ff61799 Reviewed-on: https://github.com/flang-compiler/f18/pull/230 Tree-same-pre-rewrite: false --- flang/lib/parser/char-block.h | 4 ++++ flang/lib/semantics/resolve-names.cc | 22 ++++++++++++---------- flang/lib/semantics/scope.cc | 22 ++++++++++++++++++++++ flang/lib/semantics/scope.h | 7 +++++++ flang/lib/semantics/semantics.cc | 8 ++++++++ flang/lib/semantics/semantics.h | 5 ++++- 6 files changed, 57 insertions(+), 11 deletions(-) diff --git a/flang/lib/parser/char-block.h b/flang/lib/parser/char-block.h index 3fc0cd4..ae829de 100644 --- a/flang/lib/parser/char-block.h +++ b/flang/lib/parser/char-block.h @@ -48,6 +48,10 @@ public: return interval_.start()[j]; } + bool Contains(const CharBlock &that) const { + return interval_.Contains(that.interval_); + } + bool IsBlank() const { for (char ch : *this) { if (ch != ' ' && ch != '\t') { diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 1dccfc8..b39a3ea 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -199,15 +199,8 @@ public: void set_messages(parser::Messages &messages) { messages_ = &messages; } - template bool Pre(const parser::Statement &x) { - currStmtSource_ = &x.source; - return true; - } - template void Post(const parser::Statement &) { - currStmtSource_ = nullptr; - } - const SourceName *currStmtSource() { return currStmtSource_; } + void set_currStmtSource(const SourceName *x) { currStmtSource_ = x; } // Add a message to the messages to be emitted. Message &Say(Message &&); @@ -240,8 +233,6 @@ class ImplicitRulesVisitor : public DeclTypeSpecVisitor, public MessageHandler { public: using DeclTypeSpecVisitor::Post; using DeclTypeSpecVisitor::Pre; - using MessageHandler::Post; - using MessageHandler::Pre; using ImplicitNoneNameSpec = parser::ImplicitStmt::ImplicitNoneNameSpec; void Post(const parser::ParameterStmt &); @@ -338,6 +329,15 @@ public: ImplicitRulesVisitor::ClearScopes(); } + template bool Pre(const parser::Statement &x) { + set_currStmtSource(&x.source); + currScope_->AddSourceRange(x.source); + return true; + } + template void Post(const parser::Statement &) { + set_currStmtSource(nullptr); + } + Symbol *FindSymbol(const SourceName &name); void EraseSymbol(const SourceName &name); @@ -765,6 +765,8 @@ public: using InterfaceVisitor::Pre; using ModuleVisitor::Post; using ModuleVisitor::Pre; + using ScopeHandler::Post; + using ScopeHandler::Pre; using SubprogramVisitor::Post; using SubprogramVisitor::Pre; diff --git a/flang/lib/semantics/scope.cc b/flang/lib/semantics/scope.cc index 2f583b2..ae275b4 100644 --- a/flang/lib/semantics/scope.cc +++ b/flang/lib/semantics/scope.cc @@ -134,6 +134,28 @@ bool Scope::CanImport(const SourceName &name) const { } } +const Scope *Scope::FindScope(const parser::CharBlock &source) const { + if (!sourceRange_.Contains(source)) { + return nullptr; + } + for (const auto &child : children_) { + if (const auto *scope{child.FindScope(source)}) { + return scope; + } + } + return this; +} + +void Scope::AddSourceRange(const parser::CharBlock &source) { + if (sourceRange_.empty()) { + sourceRange_ = source; + } else if (!source.empty()) { + sourceRange_ = + parser::CharBlock(std::min(sourceRange_.begin(), source.begin()), + std::max(sourceRange_.end(), source.end())); + } +} + std::ostream &operator<<(std::ostream &os, const Scope &scope) { os << Scope::EnumToString(scope.kind()) << " scope: "; if (auto *symbol{scope.symbol()}) { diff --git a/flang/lib/semantics/scope.h b/flang/lib/semantics/scope.h index b60239d..fd5404a 100644 --- a/flang/lib/semantics/scope.h +++ b/flang/lib/semantics/scope.h @@ -137,9 +137,16 @@ public: bool add_importName(const SourceName &); + // The range of the source of this and nested scopes. + const parser::CharBlock &sourceRange() const { return sourceRange_; } + void AddSourceRange(const parser::CharBlock &); + // Find the smallest scope under this one that contains source + const Scope *FindScope(const parser::CharBlock &) const; + private: Scope &parent_; const Kind kind_; + parser::CharBlock sourceRange_; Symbol *const symbol_; std::list children_; mapType symbols_; diff --git a/flang/lib/semantics/semantics.cc b/flang/lib/semantics/semantics.cc index 51feee5d..117d39c 100644 --- a/flang/lib/semantics/semantics.cc +++ b/flang/lib/semantics/semantics.cc @@ -74,6 +74,14 @@ bool Semantics::Perform() { return !AnyFatalError(); } +const Scope &Semantics::FindScope(const parser::CharBlock &source) const { + if (const auto *scope{context_.globalScope().FindScope(source)}) { + return *scope; + } else { + common::die("invalid source location"); + } +} + void Semantics::EmitMessages(std::ostream &os) const { context_.messages().Emit(os, cooked_); } diff --git a/flang/lib/semantics/semantics.h b/flang/lib/semantics/semantics.h index f66c1f8..d64a0df 100644 --- a/flang/lib/semantics/semantics.h +++ b/flang/lib/semantics/semantics.h @@ -89,10 +89,13 @@ class Semantics { public: explicit Semantics(SemanticsContext &context, parser::Program &program, parser::CookedSource &cooked) - : context_{context}, program_{program}, cooked_{cooked} {} + : context_{context}, program_{program}, cooked_{cooked} { + context.globalScope().AddSourceRange(parser::CharBlock{cooked.data()}); + } SemanticsContext &context() const { return context_; } bool Perform(); + const Scope &FindScope(const parser::CharBlock &) const; bool AnyFatalError() const { return context_.AnyFatalError(); } void EmitMessages(std::ostream &) const; void DumpSymbols(std::ostream &); -- 2.7.4