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-exception
6//
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 the
20// 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 messages
39 }
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::parser
79

source code of flang/lib/Parser/instrumented-parser.cpp