Audit of every #include directive in flang/lib/ and flang/include/flang/: - Remove 423 #include directives (293 from lib/ translation units, 23 from lib-private headers, 107 from public headers) that are not needed: no entity declared by the removed header is used - directly or in any conditional-compilation branch (Windows, macOS, ARM/PowerPC, REAL(16)/REAL(2) configuration macros) - in the including file, and for headers no consumer in flang/lib, flang/tools, flang/unittests, or flang-rt relies on the include as a re-export. Load-bearing includes were examined and retained: textual .inc/.def expansions, tablegen pass-header declaration/definition pairings, dialect headers carrying generated-op interface dependencies, config-macro providers (e.g. float128.h ahead of matmul-instances.inc guards), and ADL formatting machinery (Evaluate/formatting.h). - Add 5 missing direct #includes in lib translation units that used entities only via now-removed transitive includes, and drop one vestigial 'using namespace Fortran::runtime;' whose declaring header no longer arrives transitively (nothing namespace-qualified from it was used), per the include rules in flang/docs/C++style.md. Assisted-by: AI
237 lines
8 KiB
C++
237 lines
8 KiB
C++
//===-- include/flang/Parser/parse-state.h ----------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef FORTRAN_PARSER_PARSE_STATE_H_
|
|
#define FORTRAN_PARSER_PARSE_STATE_H_
|
|
|
|
// Defines the ParseState type used as the argument for every parser's
|
|
// Parse member or static function. Tracks source provenance, context,
|
|
// accumulated messages, and an arbitrary UserState instance for parsing
|
|
// attempts. Must be efficient to duplicate and assign for backtracking
|
|
// and recovery during parsing!
|
|
|
|
#include "user-state.h"
|
|
#include "flang/Common/idioms.h"
|
|
#include "flang/Parser/message.h"
|
|
#include "flang/Parser/provenance.h"
|
|
#include "flang/Support/Fortran-features.h"
|
|
#include <cstddef>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
namespace Fortran::parser {
|
|
|
|
using common::LanguageFeature;
|
|
|
|
class ParseState {
|
|
public:
|
|
ParseState(const CookedSource &cooked)
|
|
: p_{cooked.AsCharBlock().begin()}, limit_{cooked.AsCharBlock().end()} {}
|
|
ParseState(const ParseState &that)
|
|
: p_{that.p_}, limit_{that.limit_}, context_{that.context_},
|
|
userState_{that.userState_}, inFixedForm_{that.inFixedForm_},
|
|
anyErrorRecovery_{that.anyErrorRecovery_},
|
|
anyConformanceViolation_{that.anyConformanceViolation_},
|
|
deferMessages_{that.deferMessages_},
|
|
anyDeferredMessages_{that.anyDeferredMessages_},
|
|
anyTokenMatched_{that.anyTokenMatched_} {}
|
|
ParseState(ParseState &&that)
|
|
: p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)},
|
|
context_{std::move(that.context_)}, userState_{that.userState_},
|
|
inFixedForm_{that.inFixedForm_},
|
|
anyErrorRecovery_{that.anyErrorRecovery_},
|
|
anyConformanceViolation_{that.anyConformanceViolation_},
|
|
deferMessages_{that.deferMessages_},
|
|
anyDeferredMessages_{that.anyDeferredMessages_},
|
|
anyTokenMatched_{that.anyTokenMatched_} {}
|
|
ParseState &operator=(const ParseState &that) {
|
|
p_ = that.p_, limit_ = that.limit_, context_ = that.context_;
|
|
userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
|
|
anyErrorRecovery_ = that.anyErrorRecovery_;
|
|
anyConformanceViolation_ = that.anyConformanceViolation_;
|
|
deferMessages_ = that.deferMessages_;
|
|
anyDeferredMessages_ = that.anyDeferredMessages_;
|
|
anyTokenMatched_ = that.anyTokenMatched_;
|
|
return *this;
|
|
}
|
|
ParseState &operator=(ParseState &&that) {
|
|
p_ = that.p_, limit_ = that.limit_, messages_ = std::move(that.messages_);
|
|
context_ = std::move(that.context_);
|
|
userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
|
|
anyErrorRecovery_ = that.anyErrorRecovery_;
|
|
anyConformanceViolation_ = that.anyConformanceViolation_;
|
|
deferMessages_ = that.deferMessages_;
|
|
anyDeferredMessages_ = that.anyDeferredMessages_;
|
|
anyTokenMatched_ = that.anyTokenMatched_;
|
|
return *this;
|
|
}
|
|
|
|
const Messages &messages() const { return messages_; }
|
|
Messages &messages() { return messages_; }
|
|
|
|
const Message::Reference &context() const { return context_; }
|
|
Message::Reference &context() { return context_; }
|
|
|
|
bool anyErrorRecovery() const { return anyErrorRecovery_; }
|
|
void set_anyErrorRecovery() { anyErrorRecovery_ = true; }
|
|
|
|
bool anyConformanceViolation() const { return anyConformanceViolation_; }
|
|
void set_anyConformanceViolation() { anyConformanceViolation_ = true; }
|
|
|
|
UserState *userState() const { return userState_; }
|
|
ParseState &set_userState(UserState *u) {
|
|
userState_ = u;
|
|
return *this;
|
|
}
|
|
|
|
bool inFixedForm() const { return inFixedForm_; }
|
|
ParseState &set_inFixedForm(bool yes = true) {
|
|
inFixedForm_ = yes;
|
|
return *this;
|
|
}
|
|
|
|
bool deferMessages() const { return deferMessages_; }
|
|
ParseState &set_deferMessages(bool yes = true) {
|
|
deferMessages_ = yes;
|
|
return *this;
|
|
}
|
|
|
|
bool anyDeferredMessages() const { return anyDeferredMessages_; }
|
|
ParseState &set_anyDeferredMessages(bool yes = true) {
|
|
anyDeferredMessages_ = yes;
|
|
return *this;
|
|
}
|
|
|
|
bool anyTokenMatched() const { return anyTokenMatched_; }
|
|
ParseState &set_anyTokenMatched(bool yes = true) {
|
|
anyTokenMatched_ = yes;
|
|
return *this;
|
|
}
|
|
|
|
const char *GetLocation() const { return p_; }
|
|
|
|
void PushContext(MessageFixedText text) {
|
|
auto m{new Message{p_, text}}; // reference-counted
|
|
m->SetContext(context_.get());
|
|
context_ = Message::Reference{m};
|
|
}
|
|
|
|
void PopContext() {
|
|
CHECK(context_);
|
|
context_ = context_->attachment();
|
|
}
|
|
|
|
template <typename... A> void Say(CharBlock range, A &&...args) {
|
|
if (deferMessages_) {
|
|
anyDeferredMessages_ = true;
|
|
} else {
|
|
messages_.Say(range, std::forward<A>(args)...).SetContext(context_.get());
|
|
}
|
|
}
|
|
template <typename... A> void Say(const MessageFixedText &text, A &&...args) {
|
|
Say(p_, text, std::forward<A>(args)...);
|
|
}
|
|
template <typename... A>
|
|
void Say(const MessageExpectedText &text, A &&...args) {
|
|
Say(p_, text, std::forward<A>(args)...);
|
|
}
|
|
|
|
void Nonstandard(LanguageFeature lf, const MessageFixedText &msg) {
|
|
Nonstandard(p_, lf, msg);
|
|
}
|
|
void Nonstandard(
|
|
CharBlock range, LanguageFeature lf, const MessageFixedText &msg) {
|
|
anyConformanceViolation_ = true;
|
|
if (userState_ && userState_->features().ShouldWarn(lf)) {
|
|
Say(range, msg);
|
|
}
|
|
}
|
|
bool IsNonstandardOk(LanguageFeature lf, const MessageFixedText &msg) {
|
|
if (userState_ && !userState_->features().IsEnabled(lf)) {
|
|
return false;
|
|
}
|
|
Nonstandard(lf, msg);
|
|
return true;
|
|
}
|
|
|
|
bool IsAtEnd() const { return p_ >= limit_; }
|
|
|
|
const char *UncheckedAdvance(std::size_t n = 1) {
|
|
const char *result{p_};
|
|
p_ += n;
|
|
return result;
|
|
}
|
|
|
|
std::optional<const char *> GetNextChar() {
|
|
if (p_ < limit_) {
|
|
return UncheckedAdvance();
|
|
} else {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
std::optional<const char *> PeekAtNextChar() const {
|
|
if (p_ < limit_) {
|
|
return p_;
|
|
} else {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
std::size_t BytesRemaining() const {
|
|
std::size_t remain = limit_ - p_;
|
|
return remain;
|
|
}
|
|
|
|
void CombineFailedParses(ParseState &&that) {
|
|
bool haveMessages{anyDeferredMessages_ || !messages_.empty()};
|
|
bool thatHasMessages{that.anyDeferredMessages_ || !that.messages_.empty()};
|
|
if (haveMessages && !thatHasMessages) {
|
|
// never discard messages
|
|
} else if (!that.anyTokenMatched_ && (haveMessages || !thatHasMessages)) {
|
|
// token matching is preferred
|
|
} else if ((!anyTokenMatched_ && that.anyTokenMatched_) ||
|
|
(!haveMessages && thatHasMessages) ||
|
|
that.p_ > p_) { // 'that' is better, or no worse and got further
|
|
anyTokenMatched_ = that.anyTokenMatched_;
|
|
p_ = that.p_;
|
|
messages_ = std::move(that.messages_);
|
|
anyDeferredMessages_ = that.anyDeferredMessages_;
|
|
anyConformanceViolation_ = that.anyConformanceViolation_;
|
|
anyErrorRecovery_ = that.anyErrorRecovery_;
|
|
} else if (that.p_ == p_) { // merge states
|
|
anyTokenMatched_ |= that.anyTokenMatched_;
|
|
messages_.Merge(std::move(that.messages_));
|
|
anyDeferredMessages_ |= that.anyDeferredMessages_;
|
|
anyConformanceViolation_ |= that.anyConformanceViolation_;
|
|
anyErrorRecovery_ |= that.anyErrorRecovery_;
|
|
}
|
|
}
|
|
|
|
private:
|
|
// Text remaining to be parsed
|
|
const char *p_{nullptr}, *limit_{nullptr};
|
|
|
|
// Accumulated messages and current nested context.
|
|
Messages messages_;
|
|
Message::Reference context_;
|
|
|
|
UserState *userState_{nullptr};
|
|
|
|
bool inFixedForm_{false};
|
|
bool anyErrorRecovery_{false};
|
|
bool anyConformanceViolation_{false};
|
|
bool deferMessages_{false};
|
|
bool anyDeferredMessages_{false};
|
|
bool anyTokenMatched_{false};
|
|
// NOTE: Any additions or modifications to these data members must also be
|
|
// reflected in the copy and move constructors defined at the top of this
|
|
// class definition!
|
|
};
|
|
} // namespace Fortran::parser
|
|
#endif // FORTRAN_PARSER_PARSE_STATE_H_
|