173
|
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
|
|
15 namespace Fortran::parser {
|
|
16
|
|
17 void ParsingLog::clear() { perPos_.clear(); }
|
|
18
|
|
19 // In the logs, just use the addresses of the message texts to sort the
|
|
20 // map keys.
|
|
21 bool operator<(const MessageFixedText &x, const MessageFixedText &y) {
|
|
22 return x.text().begin() < y.text().begin();
|
|
23 }
|
|
24
|
|
25 bool 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
|
|
47 void 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
|
207
|
66 void ParsingLog::Dump(
|
|
67 llvm::raw_ostream &o, const AllCookedSources &allCooked) const {
|
173
|
68 for (const auto &posLog : perPos_) {
|
|
69 const char *at{reinterpret_cast<const char *>(posLog.first)};
|
|
70 for (const auto &tagLog : posLog.second.perTag) {
|
207
|
71 Message{at, tagLog.first}.Emit(o, allCooked, true);
|
173
|
72 auto &entry{tagLog.second};
|
|
73 o << " " << (entry.pass ? "pass" : "fail") << " " << entry.count << '\n';
|
207
|
74 entry.messages.Emit(o, allCooked);
|
173
|
75 }
|
|
76 }
|
|
77 }
|
|
78 } // namespace Fortran::parser
|