[flang] Add common base class for context, Walk(), and Say()

We need access to the SemanticsContext and Walk() function everywhere,
so move them to a BaseVisitor, a base class at the root of the class
hierarchy.

Also move MessageHandler to be a data member of BaseVisitor and forward
Say calls to it.

Original-commit: flang-compiler/f18@eb9adc342a
Reviewed-on: https://github.com/flang-compiler/f18/pull/238
Tree-same-pre-rewrite: false
This commit is contained in:
Tim Keith 2018-11-16 16:40:00 -08:00
parent d7ba02ab8c
commit 1c856ac972
1 changed files with 105 additions and 86 deletions

View File

@ -33,7 +33,11 @@ namespace Fortran::semantics {
using namespace parser::literals;
class MessageHandler;
using Message = parser::Message;
using Messages = parser::Messages;
using MessageFixedText = parser::MessageFixedText;
using MessageFormattedText = parser::MessageFormattedText;
class ResolveNamesVisitor;
static const parser::Name *GetGenericSpecName(const parser::GenericSpec &);
@ -82,8 +86,57 @@ private:
friend void ShowImplicitRule(std::ostream &, const ImplicitRules &, char);
};
// Track statement source locations and save messages.
class MessageHandler {
public:
void set_messages(Messages &messages) { messages_ = &messages; }
const SourceName *currStmtSource() { return currStmtSource_; }
void set_currStmtSource(const SourceName *);
// Emit a message
Message &Say(Message &&);
// Emit a message associated with the current statement source.
Message &Say(MessageFixedText &&);
// Emit a message about a SourceName
Message &Say(const SourceName &, MessageFixedText &&);
// Emit a formatted message associated with a source location.
Message &Say(const SourceName &, MessageFixedText &&, const SourceName &);
Message &Say(const SourceName &, MessageFixedText &&, const SourceName &,
const SourceName &);
private:
// Where messages are emitted:
Messages *messages_{nullptr};
// Source location of current statement; null if not in a statement
const SourceName *currStmtSource_{nullptr};
};
class BaseVisitor {
public:
template<typename T> void Walk(const T &);
void set_this(ResolveNamesVisitor *x) { this_ = x; }
MessageHandler &messageHandler() { return messageHandler_; }
const SourceName *currStmtSource();
SemanticsContext &context() const { return *context_; }
void set_context(SemanticsContext &);
template<typename... A>
Message &Say(const parser::Name &name, MessageFixedText &&msg, A... args) {
return Say(name.source, std::move(msg), std::forward<A>(args)...);
}
template<typename... A> Message &Say(A... args) {
return messageHandler_.Say(std::forward<A>(args)...);
}
private:
ResolveNamesVisitor *this_{nullptr};
SemanticsContext *context_{nullptr};
MessageHandler messageHandler_;
};
// Provide Post methods to collect attributes into a member variable.
class AttrsVisitor {
class AttrsVisitor : public virtual BaseVisitor {
public:
bool BeginAttrs(); // always returns true
Attrs GetAttrs();
@ -166,9 +219,6 @@ public:
bool Pre(const parser::TypeGuardStmt &);
void Post(const parser::TypeGuardStmt &);
SemanticsContext &context() const { return *context_; }
void set_context(SemanticsContext &context) { context_ = &context; }
protected:
std::unique_ptr<DeclTypeSpec> &GetDeclTypeSpec();
void BeginDeclTypeSpec();
@ -180,7 +230,6 @@ protected:
private:
bool expectDeclTypeSpec_{false}; // should only see decl-type-spec when true
std::unique_ptr<DeclTypeSpec> declTypeSpec_;
SemanticsContext *context_{nullptr};
DerivedTypeSpec *derivedTypeSpec_{nullptr};
const parser::Name *derivedTypeName_{nullptr};
@ -190,47 +239,8 @@ private:
ParamValue GetParamValue(const parser::TypeParamValue &);
};
// Track statement source locations and save messages.
class MessageHandler {
public:
using Message = parser::Message;
using MessageFixedText = parser::MessageFixedText;
using MessageFormattedText = parser::MessageFormattedText;
void set_messages(parser::Messages &messages) { messages_ = &messages; }
const SourceName *currStmtSource() { return currStmtSource_; }
void set_currStmtSource(const SourceName *x) { currStmtSource_ = x; }
// Emit a message
Message &Say(Message &&);
// Emit a message associated with the current statement source.
Message &Say(MessageFixedText &&);
// Emit a message about a SourceName
Message &Say(const SourceName &, MessageFixedText &&);
// Emit a formatted message associated with a source location.
Message &Say(const SourceName &, MessageFixedText &&, const SourceName &);
Message &Say(const SourceName &, MessageFixedText &&, const SourceName &,
const SourceName &);
template<typename... A>
Message &Say(const parser::Name &name, MessageFixedText &&msg, A... args) {
return Say(name.source, std::move(msg), std::forward<A>(args)...);
}
// Special messages: already declared; about a type; two names & locations
void SayAlreadyDeclared(const parser::Name &, const Symbol &);
void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &);
void Say2(const parser::Name &, MessageFixedText &&, const Symbol &,
MessageFixedText &&);
private:
// Where messages are emitted:
parser::Messages *messages_{nullptr};
// Source location of current statement; null if not in a statement
const SourceName *currStmtSource_{nullptr};
};
// Visit ImplicitStmt and related parse tree nodes and updates implicit rules.
class ImplicitRulesVisitor : public DeclTypeSpecVisitor, public MessageHandler {
class ImplicitRulesVisitor : public DeclTypeSpecVisitor {
public:
using DeclTypeSpecVisitor::Post;
using DeclTypeSpecVisitor::Pre;
@ -242,11 +252,6 @@ public:
bool Pre(const parser::ImplicitSpec &);
void Post(const parser::ImplicitSpec &);
void set_context(SemanticsContext &context) {
DeclTypeSpecVisitor::set_context(context);
MessageHandler::set_messages(context.messages());
}
ImplicitRules &implicitRules() { return *implicitRules_; }
const ImplicitRules &implicitRules() const { return *implicitRules_; }
bool isImplicitNoneType() const {
@ -280,7 +285,7 @@ private:
// 4. DIMENSION :: x(10)
// 5. TODO: COMMON x(10)
// 6. TODO: BasedPointerStmt
class ArraySpecVisitor {
class ArraySpecVisitor : public virtual BaseVisitor {
public:
bool Pre(const parser::ArraySpec &);
void Post(const parser::AttrSpec &) { PostAttrSpec(); }
@ -311,9 +316,6 @@ private:
// Manage a stack of Scopes
class ScopeHandler : public ImplicitRulesVisitor {
public:
template<typename T> void Walk(const T &);
void set_this(ResolveNamesVisitor *x) { this_ = x; }
Scope &currScope() { return *currScope_; }
// The enclosing scope, skipping blocks and derived types.
Scope &InclusiveScope();
@ -330,16 +332,21 @@ public:
ImplicitRulesVisitor::ClearScopes();
}
//TSK: is this the right place???
template<typename T> bool Pre(const parser::Statement<T> &x) {
set_currStmtSource(&x.source);
messageHandler().set_currStmtSource(&x.source);
currScope_->AddSourceRange(x.source);
return true;
}
template<typename T> void Post(const parser::Statement<T> &) {
set_currStmtSource(nullptr);
messageHandler().set_currStmtSource(nullptr);
}
// Special messages: already declared; about a type; two names & locations
void SayAlreadyDeclared(const parser::Name &, const Symbol &);
void SayDerivedType(const SourceName &, MessageFixedText &&, const Scope &);
void Say2(const parser::Name &, MessageFixedText &&, const Symbol &,
MessageFixedText &&);
// Search for symbol by name in current and containing scopes
Symbol *FindSymbol(const parser::Name &);
Symbol *FindSymbol(const Scope &, const parser::Name &);
@ -909,6 +916,19 @@ void ShowImplicitRule(
}
}
template<typename T> void BaseVisitor::Walk(const T &x) {
parser::Walk(x, *this_);
}
const SourceName *BaseVisitor::currStmtSource() {
return messageHandler_.currStmtSource();
}
void BaseVisitor::set_context(SemanticsContext &context) {
context_ = &context;
messageHandler_.set_messages(context.messages());
}
// AttrsVisitor implementation
bool AttrsVisitor::BeginAttrs() {
@ -1087,39 +1107,25 @@ int DeclTypeSpecVisitor::GetKindParamValue(
// MessageHandler implementation
MessageHandler::Message &MessageHandler::Say(MessageFixedText &&msg) {
void MessageHandler::set_currStmtSource(const SourceName *source) {
currStmtSource_ = source;
}
Message &MessageHandler::Say(MessageFixedText &&msg) {
CHECK(currStmtSource_);
return messages_->Say(*currStmtSource_, std::move(msg));
}
MessageHandler::Message &MessageHandler::Say(
const SourceName &name, MessageFixedText &&msg) {
Message &MessageHandler::Say(const SourceName &name, MessageFixedText &&msg) {
return Say(name, std::move(msg), name);
}
MessageHandler::Message &MessageHandler::Say(const SourceName &location,
MessageFixedText &&msg, const SourceName &arg1) {
Message &MessageHandler::Say(const SourceName &location, MessageFixedText &&msg,
const SourceName &arg1) {
return messages_->Say(location, std::move(msg), arg1.ToString().c_str());
}
MessageHandler::Message &MessageHandler::Say(const SourceName &location,
MessageFixedText &&msg, const SourceName &arg1, const SourceName &arg2) {
Message &MessageHandler::Say(const SourceName &location, MessageFixedText &&msg,
const SourceName &arg1, const SourceName &arg2) {
return messages_->Say(location, std::move(msg), arg1.ToString().c_str(),
arg2.ToString().c_str());
}
void MessageHandler::SayAlreadyDeclared(
const parser::Name &name, const Symbol &prev) {
Say2(name, "'%s' is already declared in this scoping unit"_err_en_US, prev,
"Previous declaration of '%s'"_en_US);
}
void MessageHandler::SayDerivedType(
const SourceName &name, MessageFixedText &&msg, const Scope &type) {
Say(name, std::move(msg), name, type.name())
.Attach(type.name(), "Declaration of derived type '%s'"_en_US,
type.name().ToString().c_str());
}
void MessageHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
const Symbol &symbol, MessageFixedText &&msg2) {
Say(name.source, std::move(msg1))
.Attach(symbol.name(), msg2, symbol.name().ToString().c_str());
}
// ImplicitRulesVisitor implementation
@ -1306,6 +1312,23 @@ Bound ArraySpecVisitor::GetBound(const parser::SpecificationExpr &x) {
// ScopeHandler implementation
void ScopeHandler::SayAlreadyDeclared(
const parser::Name &name, const Symbol &prev) {
Say2(name, "'%s' is already declared in this scoping unit"_err_en_US, prev,
"Previous declaration of '%s'"_en_US);
}
void ScopeHandler::SayDerivedType(
const SourceName &name, MessageFixedText &&msg, const Scope &type) {
Say(name, std::move(msg), name, type.name())
.Attach(type.name(), "Declaration of derived type '%s'"_en_US,
type.name().ToString().c_str());
}
void ScopeHandler::Say2(const parser::Name &name, MessageFixedText &&msg1,
const Symbol &symbol, MessageFixedText &&msg2) {
Say(name.source, std::move(msg1))
.Attach(symbol.name(), msg2, symbol.name().ToString().c_str());
}
Scope &ScopeHandler::InclusiveScope() {
for (auto *scope{&currScope()};; scope = &scope->parent()) {
if (scope->kind() != Scope::Kind::Block &&
@ -2720,7 +2743,7 @@ bool DeclarationVisitor::OkToAddComponent(
for (bool inParent{false};; inParent = true) {
CHECK(scope->kind() == Scope::Kind::DerivedType);
if (auto *prev{FindInScope(*scope, name)}) {
parser::MessageFixedText msg{""_en_US};
auto msg{""_en_US};
if (isParentComp) {
msg = "Type cannot be extended as it has a component named"
" '%s'"_err_en_US;
@ -2747,10 +2770,6 @@ bool DeclarationVisitor::OkToAddComponent(
// ConstructVisitor implementation
template<typename T> void ScopeHandler::Walk(const T &x) {
parser::Walk(x, *this_);
}
bool ConstructVisitor::Pre(const parser::ConcurrentHeader &) {
BeginDeclTypeSpec();
return true;