1 //===- TextDiagnosticPrinter.cpp ------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "mcld/LD/TextDiagnosticPrinter.h"
10 
11 #include "mcld/LinkerConfig.h"
12 
13 #include <llvm/Support/Signals.h>
14 
15 #include <string>
16 
17 namespace mcld {
18 
19 static const enum llvm::raw_ostream::Colors UnreachableColor =
20     llvm::raw_ostream::RED;
21 static const enum llvm::raw_ostream::Colors FatalColor =
22     llvm::raw_ostream::YELLOW;
23 static const enum llvm::raw_ostream::Colors ErrorColor = llvm::raw_ostream::RED;
24 static const enum llvm::raw_ostream::Colors WarningColor =
25     llvm::raw_ostream::MAGENTA;
26 static const enum llvm::raw_ostream::Colors DebugColor =
27     llvm::raw_ostream::CYAN;
28 static const enum llvm::raw_ostream::Colors NoteColor =
29     llvm::raw_ostream::GREEN;
30 static const enum llvm::raw_ostream::Colors IgnoreColor =
31     llvm::raw_ostream::BLUE;
32 
33 //===----------------------------------------------------------------------===//
34 // TextDiagnosticPrinter
TextDiagnosticPrinter(llvm::raw_ostream & pOStream,const LinkerConfig & pConfig)35 TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
36                                              const LinkerConfig& pConfig)
37     : m_OStream(pOStream), m_Config(pConfig), m_pInput(NULL) {
38 }
39 
~TextDiagnosticPrinter()40 TextDiagnosticPrinter::~TextDiagnosticPrinter() {
41 }
42 
43 /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
44 /// capturing it to a log as needed.
handleDiagnostic(DiagnosticEngine::Severity pSeverity,const Diagnostic & pInfo)45 void TextDiagnosticPrinter::handleDiagnostic(
46     DiagnosticEngine::Severity pSeverity,
47     const Diagnostic& pInfo) {
48   DiagnosticPrinter::handleDiagnostic(pSeverity, pInfo);
49 
50   std::string out_string;
51   pInfo.format(out_string);
52 
53   switch (pSeverity) {
54     case DiagnosticEngine::Unreachable: {
55       m_OStream.changeColor(UnreachableColor, true);
56       m_OStream << "Unreachable: ";
57       m_OStream.resetColor();
58       m_OStream << out_string << "\n";
59       break;
60     }
61     case DiagnosticEngine::Fatal: {
62       m_OStream.changeColor(FatalColor, true);
63       m_OStream << "Fatal: ";
64       m_OStream.resetColor();
65       m_OStream << out_string << "\n";
66       break;
67     }
68     case DiagnosticEngine::Error: {
69       m_OStream.changeColor(ErrorColor, true);
70       m_OStream << "Error: ";
71       m_OStream.resetColor();
72       m_OStream << out_string << "\n";
73       break;
74     }
75     case DiagnosticEngine::Warning: {
76       m_OStream.changeColor(WarningColor, true);
77       m_OStream << "Warning: ";
78       m_OStream.resetColor();
79       m_OStream << out_string << "\n";
80       break;
81     }
82     case DiagnosticEngine::Debug: {
83       // show debug message only if verbose >= 0
84       if (m_Config.options().verbose() >= 0) {
85         m_OStream.changeColor(DebugColor, true);
86         m_OStream << "Debug: ";
87         m_OStream.resetColor();
88         m_OStream << out_string << "\n";
89       }
90       break;
91     }
92     case DiagnosticEngine::Note: {
93       // show ignored message only if verbose >= 1
94       if (m_Config.options().verbose() >= 1) {
95         m_OStream.changeColor(NoteColor, true);
96         m_OStream << "Note: ";
97         m_OStream.resetColor();
98         m_OStream << out_string << "\n";
99       }
100       break;
101     }
102     case DiagnosticEngine::Ignore: {
103       // show ignored message only if verbose >= 2
104       if (m_Config.options().verbose() >= 2) {
105         m_OStream.changeColor(IgnoreColor, true);
106         m_OStream << "Ignore: ";
107         m_OStream.resetColor();
108         m_OStream << out_string << "\n";
109       }
110       break;
111     }
112     default:
113       break;
114   }
115 
116   switch (pSeverity) {
117     case DiagnosticEngine::Unreachable: {
118       m_OStream << "\n\n";
119       m_OStream.changeColor(llvm::raw_ostream::YELLOW);
120       m_OStream << "You encounter a bug of MCLinker, please report to:\n"
121                 << "  mclinker@googlegroups.com\n";
122       m_OStream.resetColor();
123     }
124     /** fall through **/
125     case DiagnosticEngine::Fatal: {
126       // If we reached here, we are failing ungracefully. Run the interrupt
127       // handlers
128       // to make sure any special cleanups get done, in particular that we
129       // remove
130       // files registered with RemoveFileOnSignal.
131       llvm::sys::RunInterruptHandlers();
132       exit(1);
133       break;
134     }
135     case DiagnosticEngine::Error: {
136       int16_t error_limit = m_Config.options().maxErrorNum();
137       if ((error_limit != -1) &&
138           (getNumErrors() > static_cast<unsigned>(error_limit))) {
139         m_OStream << "\n\n";
140         m_OStream.changeColor(llvm::raw_ostream::YELLOW);
141         m_OStream << "too many error messages (>" << error_limit << ")...\n";
142         m_OStream.resetColor();
143         llvm::sys::RunInterruptHandlers();
144         exit(1);
145       }
146       break;
147     }
148     case DiagnosticEngine::Warning: {
149       int16_t warning_limit = m_Config.options().maxWarnNum();
150       if ((warning_limit != -1) &&
151           (getNumWarnings() > static_cast<unsigned>(warning_limit))) {
152         m_OStream << "\n\n";
153         m_OStream.changeColor(llvm::raw_ostream::YELLOW);
154         m_OStream << "too many warning messages (>" << warning_limit
155                   << ")...\n";
156         m_OStream.resetColor();
157         llvm::sys::RunInterruptHandlers();
158         exit(1);
159       }
160     }
161     default:
162       break;
163   }
164 }
165 
beginInput(const Input & pInput,const LinkerConfig & pConfig)166 void TextDiagnosticPrinter::beginInput(const Input& pInput,
167                                        const LinkerConfig& pConfig) {
168   m_pInput = &pInput;
169 }
170 
endInput()171 void TextDiagnosticPrinter::endInput() {
172   m_pInput = NULL;
173 }
174 
175 }  // namespace mcld
176