Bug Summary

File:tools/clang/lib/Basic/Diagnostic.cpp
Warning:line 663, column 31
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Diagnostic.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/lib/Basic -I /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic -I /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/clang/lib/Basic -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp
1//===- Diagnostic.cpp - C Language Family Diagnostic Handling -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Diagnostic-related interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Basic/CharInfo.h"
16#include "clang/Basic/DiagnosticError.h"
17#include "clang/Basic/DiagnosticIDs.h"
18#include "clang/Basic/DiagnosticOptions.h"
19#include "clang/Basic/IdentifierTable.h"
20#include "clang/Basic/PartialDiagnostic.h"
21#include "clang/Basic/SourceLocation.h"
22#include "clang/Basic/SourceManager.h"
23#include "clang/Basic/Specifiers.h"
24#include "clang/Basic/TokenKinds.h"
25#include "llvm/ADT/SmallString.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringExtras.h"
28#include "llvm/ADT/StringRef.h"
29#include "llvm/Support/CrashRecoveryContext.h"
30#include "llvm/Support/Locale.h"
31#include "llvm/Support/raw_ostream.h"
32#include <algorithm>
33#include <cassert>
34#include <cstddef>
35#include <cstdint>
36#include <cstring>
37#include <limits>
38#include <string>
39#include <utility>
40#include <vector>
41
42using namespace clang;
43
44const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
45 DiagNullabilityKind nullability) {
46 StringRef string;
47 switch (nullability.first) {
48 case NullabilityKind::NonNull:
49 string = nullability.second ? "'nonnull'" : "'_Nonnull'";
50 break;
51
52 case NullabilityKind::Nullable:
53 string = nullability.second ? "'nullable'" : "'_Nullable'";
54 break;
55
56 case NullabilityKind::Unspecified:
57 string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
58 break;
59 }
60
61 DB.AddString(string);
62 return DB;
63}
64
65static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
66 StringRef Modifier, StringRef Argument,
67 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
68 SmallVectorImpl<char> &Output,
69 void *Cookie,
70 ArrayRef<intptr_t> QualTypeVals) {
71 StringRef Str = "<can't format argument>";
72 Output.append(Str.begin(), Str.end());
73}
74
75DiagnosticsEngine::DiagnosticsEngine(
76 IntrusiveRefCntPtr<DiagnosticIDs> diags,
77 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, DiagnosticConsumer *client,
78 bool ShouldOwnClient)
79 : Diags(std::move(diags)), DiagOpts(std::move(DiagOpts)) {
80 setClient(client, ShouldOwnClient);
81 ArgToStringFn = DummyArgToStringFn;
82
83 Reset();
84}
85
86DiagnosticsEngine::~DiagnosticsEngine() {
87 // If we own the diagnostic client, destroy it first so that it can access the
88 // engine from its destructor.
89 setClient(nullptr);
90}
91
92void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
93 bool ShouldOwnClient) {
94 Owner.reset(ShouldOwnClient ? client : nullptr);
95 Client = client;
96}
97
98void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
99 DiagStateOnPushStack.push_back(GetCurDiagState());
100}
101
102bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
103 if (DiagStateOnPushStack.empty())
104 return false;
105
106 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
107 // State changed at some point between push/pop.
108 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
109 }
110 DiagStateOnPushStack.pop_back();
111 return true;
112}
113
114void DiagnosticsEngine::Reset() {
115 ErrorOccurred = false;
116 UncompilableErrorOccurred = false;
117 FatalErrorOccurred = false;
118 UnrecoverableErrorOccurred = false;
119
120 NumWarnings = 0;
121 NumErrors = 0;
122 TrapNumErrorsOccurred = 0;
123 TrapNumUnrecoverableErrorsOccurred = 0;
124
125 CurDiagID = std::numeric_limits<unsigned>::max();
126 LastDiagLevel = DiagnosticIDs::Ignored;
127 DelayedDiagID = 0;
128
129 // Clear state related to #pragma diagnostic.
130 DiagStates.clear();
131 DiagStatesByLoc.clear();
132 DiagStateOnPushStack.clear();
133
134 // Create a DiagState and DiagStatePoint representing diagnostic changes
135 // through command-line.
136 DiagStates.emplace_back();
137 DiagStatesByLoc.appendFirst(&DiagStates.back());
138}
139
140void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
141 StringRef Arg2) {
142 if (DelayedDiagID)
143 return;
144
145 DelayedDiagID = DiagID;
146 DelayedDiagArg1 = Arg1.str();
147 DelayedDiagArg2 = Arg2.str();
148}
149
150void DiagnosticsEngine::ReportDelayed() {
151 unsigned ID = DelayedDiagID;
152 DelayedDiagID = 0;
153 Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
154}
155
156void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
157 assert(Files.empty() && "not first")(static_cast <bool> (Files.empty() && "not first"
) ? void (0) : __assert_fail ("Files.empty() && \"not first\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 157, __extension__ __PRETTY_FUNCTION__))
;
158 FirstDiagState = CurDiagState = State;
159 CurDiagStateLoc = SourceLocation();
160}
161
162void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr,
163 SourceLocation Loc,
164 DiagState *State) {
165 CurDiagState = State;
166 CurDiagStateLoc = Loc;
167
168 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
169 unsigned Offset = Decomp.second;
170 for (File *F = getFile(SrcMgr, Decomp.first); F;
171 Offset = F->ParentOffset, F = F->Parent) {
172 F->HasLocalTransitions = true;
173 auto &Last = F->StateTransitions.back();
174 assert(Last.Offset <= Offset && "state transitions added out of order")(static_cast <bool> (Last.Offset <= Offset &&
"state transitions added out of order") ? void (0) : __assert_fail
("Last.Offset <= Offset && \"state transitions added out of order\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 174, __extension__ __PRETTY_FUNCTION__))
;
175
176 if (Last.Offset == Offset) {
177 if (Last.State == State)
178 break;
179 Last.State = State;
180 continue;
181 }
182
183 F->StateTransitions.push_back({State, Offset});
184 }
185}
186
187DiagnosticsEngine::DiagState *
188DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr,
189 SourceLocation Loc) const {
190 // Common case: we have not seen any diagnostic pragmas.
191 if (Files.empty())
192 return FirstDiagState;
193
194 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedLoc(Loc);
195 const File *F = getFile(SrcMgr, Decomp.first);
196 return F->lookup(Decomp.second);
197}
198
199DiagnosticsEngine::DiagState *
200DiagnosticsEngine::DiagStateMap::File::lookup(unsigned Offset) const {
201 auto OnePastIt = std::upper_bound(
202 StateTransitions.begin(), StateTransitions.end(), Offset,
203 [](unsigned Offset, const DiagStatePoint &P) {
204 return Offset < P.Offset;
205 });
206 assert(OnePastIt != StateTransitions.begin() && "missing initial state")(static_cast <bool> (OnePastIt != StateTransitions.begin
() && "missing initial state") ? void (0) : __assert_fail
("OnePastIt != StateTransitions.begin() && \"missing initial state\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 206, __extension__ __PRETTY_FUNCTION__))
;
207 return OnePastIt[-1].State;
208}
209
210DiagnosticsEngine::DiagStateMap::File *
211DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
212 FileID ID) const {
213 // Get or insert the File for this ID.
214 auto Range = Files.equal_range(ID);
215 if (Range.first != Range.second)
216 return &Range.first->second;
217 auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
218
219 // We created a new File; look up the diagnostic state at the start of it and
220 // initialize it.
221 if (ID.isValid()) {
222 std::pair<FileID, unsigned> Decomp = SrcMgr.getDecomposedIncludedLoc(ID);
223 F.Parent = getFile(SrcMgr, Decomp.first);
224 F.ParentOffset = Decomp.second;
225 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
226 } else {
227 // This is the (imaginary) root file into which we pretend all top-level
228 // files are included; it descends from the initial state.
229 //
230 // FIXME: This doesn't guarantee that we use the same ordering as
231 // isBeforeInTranslationUnit in the cases where someone invented another
232 // top-level file and added diagnostic pragmas to it. See the code at the
233 // end of isBeforeInTranslationUnit for the quirks it deals with.
234 F.StateTransitions.push_back({FirstDiagState, 0});
235 }
236 return &F;
237}
238
239void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
240 StringRef DiagName) const {
241 llvm::errs() << "diagnostic state at ";
242 CurDiagStateLoc.dump(SrcMgr);
243 llvm::errs() << ": " << CurDiagState << "\n";
244
245 for (auto &F : Files) {
246 FileID ID = F.first;
247 File &File = F.second;
248
249 bool PrintedOuterHeading = false;
250 auto PrintOuterHeading = [&] {
251 if (PrintedOuterHeading) return;
252 PrintedOuterHeading = true;
253
254 llvm::errs() << "File " << &File << " <FileID " << ID.getHashValue()
255 << ">: " << SrcMgr.getBuffer(ID)->getBufferIdentifier();
256 if (F.second.Parent) {
257 std::pair<FileID, unsigned> Decomp =
258 SrcMgr.getDecomposedIncludedLoc(ID);
259 assert(File.ParentOffset == Decomp.second)(static_cast <bool> (File.ParentOffset == Decomp.second
) ? void (0) : __assert_fail ("File.ParentOffset == Decomp.second"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 259, __extension__ __PRETTY_FUNCTION__))
;
260 llvm::errs() << " parent " << File.Parent << " <FileID "
261 << Decomp.first.getHashValue() << "> ";
262 SrcMgr.getLocForStartOfFile(Decomp.first)
263 .getLocWithOffset(Decomp.second)
264 .dump(SrcMgr);
265 }
266 if (File.HasLocalTransitions)
267 llvm::errs() << " has_local_transitions";
268 llvm::errs() << "\n";
269 };
270
271 if (DiagName.empty())
272 PrintOuterHeading();
273
274 for (DiagStatePoint &Transition : File.StateTransitions) {
275 bool PrintedInnerHeading = false;
276 auto PrintInnerHeading = [&] {
277 if (PrintedInnerHeading) return;
278 PrintedInnerHeading = true;
279
280 PrintOuterHeading();
281 llvm::errs() << " ";
282 SrcMgr.getLocForStartOfFile(ID)
283 .getLocWithOffset(Transition.Offset)
284 .dump(SrcMgr);
285 llvm::errs() << ": state " << Transition.State << ":\n";
286 };
287
288 if (DiagName.empty())
289 PrintInnerHeading();
290
291 for (auto &Mapping : *Transition.State) {
292 StringRef Option =
293 DiagnosticIDs::getWarningOptionForDiag(Mapping.first);
294 if (!DiagName.empty() && DiagName != Option)
295 continue;
296
297 PrintInnerHeading();
298 llvm::errs() << " ";
299 if (Option.empty())
300 llvm::errs() << "<unknown " << Mapping.first << ">";
301 else
302 llvm::errs() << Option;
303 llvm::errs() << ": ";
304
305 switch (Mapping.second.getSeverity()) {
306 case diag::Severity::Ignored: llvm::errs() << "ignored"; break;
307 case diag::Severity::Remark: llvm::errs() << "remark"; break;
308 case diag::Severity::Warning: llvm::errs() << "warning"; break;
309 case diag::Severity::Error: llvm::errs() << "error"; break;
310 case diag::Severity::Fatal: llvm::errs() << "fatal"; break;
311 }
312
313 if (!Mapping.second.isUser())
314 llvm::errs() << " default";
315 if (Mapping.second.isPragma())
316 llvm::errs() << " pragma";
317 if (Mapping.second.hasNoWarningAsError())
318 llvm::errs() << " no-error";
319 if (Mapping.second.hasNoErrorAsFatal())
320 llvm::errs() << " no-fatal";
321 if (Mapping.second.wasUpgradedFromWarning())
322 llvm::errs() << " overruled";
323 llvm::errs() << "\n";
324 }
325 }
326 }
327}
328
329void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
330 SourceLocation Loc) {
331 assert(Loc.isValid() && "Adding invalid loc point")(static_cast <bool> (Loc.isValid() && "Adding invalid loc point"
) ? void (0) : __assert_fail ("Loc.isValid() && \"Adding invalid loc point\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 331, __extension__ __PRETTY_FUNCTION__))
;
332 DiagStatesByLoc.append(*SourceMgr, Loc, State);
333}
334
335void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
336 SourceLocation L) {
337 assert(Diag < diag::DIAG_UPPER_LIMIT &&(static_cast <bool> (Diag < diag::DIAG_UPPER_LIMIT &&
"Can only map builtin diagnostics") ? void (0) : __assert_fail
("Diag < diag::DIAG_UPPER_LIMIT && \"Can only map builtin diagnostics\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 338, __extension__ __PRETTY_FUNCTION__))
338 "Can only map builtin diagnostics")(static_cast <bool> (Diag < diag::DIAG_UPPER_LIMIT &&
"Can only map builtin diagnostics") ? void (0) : __assert_fail
("Diag < diag::DIAG_UPPER_LIMIT && \"Can only map builtin diagnostics\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 338, __extension__ __PRETTY_FUNCTION__))
;
339 assert((Diags->isBuiltinWarningOrExtension(Diag) ||(static_cast <bool> ((Diags->isBuiltinWarningOrExtension
(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity
::Error)) && "Cannot map errors into warnings!") ? void
(0) : __assert_fail ("(Diags->isBuiltinWarningOrExtension(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) && \"Cannot map errors into warnings!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 341, __extension__ __PRETTY_FUNCTION__))
340 (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&(static_cast <bool> ((Diags->isBuiltinWarningOrExtension
(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity
::Error)) && "Cannot map errors into warnings!") ? void
(0) : __assert_fail ("(Diags->isBuiltinWarningOrExtension(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) && \"Cannot map errors into warnings!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 341, __extension__ __PRETTY_FUNCTION__))
341 "Cannot map errors into warnings!")(static_cast <bool> ((Diags->isBuiltinWarningOrExtension
(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity
::Error)) && "Cannot map errors into warnings!") ? void
(0) : __assert_fail ("(Diags->isBuiltinWarningOrExtension(Diag) || (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) && \"Cannot map errors into warnings!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 341, __extension__ __PRETTY_FUNCTION__))
;
342 assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location")(static_cast <bool> ((L.isInvalid() || SourceMgr) &&
"No SourceMgr for valid location") ? void (0) : __assert_fail
("(L.isInvalid() || SourceMgr) && \"No SourceMgr for valid location\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 342, __extension__ __PRETTY_FUNCTION__))
;
343
344 // Don't allow a mapping to a warning override an error/fatal mapping.
345 bool WasUpgradedFromWarning = false;
346 if (Map == diag::Severity::Warning) {
347 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
348 if (Info.getSeverity() == diag::Severity::Error ||
349 Info.getSeverity() == diag::Severity::Fatal) {
350 Map = Info.getSeverity();
351 WasUpgradedFromWarning = true;
352 }
353 }
354 DiagnosticMapping Mapping = makeUserMapping(Map, L);
355 Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
356
357 // Common case; setting all the diagnostics of a group in one place.
358 if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
359 DiagStatesByLoc.getCurDiagState()) {
360 // FIXME: This is theoretically wrong: if the current state is shared with
361 // some other location (via push/pop) we will change the state for that
362 // other location as well. This cannot currently happen, as we can't update
363 // the diagnostic state at the same location at which we pop.
364 DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
365 return;
366 }
367
368 // A diagnostic pragma occurred, create a new DiagState initialized with
369 // the current one and a new DiagStatePoint to record at which location
370 // the new state became active.
371 DiagStates.push_back(*GetCurDiagState());
372 DiagStates.back().setMapping(Diag, Mapping);
373 PushDiagStatePoint(&DiagStates.back(), L);
374}
375
376bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
377 StringRef Group, diag::Severity Map,
378 SourceLocation Loc) {
379 // Get the diagnostics in this group.
380 SmallVector<diag::kind, 256> GroupDiags;
381 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
382 return true;
383
384 // Set the mapping.
385 for (diag::kind Diag : GroupDiags)
386 setSeverity(Diag, Map, Loc);
387
388 return false;
389}
390
391bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
392 bool Enabled) {
393 // If we are enabling this feature, just set the diagnostic mappings to map to
394 // errors.
395 if (Enabled)
396 return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
397 diag::Severity::Error);
398
399 // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
400 // potentially downgrade anything already mapped to be a warning.
401
402 // Get the diagnostics in this group.
403 SmallVector<diag::kind, 8> GroupDiags;
404 if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
405 GroupDiags))
406 return true;
407
408 // Perform the mapping change.
409 for (diag::kind Diag : GroupDiags) {
410 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
411
412 if (Info.getSeverity() == diag::Severity::Error ||
413 Info.getSeverity() == diag::Severity::Fatal)
414 Info.setSeverity(diag::Severity::Warning);
415
416 Info.setNoWarningAsError(true);
417 }
418
419 return false;
420}
421
422bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
423 bool Enabled) {
424 // If we are enabling this feature, just set the diagnostic mappings to map to
425 // fatal errors.
426 if (Enabled)
427 return setSeverityForGroup(diag::Flavor::WarningOrError, Group,
428 diag::Severity::Fatal);
429
430 // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,
431 // and potentially downgrade anything already mapped to be a fatal error.
432
433 // Get the diagnostics in this group.
434 SmallVector<diag::kind, 8> GroupDiags;
435 if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
436 GroupDiags))
437 return true;
438
439 // Perform the mapping change.
440 for (diag::kind Diag : GroupDiags) {
441 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
442
443 if (Info.getSeverity() == diag::Severity::Fatal)
444 Info.setSeverity(diag::Severity::Error);
445
446 Info.setNoErrorAsFatal(true);
447 }
448
449 return false;
450}
451
452void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor,
453 diag::Severity Map,
454 SourceLocation Loc) {
455 // Get all the diagnostics.
456 std::vector<diag::kind> AllDiags;
457 DiagnosticIDs::getAllDiagnostics(Flavor, AllDiags);
458
459 // Set the mapping.
460 for (diag::kind Diag : AllDiags)
461 if (Diags->isBuiltinWarningOrExtension(Diag))
462 setSeverity(Diag, Map, Loc);
463}
464
465void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
466 assert(CurDiagID == std::numeric_limits<unsigned>::max() &&(static_cast <bool> (CurDiagID == std::numeric_limits<
unsigned>::max() && "Multiple diagnostics in flight at once!"
) ? void (0) : __assert_fail ("CurDiagID == std::numeric_limits<unsigned>::max() && \"Multiple diagnostics in flight at once!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 467, __extension__ __PRETTY_FUNCTION__))
467 "Multiple diagnostics in flight at once!")(static_cast <bool> (CurDiagID == std::numeric_limits<
unsigned>::max() && "Multiple diagnostics in flight at once!"
) ? void (0) : __assert_fail ("CurDiagID == std::numeric_limits<unsigned>::max() && \"Multiple diagnostics in flight at once!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 467, __extension__ __PRETTY_FUNCTION__))
;
468
469 CurDiagLoc = storedDiag.getLocation();
470 CurDiagID = storedDiag.getID();
471 NumDiagArgs = 0;
472
473 DiagRanges.clear();
474 DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end());
475
476 DiagFixItHints.clear();
477 DiagFixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end());
478
479 assert(Client && "DiagnosticConsumer not set!")(static_cast <bool> (Client && "DiagnosticConsumer not set!"
) ? void (0) : __assert_fail ("Client && \"DiagnosticConsumer not set!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 479, __extension__ __PRETTY_FUNCTION__))
;
480 Level DiagLevel = storedDiag.getLevel();
481 Diagnostic Info(this, storedDiag.getMessage());
482 Client->HandleDiagnostic(DiagLevel, Info);
483 if (Client->IncludeInDiagnosticCounts()) {
484 if (DiagLevel == DiagnosticsEngine::Warning)
485 ++NumWarnings;
486 }
487
488 CurDiagID = std::numeric_limits<unsigned>::max();
489}
490
491bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
492 assert(getClient() && "DiagnosticClient not set!")(static_cast <bool> (getClient() && "DiagnosticClient not set!"
) ? void (0) : __assert_fail ("getClient() && \"DiagnosticClient not set!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 492, __extension__ __PRETTY_FUNCTION__))
;
493
494 bool Emitted;
495 if (Force) {
496 Diagnostic Info(this);
497
498 // Figure out the diagnostic level of this message.
499 DiagnosticIDs::Level DiagLevel
500 = Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
501
502 Emitted = (DiagLevel != DiagnosticIDs::Ignored);
503 if (Emitted) {
504 // Emit the diagnostic regardless of suppression level.
505 Diags->EmitDiag(*this, DiagLevel);
506 }
507 } else {
508 // Process the diagnostic, sending the accumulated information to the
509 // DiagnosticConsumer.
510 Emitted = ProcessDiag();
511 }
512
513 // Clear out the current diagnostic object.
514 Clear();
515
516 // If there was a delayed diagnostic, emit it now.
517 if (!Force && DelayedDiagID)
518 ReportDelayed();
519
520 return Emitted;
521}
522
523DiagnosticConsumer::~DiagnosticConsumer() = default;
524
525void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
526 const Diagnostic &Info) {
527 if (!IncludeInDiagnosticCounts())
528 return;
529
530 if (DiagLevel == DiagnosticsEngine::Warning)
531 ++NumWarnings;
532 else if (DiagLevel >= DiagnosticsEngine::Error)
533 ++NumErrors;
534}
535
536/// ModifierIs - Return true if the specified modifier matches specified string.
537template <std::size_t StrLen>
538static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
539 const char (&Str)[StrLen]) {
540 return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0;
541}
542
543/// ScanForward - Scans forward, looking for the given character, skipping
544/// nested clauses and escaped characters.
545static const char *ScanFormat(const char *I, const char *E, char Target) {
546 unsigned Depth = 0;
547
548 for ( ; I != E; ++I) {
549 if (Depth == 0 && *I == Target) return I;
550 if (Depth != 0 && *I == '}') Depth--;
551
552 if (*I == '%') {
553 I++;
554 if (I == E) break;
555
556 // Escaped characters get implicitly skipped here.
557
558 // Format specifier.
559 if (!isDigit(*I) && !isPunctuation(*I)) {
560 for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ;
561 if (I == E) break;
562 if (*I == '{')
563 Depth++;
564 }
565 }
566 }
567 return E;
568}
569
570/// HandleSelectModifier - Handle the integer 'select' modifier. This is used
571/// like this: %select{foo|bar|baz}2. This means that the integer argument
572/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
573/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
574/// This is very useful for certain classes of variant diagnostics.
575static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
576 const char *Argument, unsigned ArgumentLen,
577 SmallVectorImpl<char> &OutStr) {
578 const char *ArgumentEnd = Argument+ArgumentLen;
579
580 // Skip over 'ValNo' |'s.
581 while (ValNo) {
582 const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
583 assert(NextVal != ArgumentEnd && "Value for integer select modifier was"(static_cast <bool> (NextVal != ArgumentEnd && "Value for integer select modifier was"
" larger than the number of options in the diagnostic string!"
) ? void (0) : __assert_fail ("NextVal != ArgumentEnd && \"Value for integer select modifier was\" \" larger than the number of options in the diagnostic string!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 584, __extension__ __PRETTY_FUNCTION__))
584 " larger than the number of options in the diagnostic string!")(static_cast <bool> (NextVal != ArgumentEnd && "Value for integer select modifier was"
" larger than the number of options in the diagnostic string!"
) ? void (0) : __assert_fail ("NextVal != ArgumentEnd && \"Value for integer select modifier was\" \" larger than the number of options in the diagnostic string!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 584, __extension__ __PRETTY_FUNCTION__))
;
585 Argument = NextVal+1; // Skip this string.
586 --ValNo;
587 }
588
589 // Get the end of the value. This is either the } or the |.
590 const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
591
592 // Recursively format the result of the select clause into the output string.
593 DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
594}
595
596/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
597/// letter 's' to the string if the value is not 1. This is used in cases like
598/// this: "you idiot, you have %4 parameter%s4!".
599static void HandleIntegerSModifier(unsigned ValNo,
600 SmallVectorImpl<char> &OutStr) {
601 if (ValNo != 1)
602 OutStr.push_back('s');
603}
604
605/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
606/// prints the ordinal form of the given integer, with 1 corresponding
607/// to the first ordinal. Currently this is hard-coded to use the
608/// English form.
609static void HandleOrdinalModifier(unsigned ValNo,
610 SmallVectorImpl<char> &OutStr) {
611 assert(ValNo != 0 && "ValNo must be strictly positive!")(static_cast <bool> (ValNo != 0 && "ValNo must be strictly positive!"
) ? void (0) : __assert_fail ("ValNo != 0 && \"ValNo must be strictly positive!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 611, __extension__ __PRETTY_FUNCTION__))
;
612
613 llvm::raw_svector_ostream Out(OutStr);
614
615 // We could use text forms for the first N ordinals, but the numeric
616 // forms are actually nicer in diagnostics because they stand out.
617 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
618}
619
620/// PluralNumber - Parse an unsigned integer and advance Start.
621static unsigned PluralNumber(const char *&Start, const char *End) {
622 // Programming 101: Parse a decimal number :-)
623 unsigned Val = 0;
14
'Val' initialized to 0
624 while (Start != End && *Start >= '0' && *Start <= '9') {
15
Assuming the condition is true
16
Assuming the condition is false
17
Loop condition is false. Execution continues on line 629
625 Val *= 10;
626 Val += *Start - '0';
627 ++Start;
628 }
629 return Val;
18
Returning zero (loaded from 'Val')
630}
631
632/// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
633static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
634 if (*Start != '[') {
635 unsigned Ref = PluralNumber(Start, End);
636 return Ref == Val;
637 }
638
639 ++Start;
640 unsigned Low = PluralNumber(Start, End);
641 assert(*Start == ',' && "Bad plural expression syntax: expected ,")(static_cast <bool> (*Start == ',' && "Bad plural expression syntax: expected ,"
) ? void (0) : __assert_fail ("*Start == ',' && \"Bad plural expression syntax: expected ,\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 641, __extension__ __PRETTY_FUNCTION__))
;
642 ++Start;
643 unsigned High = PluralNumber(Start, End);
644 assert(*Start == ']' && "Bad plural expression syntax: expected )")(static_cast <bool> (*Start == ']' && "Bad plural expression syntax: expected )"
) ? void (0) : __assert_fail ("*Start == ']' && \"Bad plural expression syntax: expected )\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 644, __extension__ __PRETTY_FUNCTION__))
;
645 ++Start;
646 return Low <= Val && Val <= High;
647}
648
649/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
650static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
651 // Empty condition?
652 if (*Start == ':')
9
Taking false branch
653 return true;
654
655 while (true) {
10
Loop condition is true. Entering loop body
656 char C = *Start;
657 if (C == '%') {
11
Assuming the condition is true
12
Taking true branch
658 // Modulo expression
659 ++Start;
660 unsigned Arg = PluralNumber(Start, End);
13
Calling 'PluralNumber'
19
Returning from 'PluralNumber'
20
'Arg' initialized to 0
661 assert(*Start == '=' && "Bad plural expression syntax: expected =")(static_cast <bool> (*Start == '=' && "Bad plural expression syntax: expected ="
) ? void (0) : __assert_fail ("*Start == '=' && \"Bad plural expression syntax: expected =\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 661, __extension__ __PRETTY_FUNCTION__))
;
662 ++Start;
663 unsigned ValMod = ValNo % Arg;
21
Division by zero
664 if (TestPluralRange(ValMod, Start, End))
665 return true;
666 } else {
667 assert((C == '[' || (C >= '0' && C <= '9')) &&(static_cast <bool> ((C == '[' || (C >= '0' &&
C <= '9')) && "Bad plural expression syntax: unexpected character"
) ? void (0) : __assert_fail ("(C == '[' || (C >= '0' && C <= '9')) && \"Bad plural expression syntax: unexpected character\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 668, __extension__ __PRETTY_FUNCTION__))
668 "Bad plural expression syntax: unexpected character")(static_cast <bool> ((C == '[' || (C >= '0' &&
C <= '9')) && "Bad plural expression syntax: unexpected character"
) ? void (0) : __assert_fail ("(C == '[' || (C >= '0' && C <= '9')) && \"Bad plural expression syntax: unexpected character\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 668, __extension__ __PRETTY_FUNCTION__))
;
669 // Range expression
670 if (TestPluralRange(ValNo, Start, End))
671 return true;
672 }
673
674 // Scan for next or-expr part.
675 Start = std::find(Start, End, ',');
676 if (Start == End)
677 break;
678 ++Start;
679 }
680 return false;
681}
682
683/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
684/// for complex plural forms, or in languages where all plurals are complex.
685/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
686/// conditions that are tested in order, the form corresponding to the first
687/// that applies being emitted. The empty condition is always true, making the
688/// last form a default case.
689/// Conditions are simple boolean expressions, where n is the number argument.
690/// Here are the rules.
691/// condition := expression | empty
692/// empty := -> always true
693/// expression := numeric [',' expression] -> logical or
694/// numeric := range -> true if n in range
695/// | '%' number '=' range -> true if n % number in range
696/// range := number
697/// | '[' number ',' number ']' -> ranges are inclusive both ends
698///
699/// Here are some examples from the GNU gettext manual written in this form:
700/// English:
701/// {1:form0|:form1}
702/// Latvian:
703/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
704/// Gaeilge:
705/// {1:form0|2:form1|:form2}
706/// Romanian:
707/// {1:form0|0,%100=[1,19]:form1|:form2}
708/// Lithuanian:
709/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
710/// Russian (requires repeated form):
711/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
712/// Slovak
713/// {1:form0|[2,4]:form1|:form2}
714/// Polish (requires repeated form):
715/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
716static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
717 const char *Argument, unsigned ArgumentLen,
718 SmallVectorImpl<char> &OutStr) {
719 const char *ArgumentEnd = Argument + ArgumentLen;
720 while (true) {
1
Loop condition is true. Entering loop body
721 assert(Argument < ArgumentEnd && "Plural expression didn't match.")(static_cast <bool> (Argument < ArgumentEnd &&
"Plural expression didn't match.") ? void (0) : __assert_fail
("Argument < ArgumentEnd && \"Plural expression didn't match.\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 721, __extension__ __PRETTY_FUNCTION__))
;
722 const char *ExprEnd = Argument;
723 while (*ExprEnd != ':') {
2
Assuming the condition is true
3
Loop condition is true. Entering loop body
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
6
Assuming the condition is false
7
Loop condition is false. Execution continues on line 727
724 assert(ExprEnd != ArgumentEnd && "Plural missing expression end")(static_cast <bool> (ExprEnd != ArgumentEnd && "Plural missing expression end"
) ? void (0) : __assert_fail ("ExprEnd != ArgumentEnd && \"Plural missing expression end\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 724, __extension__ __PRETTY_FUNCTION__))
;
725 ++ExprEnd;
726 }
727 if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
8
Calling 'EvalPluralExpr'
728 Argument = ExprEnd + 1;
729 ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
730
731 // Recursively format the result of the plural clause into the
732 // output string.
733 DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
734 return;
735 }
736 Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
737 }
738}
739
740/// \brief Returns the friendly description for a token kind that will appear
741/// without quotes in diagnostic messages. These strings may be translatable in
742/// future.
743static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
744 switch (Kind) {
745 case tok::identifier:
746 return "identifier";
747 default:
748 return nullptr;
749 }
750}
751
752/// FormatDiagnostic - Format this diagnostic into a string, substituting the
753/// formal arguments into the %0 slots. The result is appended onto the Str
754/// array.
755void Diagnostic::
756FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
757 if (!StoredDiagMessage.empty()) {
758 OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
759 return;
760 }
761
762 StringRef Diag =
763 getDiags()->getDiagnosticIDs()->getDescription(getID());
764
765 FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
766}
767
768void Diagnostic::
769FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
770 SmallVectorImpl<char> &OutStr) const {
771 // When the diagnostic string is only "%0", the entire string is being given
772 // by an outside source. Remove unprintable characters from this string
773 // and skip all the other string processing.
774 if (DiagEnd - DiagStr == 2 &&
775 StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") &&
776 getArgKind(0) == DiagnosticsEngine::ak_std_string) {
777 const std::string &S = getArgStdStr(0);
778 for (char c : S) {
779 if (llvm::sys::locale::isPrint(c) || c == '\t') {
780 OutStr.push_back(c);
781 }
782 }
783 return;
784 }
785
786 /// FormattedArgs - Keep track of all of the arguments formatted by
787 /// ConvertArgToString and pass them into subsequent calls to
788 /// ConvertArgToString, allowing the implementation to avoid redundancies in
789 /// obvious cases.
790 SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
791
792 /// QualTypeVals - Pass a vector of arrays so that QualType names can be
793 /// compared to see if more information is needed to be printed.
794 SmallVector<intptr_t, 2> QualTypeVals;
795 SmallVector<char, 64> Tree;
796
797 for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
798 if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
799 QualTypeVals.push_back(getRawArg(i));
800
801 while (DiagStr != DiagEnd) {
802 if (DiagStr[0] != '%') {
803 // Append non-%0 substrings to Str if we have one.
804 const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
805 OutStr.append(DiagStr, StrEnd);
806 DiagStr = StrEnd;
807 continue;
808 } else if (isPunctuation(DiagStr[1])) {
809 OutStr.push_back(DiagStr[1]); // %% -> %.
810 DiagStr += 2;
811 continue;
812 }
813
814 // Skip the %.
815 ++DiagStr;
816
817 // This must be a placeholder for a diagnostic argument. The format for a
818 // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
819 // The digit is a number from 0-9 indicating which argument this comes from.
820 // The modifier is a string of digits from the set [-a-z]+, arguments is a
821 // brace enclosed string.
822 const char *Modifier = nullptr, *Argument = nullptr;
823 unsigned ModifierLen = 0, ArgumentLen = 0;
824
825 // Check to see if we have a modifier. If so eat it.
826 if (!isDigit(DiagStr[0])) {
827 Modifier = DiagStr;
828 while (DiagStr[0] == '-' ||
829 (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
830 ++DiagStr;
831 ModifierLen = DiagStr-Modifier;
832
833 // If we have an argument, get it next.
834 if (DiagStr[0] == '{') {
835 ++DiagStr; // Skip {.
836 Argument = DiagStr;
837
838 DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
839 assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!")(static_cast <bool> (DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!"
) ? void (0) : __assert_fail ("DiagStr != DiagEnd && \"Mismatched {}'s in diagnostic string!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 839, __extension__ __PRETTY_FUNCTION__))
;
840 ArgumentLen = DiagStr-Argument;
841 ++DiagStr; // Skip }.
842 }
843 }
844
845 assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic")(static_cast <bool> (isDigit(*DiagStr) && "Invalid format for argument in diagnostic"
) ? void (0) : __assert_fail ("isDigit(*DiagStr) && \"Invalid format for argument in diagnostic\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 845, __extension__ __PRETTY_FUNCTION__))
;
846 unsigned ArgNo = *DiagStr++ - '0';
847
848 // Only used for type diffing.
849 unsigned ArgNo2 = ArgNo;
850
851 DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
852 if (ModifierIs(Modifier, ModifierLen, "diff")) {
853 assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&(static_cast <bool> (*DiagStr == ',' && isDigit
(*(DiagStr + 1)) && "Invalid format for diff modifier"
) ? void (0) : __assert_fail ("*DiagStr == ',' && isDigit(*(DiagStr + 1)) && \"Invalid format for diff modifier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 854, __extension__ __PRETTY_FUNCTION__))
854 "Invalid format for diff modifier")(static_cast <bool> (*DiagStr == ',' && isDigit
(*(DiagStr + 1)) && "Invalid format for diff modifier"
) ? void (0) : __assert_fail ("*DiagStr == ',' && isDigit(*(DiagStr + 1)) && \"Invalid format for diff modifier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 854, __extension__ __PRETTY_FUNCTION__))
;
855 ++DiagStr; // Comma.
856 ArgNo2 = *DiagStr++ - '0';
857 DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
858 if (Kind == DiagnosticsEngine::ak_qualtype &&
859 Kind2 == DiagnosticsEngine::ak_qualtype)
860 Kind = DiagnosticsEngine::ak_qualtype_pair;
861 else {
862 // %diff only supports QualTypes. For other kinds of arguments,
863 // use the default printing. For example, if the modifier is:
864 // "%diff{compare $ to $|other text}1,2"
865 // treat it as:
866 // "compare %1 to %2"
867 const char *ArgumentEnd = Argument + ArgumentLen;
868 const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
869 assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&(static_cast <bool> (ScanFormat(Pipe + 1, ArgumentEnd, '|'
) == ArgumentEnd && "Found too many '|'s in a %diff modifier!"
) ? void (0) : __assert_fail ("ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd && \"Found too many '|'s in a %diff modifier!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 870, __extension__ __PRETTY_FUNCTION__))
870 "Found too many '|'s in a %diff modifier!")(static_cast <bool> (ScanFormat(Pipe + 1, ArgumentEnd, '|'
) == ArgumentEnd && "Found too many '|'s in a %diff modifier!"
) ? void (0) : __assert_fail ("ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd && \"Found too many '|'s in a %diff modifier!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 870, __extension__ __PRETTY_FUNCTION__))
;
871 const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
872 const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
873 const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
874 const char ArgStr2[] = { '%', static_cast<char>('0' + ArgNo2) };
875 FormatDiagnostic(Argument, FirstDollar, OutStr);
876 FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
877 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
878 FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
879 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
880 continue;
881 }
882 }
883
884 switch (Kind) {
885 // ---- STRINGS ----
886 case DiagnosticsEngine::ak_std_string: {
887 const std::string &S = getArgStdStr(ArgNo);
888 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast <bool> (ModifierLen == 0 && "No modifiers for strings yet"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"No modifiers for strings yet\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 888, __extension__ __PRETTY_FUNCTION__))
;
889 OutStr.append(S.begin(), S.end());
890 break;
891 }
892 case DiagnosticsEngine::ak_c_string: {
893 const char *S = getArgCStr(ArgNo);
894 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast <bool> (ModifierLen == 0 && "No modifiers for strings yet"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"No modifiers for strings yet\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 894, __extension__ __PRETTY_FUNCTION__))
;
895
896 // Don't crash if get passed a null pointer by accident.
897 if (!S)
898 S = "(null)";
899
900 OutStr.append(S, S + strlen(S));
901 break;
902 }
903 // ---- INTEGERS ----
904 case DiagnosticsEngine::ak_sint: {
905 int Val = getArgSInt(ArgNo);
906
907 if (ModifierIs(Modifier, ModifierLen, "select")) {
908 HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
909 OutStr);
910 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
911 HandleIntegerSModifier(Val, OutStr);
912 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
913 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
914 OutStr);
915 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
916 HandleOrdinalModifier((unsigned)Val, OutStr);
917 } else {
918 assert(ModifierLen == 0 && "Unknown integer modifier")(static_cast <bool> (ModifierLen == 0 && "Unknown integer modifier"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"Unknown integer modifier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 918, __extension__ __PRETTY_FUNCTION__))
;
919 llvm::raw_svector_ostream(OutStr) << Val;
920 }
921 break;
922 }
923 case DiagnosticsEngine::ak_uint: {
924 unsigned Val = getArgUInt(ArgNo);
925
926 if (ModifierIs(Modifier, ModifierLen, "select")) {
927 HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
928 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
929 HandleIntegerSModifier(Val, OutStr);
930 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
931 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
932 OutStr);
933 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
934 HandleOrdinalModifier(Val, OutStr);
935 } else {
936 assert(ModifierLen == 0 && "Unknown integer modifier")(static_cast <bool> (ModifierLen == 0 && "Unknown integer modifier"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"Unknown integer modifier\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 936, __extension__ __PRETTY_FUNCTION__))
;
937 llvm::raw_svector_ostream(OutStr) << Val;
938 }
939 break;
940 }
941 // ---- TOKEN SPELLINGS ----
942 case DiagnosticsEngine::ak_tokenkind: {
943 tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
944 assert(ModifierLen == 0 && "No modifiers for token kinds yet")(static_cast <bool> (ModifierLen == 0 && "No modifiers for token kinds yet"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"No modifiers for token kinds yet\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 944, __extension__ __PRETTY_FUNCTION__))
;
945
946 llvm::raw_svector_ostream Out(OutStr);
947 if (const char *S = tok::getPunctuatorSpelling(Kind))
948 // Quoted token spelling for punctuators.
949 Out << '\'' << S << '\'';
950 else if (const char *S = tok::getKeywordSpelling(Kind))
951 // Unquoted token spelling for keywords.
952 Out << S;
953 else if (const char *S = getTokenDescForDiagnostic(Kind))
954 // Unquoted translatable token name.
955 Out << S;
956 else if (const char *S = tok::getTokenName(Kind))
957 // Debug name, shouldn't appear in user-facing diagnostics.
958 Out << '<' << S << '>';
959 else
960 Out << "(null)";
961 break;
962 }
963 // ---- NAMES and TYPES ----
964 case DiagnosticsEngine::ak_identifierinfo: {
965 const IdentifierInfo *II = getArgIdentifier(ArgNo);
966 assert(ModifierLen == 0 && "No modifiers for strings yet")(static_cast <bool> (ModifierLen == 0 && "No modifiers for strings yet"
) ? void (0) : __assert_fail ("ModifierLen == 0 && \"No modifiers for strings yet\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 966, __extension__ __PRETTY_FUNCTION__))
;
967
968 // Don't crash if get passed a null pointer by accident.
969 if (!II) {
970 const char *S = "(null)";
971 OutStr.append(S, S + strlen(S));
972 continue;
973 }
974
975 llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
976 break;
977 }
978 case DiagnosticsEngine::ak_qualtype:
979 case DiagnosticsEngine::ak_declarationname:
980 case DiagnosticsEngine::ak_nameddecl:
981 case DiagnosticsEngine::ak_nestednamespec:
982 case DiagnosticsEngine::ak_declcontext:
983 case DiagnosticsEngine::ak_attr:
984 getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
985 StringRef(Modifier, ModifierLen),
986 StringRef(Argument, ArgumentLen),
987 FormattedArgs,
988 OutStr, QualTypeVals);
989 break;
990 case DiagnosticsEngine::ak_qualtype_pair: {
991 // Create a struct with all the info needed for printing.
992 TemplateDiffTypes TDT;
993 TDT.FromType = getRawArg(ArgNo);
994 TDT.ToType = getRawArg(ArgNo2);
995 TDT.ElideType = getDiags()->ElideType;
996 TDT.ShowColors = getDiags()->ShowColors;
997 TDT.TemplateDiffUsed = false;
998 intptr_t val = reinterpret_cast<intptr_t>(&TDT);
999
1000 const char *ArgumentEnd = Argument + ArgumentLen;
1001 const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
1002
1003 // Print the tree. If this diagnostic already has a tree, skip the
1004 // second tree.
1005 if (getDiags()->PrintTemplateTree && Tree.empty()) {
1006 TDT.PrintFromType = true;
1007 TDT.PrintTree = true;
1008 getDiags()->ConvertArgToString(Kind, val,
1009 StringRef(Modifier, ModifierLen),
1010 StringRef(Argument, ArgumentLen),
1011 FormattedArgs,
1012 Tree, QualTypeVals);
1013 // If there is no tree information, fall back to regular printing.
1014 if (!Tree.empty()) {
1015 FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
1016 break;
1017 }
1018 }
1019
1020 // Non-tree printing, also the fall-back when tree printing fails.
1021 // The fall-back is triggered when the types compared are not templates.
1022 const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
1023 const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
1024
1025 // Append before text
1026 FormatDiagnostic(Argument, FirstDollar, OutStr);
1027
1028 // Append first type
1029 TDT.PrintTree = false;
1030 TDT.PrintFromType = true;
1031 getDiags()->ConvertArgToString(Kind, val,
1032 StringRef(Modifier, ModifierLen),
1033 StringRef(Argument, ArgumentLen),
1034 FormattedArgs,
1035 OutStr, QualTypeVals);
1036 if (!TDT.TemplateDiffUsed)
1037 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
1038 TDT.FromType));
1039
1040 // Append middle text
1041 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
1042
1043 // Append second type
1044 TDT.PrintFromType = false;
1045 getDiags()->ConvertArgToString(Kind, val,
1046 StringRef(Modifier, ModifierLen),
1047 StringRef(Argument, ArgumentLen),
1048 FormattedArgs,
1049 OutStr, QualTypeVals);
1050 if (!TDT.TemplateDiffUsed)
1051 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
1052 TDT.ToType));
1053
1054 // Append end text
1055 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
1056 break;
1057 }
1058 }
1059
1060 // Remember this argument info for subsequent formatting operations. Turn
1061 // std::strings into a null terminated string to make it be the same case as
1062 // all the other ones.
1063 if (Kind == DiagnosticsEngine::ak_qualtype_pair)
1064 continue;
1065 else if (Kind != DiagnosticsEngine::ak_std_string)
1066 FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
1067 else
1068 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
1069 (intptr_t)getArgStdStr(ArgNo).c_str()));
1070 }
1071
1072 // Append the type tree to the end of the diagnostics.
1073 OutStr.append(Tree.begin(), Tree.end());
1074}
1075
1076StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1077 StringRef Message)
1078 : ID(ID), Level(Level), Message(Message) {}
1079
1080StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
1081 const Diagnostic &Info)
1082 : ID(Info.getID()), Level(Level) {
1083 assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&(static_cast <bool> ((Info.getLocation().isInvalid() ||
Info.hasSourceManager()) && "Valid source location without setting a source manager for diagnostic"
) ? void (0) : __assert_fail ("(Info.getLocation().isInvalid() || Info.hasSourceManager()) && \"Valid source location without setting a source manager for diagnostic\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 1084, __extension__ __PRETTY_FUNCTION__))
1084 "Valid source location without setting a source manager for diagnostic")(static_cast <bool> ((Info.getLocation().isInvalid() ||
Info.hasSourceManager()) && "Valid source location without setting a source manager for diagnostic"
) ? void (0) : __assert_fail ("(Info.getLocation().isInvalid() || Info.hasSourceManager()) && \"Valid source location without setting a source manager for diagnostic\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 1084, __extension__ __PRETTY_FUNCTION__))
;
1085 if (Info.getLocation().isValid())
1086 Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
1087 SmallString<64> Message;
1088 Info.FormatDiagnostic(Message);
1089 this->Message.assign(Message.begin(), Message.end());
1090 this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
1091 this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
1092}
1093
1094StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1095 StringRef Message, FullSourceLoc Loc,
1096 ArrayRef<CharSourceRange> Ranges,
1097 ArrayRef<FixItHint> FixIts)
1098 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1099 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1100{
1101}
1102
1103/// IncludeInDiagnosticCounts - This method (whose default implementation
1104/// returns true) indicates whether the diagnostics handled by this
1105/// DiagnosticConsumer should be included in the number of diagnostics
1106/// reported by DiagnosticsEngine.
1107bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
1108
1109void IgnoringDiagConsumer::anchor() {}
1110
1111ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() = default;
1112
1113void ForwardingDiagnosticConsumer::HandleDiagnostic(
1114 DiagnosticsEngine::Level DiagLevel,
1115 const Diagnostic &Info) {
1116 Target.HandleDiagnostic(DiagLevel, Info);
1117}
1118
1119void ForwardingDiagnosticConsumer::clear() {
1120 DiagnosticConsumer::clear();
1121 Target.clear();
1122}
1123
1124bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
1125 return Target.IncludeInDiagnosticCounts();
1126}
1127
1128PartialDiagnostic::StorageAllocator::StorageAllocator() {
1129 for (unsigned I = 0; I != NumCached; ++I)
1130 FreeList[I] = Cached + I;
1131 NumFreeListEntries = NumCached;
1132}
1133
1134PartialDiagnostic::StorageAllocator::~StorageAllocator() {
1135 // Don't assert if we are in a CrashRecovery context, as this invariant may
1136 // be invalidated during a crash.
1137 assert((NumFreeListEntries == NumCached ||(static_cast <bool> ((NumFreeListEntries == NumCached ||
llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
"A partial is on the lam") ? void (0) : __assert_fail ("(NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && \"A partial is on the lam\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 1139, __extension__ __PRETTY_FUNCTION__))
1138 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&(static_cast <bool> ((NumFreeListEntries == NumCached ||
llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
"A partial is on the lam") ? void (0) : __assert_fail ("(NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && \"A partial is on the lam\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 1139, __extension__ __PRETTY_FUNCTION__))
1139 "A partial is on the lam")(static_cast <bool> ((NumFreeListEntries == NumCached ||
llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
"A partial is on the lam") ? void (0) : __assert_fail ("(NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && \"A partial is on the lam\""
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Basic/Diagnostic.cpp"
, 1139, __extension__ __PRETTY_FUNCTION__))
;
1140}
1141
1142char DiagnosticError::ID;