Clang Project

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