1 //===-- lib/Parser/instrumented-parser.cpp --------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
15 namespace Fortran::parser
{
17 void ParsingLog::clear() { perPos_
.clear(); }
19 // In the logs, just use the addresses of the message texts to sort the
21 bool operator<(const MessageFixedText
&x
, const MessageFixedText
&y
) {
22 return x
.text().begin() < y
.text().begin();
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()) {
32 auto tagIter
{posIter
->second
.perTag
.find(tag
)};
33 if (tagIter
== posIter
->second
.perTag
.end()) {
36 auto &entry
{tagIter
->second
};
37 if (entry
.deferred
&& !state
.deferMessages()) {
38 return false; // don't fail fast, we want to generate messages
41 if (!state
.deferMessages()) {
42 state
.messages().Copy(entry
.messages
);
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) {
53 entry
.deferred
= state
.deferMessages();
54 if (!entry
.deferred
) {
55 entry
.messages
.Copy(state
.messages());
58 CHECK(entry
.pass
== pass
);
59 if (entry
.deferred
&& !state
.deferMessages()) {
60 entry
.deferred
= false;
61 entry
.messages
.Copy(state
.messages());
66 void 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
);
78 } // namespace Fortran::parser