Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/Common/ErrorHandler.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ErrorHandler.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 "lld/Common/ErrorHandler.h"
10
11
#include "lld/Common/Threads.h"
12
13
#include "llvm/ADT/Twine.h"
14
#include "llvm/IR/DiagnosticInfo.h"
15
#include "llvm/IR/DiagnosticPrinter.h"
16
#include "llvm/Support/ManagedStatic.h"
17
#include "llvm/Support/raw_ostream.h"
18
#include <mutex>
19
#include <regex>
20
21
#if !defined(_MSC_VER) && !defined(__MINGW32__)
22
#include <unistd.h>
23
#endif
24
25
using namespace llvm;
26
using namespace lld;
27
28
// The functions defined in this file can be called from multiple threads,
29
// but outs() or errs() are not thread-safe. We protect them using a mutex.
30
static std::mutex mu;
31
32
// Prints "\n" or does nothing, depending on Msg contents of
33
// the previous call of this function.
34
3.65k
static void newline(raw_ostream *errorOS, const Twine &msg) {
35
3.65k
  // True if the previous error message contained "\n".
36
3.65k
  // We want to separate multi-line error messages with a newline.
37
3.65k
  static bool flag;
38
3.65k
39
3.65k
  if (flag)
40
120
    *errorOS << "\n";
41
3.65k
  flag = StringRef(msg.str()).contains('\n');
42
3.65k
}
43
44
291k
ErrorHandler &lld::errorHandler() {
45
291k
  static ErrorHandler handler;
46
291k
  return handler;
47
291k
}
48
49
0
void lld::exitLld(int val) {
50
0
  // Delete any temporary file, while keeping the memory mapping open.
51
0
  if (errorHandler().outputBuffer)
52
0
    errorHandler().outputBuffer->discard();
53
0
54
0
  // Dealloc/destroy ManagedStatic variables before calling
55
0
  // _exit(). In a non-LTO build, this is a nop. In an LTO
56
0
  // build allows us to get the output of -time-passes.
57
0
  llvm_shutdown();
58
0
59
0
  outs().flush();
60
0
  errs().flush();
61
0
  _exit(val);
62
0
}
63
64
3
void lld::diagnosticHandler(const DiagnosticInfo &di) {
65
3
  SmallString<128> s;
66
3
  raw_svector_ostream os(s);
67
3
  DiagnosticPrinterRawOStream dp(os);
68
3
  di.print(dp);
69
3
  switch (di.getSeverity()) {
70
3
  case DS_Error:
71
1
    error(s);
72
1
    break;
73
3
  case DS_Warning:
74
2
    warn(s);
75
2
    break;
76
3
  case DS_Remark:
77
0
  case DS_Note:
78
0
    message(s);
79
0
    break;
80
3
  }
81
3
}
82
83
692
void lld::checkError(Error e) {
84
692
  handleAllErrors(std::move(e),
85
692
                  [&](ErrorInfoBase &eib) 
{ error(eib.message()); }4
);
86
692
}
87
88
11
static std::string getLocation(std::string msg, std::string defaultMsg) {
89
11
  static std::vector<std::regex> Regexes{
90
11
      std::regex(R"(^undefined symbol:.*\n>>> referenced by (\S+):(\d+)\n.*)"),
91
11
      std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"),
92
11
      std::regex(
93
11
          R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"),
94
11
      std::regex(
95
11
          R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+).*)"),
96
11
      std::regex(
97
11
          R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"),
98
11
      std::regex(
99
11
          R"(^undefined (internal|hidden|protected) symbol: .*\n>>> referenced by (\S+):(\d+)\n.*)"),
100
11
      std::regex(R"((\S+):(\d+): unclosed quote)"),
101
11
  };
102
11
103
11
  std::smatch Match;
104
47
  for (std::regex &Re : Regexes) {
105
47
    if (std::regex_search(msg, Match, Re)) {
106
8
      return Match.size() > 2 ? 
Match.str(1) + "(" + Match.str(2) + ")"6
107
8
                              : 
Match.str(1)2
;
108
8
    }
109
47
  }
110
11
  
return defaultMsg3
;
111
11
}
112
113
void ErrorHandler::printHeader(StringRef s, raw_ostream::Colors c,
114
1.85k
                               const Twine &msg) {
115
1.85k
116
1.85k
  if (vsDiagnostics) {
117
11
    // A Visual Studio-style error message starts with an error location.
118
11
    // If a location cannot be extracted then we default to LogName.
119
11
    *errorOS << getLocation(msg.str(), logName) << ": ";
120
1.84k
  } else {
121
1.84k
    *errorOS << logName << ": ";
122
1.84k
  }
123
1.85k
124
1.85k
  if (colorDiagnostics) {
125
8
    errorOS->changeColor(c, true);
126
8
    *errorOS << s;
127
8
    errorOS->resetColor();
128
1.84k
  } else {
129
1.84k
    *errorOS << s;
130
1.84k
  }
131
1.85k
}
132
133
19.0k
void ErrorHandler::log(const Twine &msg) {
134
19.0k
  if (verbose) {
135
276
    std::lock_guard<std::mutex> lock(mu);
136
276
    *errorOS << logName << ": " << msg << "\n";
137
276
  }
138
19.0k
}
139
140
288
void ErrorHandler::message(const Twine &msg) {
141
288
  std::lock_guard<std::mutex> lock(mu);
142
288
  outs() << msg << "\n";
143
288
  outs().flush();
144
288
}
145
146
844
void ErrorHandler::warn(const Twine &msg) {
147
844
  if (fatalWarnings) {
148
12
    error(msg);
149
12
    return;
150
12
  }
151
832
152
832
  std::lock_guard<std::mutex> lock(mu);
153
832
  newline(errorOS, msg);
154
832
  printHeader("warning: ", raw_ostream::MAGENTA, msg);
155
832
  *errorOS << msg << "\n";
156
832
}
157
158
2.82k
void ErrorHandler::error(const Twine &msg) {
159
2.82k
  std::lock_guard<std::mutex> lock(mu);
160
2.82k
  newline(errorOS, msg);
161
2.82k
162
2.82k
  if (errorLimit == 0 || 
errorCount < errorLimit2.75k
) {
163
1.01k
    printHeader("error: ", raw_ostream::RED, msg);
164
1.01k
    *errorOS << msg << "\n";
165
1.80k
  } else if (errorCount == errorLimit) {
166
6
    printHeader("error: ", raw_ostream::RED, msg);
167
6
    *errorOS << errorLimitExceededMsg << "\n";
168
6
    if (exitEarly)
169
0
      exitLld(1);
170
2.82k
  }
171
2.82k
172
2.82k
  ++errorCount;
173
2.82k
}
174
175
0
void ErrorHandler::fatal(const Twine &msg) {
176
0
  error(msg);
177
0
  exitLld(1);
178
0
}