1 //===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===//
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 // This is a concrete diagnostic client, which buffers the diagnostic messages.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "flang/Frontend/TextDiagnosticBuffer.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/Support/ErrorHandling.h"
17 
18 using namespace Fortran::frontend;
19 
20 /// HandleDiagnostic - Store the errors, warnings, and notes that are
21 /// reported.
HandleDiagnostic(clang::DiagnosticsEngine::Level level,const clang::Diagnostic & info)22 void TextDiagnosticBuffer::HandleDiagnostic(
23     clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
24   // Default implementation (warnings_/errors count).
25   DiagnosticConsumer::HandleDiagnostic(level, info);
26 
27   llvm::SmallString<100> buf;
28   info.FormatDiagnostic(buf);
29   switch (level) {
30   default:
31     llvm_unreachable("Diagnostic not handled during diagnostic buffering!");
32   case clang::DiagnosticsEngine::Note:
33     all_.emplace_back(level, notes_.size());
34     notes_.emplace_back(info.getLocation(), std::string(buf.str()));
35     break;
36   case clang::DiagnosticsEngine::Warning:
37     all_.emplace_back(level, warnings_.size());
38     warnings_.emplace_back(info.getLocation(), std::string(buf.str()));
39     break;
40   case clang::DiagnosticsEngine::Remark:
41     all_.emplace_back(level, remarks_.size());
42     remarks_.emplace_back(info.getLocation(), std::string(buf.str()));
43     break;
44   case clang::DiagnosticsEngine::Error:
45   case clang::DiagnosticsEngine::Fatal:
46     all_.emplace_back(level, errors_.size());
47     errors_.emplace_back(info.getLocation(), std::string(buf.str()));
48     break;
49   }
50 }
51 
FlushDiagnostics(clang::DiagnosticsEngine & Diags) const52 void TextDiagnosticBuffer::FlushDiagnostics(
53     clang::DiagnosticsEngine &Diags) const {
54   for (const auto &i : all_) {
55     auto Diag = Diags.Report(Diags.getCustomDiagID(i.first, "%0"));
56     switch (i.first) {
57     default:
58       llvm_unreachable("Diagnostic not handled during diagnostic flushing!");
59     case clang::DiagnosticsEngine::Note:
60       Diag << notes_[i.second].second;
61       break;
62     case clang::DiagnosticsEngine::Warning:
63       Diag << warnings_[i.second].second;
64       break;
65     case clang::DiagnosticsEngine::Remark:
66       Diag << remarks_[i.second].second;
67       break;
68     case clang::DiagnosticsEngine::Error:
69     case clang::DiagnosticsEngine::Fatal:
70       Diag << errors_[i.second].second;
71       break;
72     }
73   }
74 }
75