79 lines · cpp
1//===-- lib/Parser/instrumented-parser.cpp --------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Parser/instrumented-parser.h"10#include "flang/Parser/message.h"11#include "flang/Parser/provenance.h"12#include "llvm/Support/raw_ostream.h"13#include <map>14 15namespace Fortran::parser {16 17void ParsingLog::clear() { perPos_.clear(); }18 19// In the logs, just use the addresses of the message texts to sort the20// map keys.21bool operator<(const MessageFixedText &x, const MessageFixedText &y) {22 return x.text().begin() < y.text().begin();23}24 25bool ParsingLog::Fails(26 const char *at, const MessageFixedText &tag, ParseState &state) {27 std::size_t offset{reinterpret_cast<std::size_t>(at)};28 auto posIter{perPos_.find(offset)};29 if (posIter == perPos_.end()) {30 return false;31 }32 auto tagIter{posIter->second.perTag.find(tag)};33 if (tagIter == posIter->second.perTag.end()) {34 return false;35 }36 auto &entry{tagIter->second};37 if (entry.deferred && !state.deferMessages()) {38 return false; // don't fail fast, we want to generate messages39 }40 ++entry.count;41 if (!state.deferMessages()) {42 state.messages().Copy(entry.messages);43 }44 return !entry.pass;45}46 47void ParsingLog::Note(const char *at, const MessageFixedText &tag, bool pass,48 const ParseState &state) {49 std::size_t offset{reinterpret_cast<std::size_t>(at)};50 auto &entry{perPos_[offset].perTag[tag]};51 if (++entry.count == 1) {52 entry.pass = pass;53 entry.deferred = state.deferMessages();54 if (!entry.deferred) {55 entry.messages.Copy(state.messages());56 }57 } else {58 CHECK(entry.pass == pass);59 if (entry.deferred && !state.deferMessages()) {60 entry.deferred = false;61 entry.messages.Copy(state.messages());62 }63 }64}65 66void ParsingLog::Dump(67 llvm::raw_ostream &o, const AllCookedSources &allCooked) const {68 for (const auto &posLog : perPos_) {69 const char *at{reinterpret_cast<const char *>(posLog.first)};70 for (const auto &tagLog : posLog.second.perTag) {71 Message{at, tagLog.first}.Emit(o, allCooked, true);72 auto &entry{tagLog.second};73 o << " " << (entry.pass ? "pass" : "fail") << " " << entry.count << '\n';74 entry.messages.Emit(o, allCooked);75 }76 }77}78} // namespace Fortran::parser79