clang  6.0.0svn
Diagnostic.cpp
Go to the documentation of this file.
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"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Support/CrashRecoveryContext.h"
24 #include "llvm/Support/Locale.h"
25 #include "llvm/Support/raw_ostream.h"
26 
27 using namespace clang;
28 
30  DiagNullabilityKind nullability) {
31  StringRef string;
32  switch (nullability.first) {
34  string = nullability.second ? "'nonnull'" : "'_Nonnull'";
35  break;
36 
38  string = nullability.second ? "'nullable'" : "'_Nullable'";
39  break;
40 
42  string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
43  break;
44  }
45 
46  DB.AddString(string);
47  return DB;
48 }
49 
51  StringRef Modifier, StringRef Argument,
53  SmallVectorImpl<char> &Output,
54  void *Cookie,
55  ArrayRef<intptr_t> QualTypeVals) {
56  StringRef Str = "<can't format argument>";
57  Output.append(Str.begin(), Str.end());
58 }
59 
61  DiagnosticOptions *DiagOpts,
62  DiagnosticConsumer *client,
63  bool ShouldOwnClient)
64  : Diags(std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
65  SourceMgr(nullptr) {
66  setClient(client, ShouldOwnClient);
67  ArgToStringFn = DummyArgToStringFn;
68  ArgToStringCookie = nullptr;
69 
70  AllExtensionsSilenced = 0;
71  SuppressAfterFatalError = true;
72  SuppressAllDiagnostics = false;
73  ElideType = true;
74  PrintTemplateTree = false;
75  ShowColors = false;
76  ShowOverloads = Ovl_All;
77 
78  ErrorLimit = 0;
79  TemplateBacktraceLimit = 0;
80  ConstexprBacktraceLimit = 0;
81 
82  Reset();
83 }
84 
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 
92  bool ShouldOwnClient) {
93  Owner.reset(ShouldOwnClient ? client : nullptr);
94  Client = client;
95 }
96 
98  DiagStateOnPushStack.push_back(GetCurDiagState());
99 }
100 
102  if (DiagStateOnPushStack.empty())
103  return false;
104 
105  if (DiagStateOnPushStack.back() != GetCurDiagState()) {
106  // State changed at some point between push/pop.
107  PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
108  }
109  DiagStateOnPushStack.pop_back();
110  return true;
111 }
112 
114  ErrorOccurred = false;
115  UncompilableErrorOccurred = false;
116  FatalErrorOccurred = false;
117  UnrecoverableErrorOccurred = false;
118 
119  NumWarnings = 0;
120  NumErrors = 0;
121  TrapNumErrorsOccurred = 0;
122  TrapNumUnrecoverableErrorsOccurred = 0;
123 
124  CurDiagID = ~0U;
125  LastDiagLevel = DiagnosticIDs::Ignored;
126  DelayedDiagID = 0;
127 
128  // Clear state related to #pragma diagnostic.
129  DiagStates.clear();
130  DiagStatesByLoc.clear();
131  DiagStateOnPushStack.clear();
132 
133  // Create a DiagState and DiagStatePoint representing diagnostic changes
134  // through command-line.
135  DiagStates.emplace_back();
136  DiagStatesByLoc.appendFirst(&DiagStates.back());
137 }
138 
139 void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
140  StringRef Arg2) {
141  if (DelayedDiagID)
142  return;
143 
144  DelayedDiagID = DiagID;
145  DelayedDiagArg1 = Arg1.str();
146  DelayedDiagArg2 = Arg2.str();
147 }
148 
149 void DiagnosticsEngine::ReportDelayed() {
150  unsigned ID = DelayedDiagID;
151  DelayedDiagID = 0;
152  Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
153 }
154 
155 void DiagnosticsEngine::DiagStateMap::appendFirst(
156  DiagState *State) {
157  assert(Files.empty() && "not first");
158  FirstDiagState = CurDiagState = State;
159  CurDiagStateLoc = SourceLocation();
160 }
161 
162 void 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");
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 
187 DiagnosticsEngine::DiagState *
188 DiagnosticsEngine::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 
199 DiagnosticsEngine::DiagState *
200 DiagnosticsEngine::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");
207  return OnePastIt[-1].State;
208 }
209 
210 DiagnosticsEngine::DiagStateMap::File *
211 DiagnosticsEngine::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 
239 void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
240  SourceLocation Loc) {
241  assert(Loc.isValid() && "Adding invalid loc point");
242  DiagStatesByLoc.append(*SourceMgr, Loc, State);
243 }
244 
246  SourceLocation L) {
247  assert(Diag < diag::DIAG_UPPER_LIMIT &&
248  "Can only map builtin diagnostics");
249  assert((Diags->isBuiltinWarningOrExtension(Diag) ||
250  (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
251  "Cannot map errors into warnings!");
252  assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location");
253 
254  // Don't allow a mapping to a warning override an error/fatal mapping.
255  bool WasUpgradedFromWarning = false;
256  if (Map == diag::Severity::Warning) {
257  DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
258  if (Info.getSeverity() == diag::Severity::Error ||
260  Map = Info.getSeverity();
261  WasUpgradedFromWarning = true;
262  }
263  }
264  DiagnosticMapping Mapping = makeUserMapping(Map, L);
265  Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
266 
267  // Common case; setting all the diagnostics of a group in one place.
268  if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
269  DiagStatesByLoc.getCurDiagState()) {
270  // FIXME: This is theoretically wrong: if the current state is shared with
271  // some other location (via push/pop) we will change the state for that
272  // other location as well. This cannot currently happen, as we can't update
273  // the diagnostic state at the same location at which we pop.
274  DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
275  return;
276  }
277 
278  // A diagnostic pragma occurred, create a new DiagState initialized with
279  // the current one and a new DiagStatePoint to record at which location
280  // the new state became active.
281  DiagStates.push_back(*GetCurDiagState());
282  DiagStates.back().setMapping(Diag, Mapping);
283  PushDiagStatePoint(&DiagStates.back(), L);
284 }
285 
287  StringRef Group, diag::Severity Map,
288  SourceLocation Loc) {
289  // Get the diagnostics in this group.
290  SmallVector<diag::kind, 256> GroupDiags;
291  if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
292  return true;
293 
294  // Set the mapping.
295  for (diag::kind Diag : GroupDiags)
296  setSeverity(Diag, Map, Loc);
297 
298  return false;
299 }
300 
302  bool Enabled) {
303  // If we are enabling this feature, just set the diagnostic mappings to map to
304  // errors.
305  if (Enabled)
308 
309  // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
310  // potentially downgrade anything already mapped to be a warning.
311 
312  // Get the diagnostics in this group.
313  SmallVector<diag::kind, 8> GroupDiags;
314  if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
315  GroupDiags))
316  return true;
317 
318  // Perform the mapping change.
319  for (diag::kind Diag : GroupDiags) {
320  DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
321 
322  if (Info.getSeverity() == diag::Severity::Error ||
325 
326  Info.setNoWarningAsError(true);
327  }
328 
329  return false;
330 }
331 
333  bool Enabled) {
334  // If we are enabling this feature, just set the diagnostic mappings to map to
335  // fatal errors.
336  if (Enabled)
339 
340  // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit,
341  // and potentially downgrade anything already mapped to be a fatal error.
342 
343  // Get the diagnostics in this group.
344  SmallVector<diag::kind, 8> GroupDiags;
345  if (Diags->getDiagnosticsInGroup(diag::Flavor::WarningOrError, Group,
346  GroupDiags))
347  return true;
348 
349  // Perform the mapping change.
350  for (diag::kind Diag : GroupDiags) {
351  DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
352 
353  if (Info.getSeverity() == diag::Severity::Fatal)
355 
356  Info.setNoErrorAsFatal(true);
357  }
358 
359  return false;
360 }
361 
363  diag::Severity Map,
364  SourceLocation Loc) {
365  // Get all the diagnostics.
367  Diags->getAllDiagnostics(Flavor, AllDiags);
368 
369  // Set the mapping.
370  for (diag::kind Diag : AllDiags)
371  if (Diags->isBuiltinWarningOrExtension(Diag))
372  setSeverity(Diag, Map, Loc);
373 }
374 
376  assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
377 
378  CurDiagLoc = storedDiag.getLocation();
379  CurDiagID = storedDiag.getID();
380  NumDiagArgs = 0;
381 
382  DiagRanges.clear();
383  DiagRanges.append(storedDiag.range_begin(), storedDiag.range_end());
384 
385  DiagFixItHints.clear();
386  DiagFixItHints.append(storedDiag.fixit_begin(), storedDiag.fixit_end());
387 
388  assert(Client && "DiagnosticConsumer not set!");
389  Level DiagLevel = storedDiag.getLevel();
390  Diagnostic Info(this, storedDiag.getMessage());
391  Client->HandleDiagnostic(DiagLevel, Info);
392  if (Client->IncludeInDiagnosticCounts()) {
393  if (DiagLevel == DiagnosticsEngine::Warning)
394  ++NumWarnings;
395  }
396 
397  CurDiagID = ~0U;
398 }
399 
401  assert(getClient() && "DiagnosticClient not set!");
402 
403  bool Emitted;
404  if (Force) {
405  Diagnostic Info(this);
406 
407  // Figure out the diagnostic level of this message.
408  DiagnosticIDs::Level DiagLevel
409  = Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
410 
411  Emitted = (DiagLevel != DiagnosticIDs::Ignored);
412  if (Emitted) {
413  // Emit the diagnostic regardless of suppression level.
414  Diags->EmitDiag(*this, DiagLevel);
415  }
416  } else {
417  // Process the diagnostic, sending the accumulated information to the
418  // DiagnosticConsumer.
419  Emitted = ProcessDiag();
420  }
421 
422  // Clear out the current diagnostic object.
423  Clear();
424 
425  // If there was a delayed diagnostic, emit it now.
426  if (!Force && DelayedDiagID)
427  ReportDelayed();
428 
429  return Emitted;
430 }
431 
432 
434 
436  const Diagnostic &Info) {
437  if (!IncludeInDiagnosticCounts())
438  return;
439 
440  if (DiagLevel == DiagnosticsEngine::Warning)
441  ++NumWarnings;
442  else if (DiagLevel >= DiagnosticsEngine::Error)
443  ++NumErrors;
444 }
445 
446 /// ModifierIs - Return true if the specified modifier matches specified string.
447 template <std::size_t StrLen>
448 static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
449  const char (&Str)[StrLen]) {
450  return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
451 }
452 
453 /// ScanForward - Scans forward, looking for the given character, skipping
454 /// nested clauses and escaped characters.
455 static const char *ScanFormat(const char *I, const char *E, char Target) {
456  unsigned Depth = 0;
457 
458  for ( ; I != E; ++I) {
459  if (Depth == 0 && *I == Target) return I;
460  if (Depth != 0 && *I == '}') Depth--;
461 
462  if (*I == '%') {
463  I++;
464  if (I == E) break;
465 
466  // Escaped characters get implicitly skipped here.
467 
468  // Format specifier.
469  if (!isDigit(*I) && !isPunctuation(*I)) {
470  for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ;
471  if (I == E) break;
472  if (*I == '{')
473  Depth++;
474  }
475  }
476  }
477  return E;
478 }
479 
480 /// HandleSelectModifier - Handle the integer 'select' modifier. This is used
481 /// like this: %select{foo|bar|baz}2. This means that the integer argument
482 /// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
483 /// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
484 /// This is very useful for certain classes of variant diagnostics.
485 static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
486  const char *Argument, unsigned ArgumentLen,
487  SmallVectorImpl<char> &OutStr) {
488  const char *ArgumentEnd = Argument+ArgumentLen;
489 
490  // Skip over 'ValNo' |'s.
491  while (ValNo) {
492  const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
493  assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
494  " larger than the number of options in the diagnostic string!");
495  Argument = NextVal+1; // Skip this string.
496  --ValNo;
497  }
498 
499  // Get the end of the value. This is either the } or the |.
500  const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
501 
502  // Recursively format the result of the select clause into the output string.
503  DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
504 }
505 
506 /// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
507 /// letter 's' to the string if the value is not 1. This is used in cases like
508 /// this: "you idiot, you have %4 parameter%s4!".
509 static void HandleIntegerSModifier(unsigned ValNo,
510  SmallVectorImpl<char> &OutStr) {
511  if (ValNo != 1)
512  OutStr.push_back('s');
513 }
514 
515 /// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
516 /// prints the ordinal form of the given integer, with 1 corresponding
517 /// to the first ordinal. Currently this is hard-coded to use the
518 /// English form.
519 static void HandleOrdinalModifier(unsigned ValNo,
520  SmallVectorImpl<char> &OutStr) {
521  assert(ValNo != 0 && "ValNo must be strictly positive!");
522 
523  llvm::raw_svector_ostream Out(OutStr);
524 
525  // We could use text forms for the first N ordinals, but the numeric
526  // forms are actually nicer in diagnostics because they stand out.
527  Out << ValNo << llvm::getOrdinalSuffix(ValNo);
528 }
529 
530 
531 /// PluralNumber - Parse an unsigned integer and advance Start.
532 static unsigned PluralNumber(const char *&Start, const char *End) {
533  // Programming 101: Parse a decimal number :-)
534  unsigned Val = 0;
535  while (Start != End && *Start >= '0' && *Start <= '9') {
536  Val *= 10;
537  Val += *Start - '0';
538  ++Start;
539  }
540  return Val;
541 }
542 
543 /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
544 static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
545  if (*Start != '[') {
546  unsigned Ref = PluralNumber(Start, End);
547  return Ref == Val;
548  }
549 
550  ++Start;
551  unsigned Low = PluralNumber(Start, End);
552  assert(*Start == ',' && "Bad plural expression syntax: expected ,");
553  ++Start;
554  unsigned High = PluralNumber(Start, End);
555  assert(*Start == ']' && "Bad plural expression syntax: expected )");
556  ++Start;
557  return Low <= Val && Val <= High;
558 }
559 
560 /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
561 static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
562  // Empty condition?
563  if (*Start == ':')
564  return true;
565 
566  while (1) {
567  char C = *Start;
568  if (C == '%') {
569  // Modulo expression
570  ++Start;
571  unsigned Arg = PluralNumber(Start, End);
572  assert(*Start == '=' && "Bad plural expression syntax: expected =");
573  ++Start;
574  unsigned ValMod = ValNo % Arg;
575  if (TestPluralRange(ValMod, Start, End))
576  return true;
577  } else {
578  assert((C == '[' || (C >= '0' && C <= '9')) &&
579  "Bad plural expression syntax: unexpected character");
580  // Range expression
581  if (TestPluralRange(ValNo, Start, End))
582  return true;
583  }
584 
585  // Scan for next or-expr part.
586  Start = std::find(Start, End, ',');
587  if (Start == End)
588  break;
589  ++Start;
590  }
591  return false;
592 }
593 
594 /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
595 /// for complex plural forms, or in languages where all plurals are complex.
596 /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
597 /// conditions that are tested in order, the form corresponding to the first
598 /// that applies being emitted. The empty condition is always true, making the
599 /// last form a default case.
600 /// Conditions are simple boolean expressions, where n is the number argument.
601 /// Here are the rules.
602 /// condition := expression | empty
603 /// empty := -> always true
604 /// expression := numeric [',' expression] -> logical or
605 /// numeric := range -> true if n in range
606 /// | '%' number '=' range -> true if n % number in range
607 /// range := number
608 /// | '[' number ',' number ']' -> ranges are inclusive both ends
609 ///
610 /// Here are some examples from the GNU gettext manual written in this form:
611 /// English:
612 /// {1:form0|:form1}
613 /// Latvian:
614 /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
615 /// Gaeilge:
616 /// {1:form0|2:form1|:form2}
617 /// Romanian:
618 /// {1:form0|0,%100=[1,19]:form1|:form2}
619 /// Lithuanian:
620 /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
621 /// Russian (requires repeated form):
622 /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
623 /// Slovak
624 /// {1:form0|[2,4]:form1|:form2}
625 /// Polish (requires repeated form):
626 /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
627 static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
628  const char *Argument, unsigned ArgumentLen,
629  SmallVectorImpl<char> &OutStr) {
630  const char *ArgumentEnd = Argument + ArgumentLen;
631  while (1) {
632  assert(Argument < ArgumentEnd && "Plural expression didn't match.");
633  const char *ExprEnd = Argument;
634  while (*ExprEnd != ':') {
635  assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
636  ++ExprEnd;
637  }
638  if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
639  Argument = ExprEnd + 1;
640  ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
641 
642  // Recursively format the result of the plural clause into the
643  // output string.
644  DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
645  return;
646  }
647  Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
648  }
649 }
650 
651 /// \brief Returns the friendly description for a token kind that will appear
652 /// without quotes in diagnostic messages. These strings may be translatable in
653 /// future.
655  switch (Kind) {
656  case tok::identifier:
657  return "identifier";
658  default:
659  return nullptr;
660  }
661 }
662 
663 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
664 /// formal arguments into the %0 slots. The result is appended onto the Str
665 /// array.
666 void Diagnostic::
668  if (!StoredDiagMessage.empty()) {
669  OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
670  return;
671  }
672 
673  StringRef Diag =
674  getDiags()->getDiagnosticIDs()->getDescription(getID());
675 
676  FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
677 }
678 
679 void Diagnostic::
680 FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
681  SmallVectorImpl<char> &OutStr) const {
682 
683  // When the diagnostic string is only "%0", the entire string is being given
684  // by an outside source. Remove unprintable characters from this string
685  // and skip all the other string processing.
686  if (DiagEnd - DiagStr == 2 &&
687  StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") &&
688  getArgKind(0) == DiagnosticsEngine::ak_std_string) {
689  const std::string &S = getArgStdStr(0);
690  for (char c : S) {
691  if (llvm::sys::locale::isPrint(c) || c == '\t') {
692  OutStr.push_back(c);
693  }
694  }
695  return;
696  }
697 
698  /// FormattedArgs - Keep track of all of the arguments formatted by
699  /// ConvertArgToString and pass them into subsequent calls to
700  /// ConvertArgToString, allowing the implementation to avoid redundancies in
701  /// obvious cases.
703 
704  /// QualTypeVals - Pass a vector of arrays so that QualType names can be
705  /// compared to see if more information is needed to be printed.
706  SmallVector<intptr_t, 2> QualTypeVals;
708 
709  for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
710  if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
711  QualTypeVals.push_back(getRawArg(i));
712 
713  while (DiagStr != DiagEnd) {
714  if (DiagStr[0] != '%') {
715  // Append non-%0 substrings to Str if we have one.
716  const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
717  OutStr.append(DiagStr, StrEnd);
718  DiagStr = StrEnd;
719  continue;
720  } else if (isPunctuation(DiagStr[1])) {
721  OutStr.push_back(DiagStr[1]); // %% -> %.
722  DiagStr += 2;
723  continue;
724  }
725 
726  // Skip the %.
727  ++DiagStr;
728 
729  // This must be a placeholder for a diagnostic argument. The format for a
730  // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
731  // The digit is a number from 0-9 indicating which argument this comes from.
732  // The modifier is a string of digits from the set [-a-z]+, arguments is a
733  // brace enclosed string.
734  const char *Modifier = nullptr, *Argument = nullptr;
735  unsigned ModifierLen = 0, ArgumentLen = 0;
736 
737  // Check to see if we have a modifier. If so eat it.
738  if (!isDigit(DiagStr[0])) {
739  Modifier = DiagStr;
740  while (DiagStr[0] == '-' ||
741  (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
742  ++DiagStr;
743  ModifierLen = DiagStr-Modifier;
744 
745  // If we have an argument, get it next.
746  if (DiagStr[0] == '{') {
747  ++DiagStr; // Skip {.
748  Argument = DiagStr;
749 
750  DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
751  assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
752  ArgumentLen = DiagStr-Argument;
753  ++DiagStr; // Skip }.
754  }
755  }
756 
757  assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic");
758  unsigned ArgNo = *DiagStr++ - '0';
759 
760  // Only used for type diffing.
761  unsigned ArgNo2 = ArgNo;
762 
763  DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
764  if (ModifierIs(Modifier, ModifierLen, "diff")) {
765  assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&
766  "Invalid format for diff modifier");
767  ++DiagStr; // Comma.
768  ArgNo2 = *DiagStr++ - '0';
769  DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
770  if (Kind == DiagnosticsEngine::ak_qualtype &&
773  else {
774  // %diff only supports QualTypes. For other kinds of arguments,
775  // use the default printing. For example, if the modifier is:
776  // "%diff{compare $ to $|other text}1,2"
777  // treat it as:
778  // "compare %1 to %2"
779  const char *ArgumentEnd = Argument + ArgumentLen;
780  const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
781  assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&
782  "Found too many '|'s in a %diff modifier!");
783  const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
784  const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
785  const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
786  const char ArgStr2[] = { '%', static_cast<char>('0' + ArgNo2) };
787  FormatDiagnostic(Argument, FirstDollar, OutStr);
788  FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
789  FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
790  FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
791  FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
792  continue;
793  }
794  }
795 
796  switch (Kind) {
797  // ---- STRINGS ----
799  const std::string &S = getArgStdStr(ArgNo);
800  assert(ModifierLen == 0 && "No modifiers for strings yet");
801  OutStr.append(S.begin(), S.end());
802  break;
803  }
805  const char *S = getArgCStr(ArgNo);
806  assert(ModifierLen == 0 && "No modifiers for strings yet");
807 
808  // Don't crash if get passed a null pointer by accident.
809  if (!S)
810  S = "(null)";
811 
812  OutStr.append(S, S + strlen(S));
813  break;
814  }
815  // ---- INTEGERS ----
817  int Val = getArgSInt(ArgNo);
818 
819  if (ModifierIs(Modifier, ModifierLen, "select")) {
820  HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
821  OutStr);
822  } else if (ModifierIs(Modifier, ModifierLen, "s")) {
823  HandleIntegerSModifier(Val, OutStr);
824  } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
825  HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
826  OutStr);
827  } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
828  HandleOrdinalModifier((unsigned)Val, OutStr);
829  } else {
830  assert(ModifierLen == 0 && "Unknown integer modifier");
831  llvm::raw_svector_ostream(OutStr) << Val;
832  }
833  break;
834  }
836  unsigned Val = getArgUInt(ArgNo);
837 
838  if (ModifierIs(Modifier, ModifierLen, "select")) {
839  HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
840  } else if (ModifierIs(Modifier, ModifierLen, "s")) {
841  HandleIntegerSModifier(Val, OutStr);
842  } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
843  HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
844  OutStr);
845  } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
846  HandleOrdinalModifier(Val, OutStr);
847  } else {
848  assert(ModifierLen == 0 && "Unknown integer modifier");
849  llvm::raw_svector_ostream(OutStr) << Val;
850  }
851  break;
852  }
853  // ---- TOKEN SPELLINGS ----
855  tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
856  assert(ModifierLen == 0 && "No modifiers for token kinds yet");
857 
858  llvm::raw_svector_ostream Out(OutStr);
859  if (const char *S = tok::getPunctuatorSpelling(Kind))
860  // Quoted token spelling for punctuators.
861  Out << '\'' << S << '\'';
862  else if (const char *S = tok::getKeywordSpelling(Kind))
863  // Unquoted token spelling for keywords.
864  Out << S;
865  else if (const char *S = getTokenDescForDiagnostic(Kind))
866  // Unquoted translatable token name.
867  Out << S;
868  else if (const char *S = tok::getTokenName(Kind))
869  // Debug name, shouldn't appear in user-facing diagnostics.
870  Out << '<' << S << '>';
871  else
872  Out << "(null)";
873  break;
874  }
875  // ---- NAMES and TYPES ----
876  case DiagnosticsEngine::ak_identifierinfo: {
877  const IdentifierInfo *II = getArgIdentifier(ArgNo);
878  assert(ModifierLen == 0 && "No modifiers for strings yet");
879 
880  // Don't crash if get passed a null pointer by accident.
881  if (!II) {
882  const char *S = "(null)";
883  OutStr.append(S, S + strlen(S));
884  continue;
885  }
886 
887  llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
888  break;
889  }
896  getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
897  StringRef(Modifier, ModifierLen),
898  StringRef(Argument, ArgumentLen),
899  FormattedArgs,
900  OutStr, QualTypeVals);
901  break;
903  // Create a struct with all the info needed for printing.
904  TemplateDiffTypes TDT;
905  TDT.FromType = getRawArg(ArgNo);
906  TDT.ToType = getRawArg(ArgNo2);
907  TDT.ElideType = getDiags()->ElideType;
908  TDT.ShowColors = getDiags()->ShowColors;
909  TDT.TemplateDiffUsed = false;
910  intptr_t val = reinterpret_cast<intptr_t>(&TDT);
911 
912  const char *ArgumentEnd = Argument + ArgumentLen;
913  const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
914 
915  // Print the tree. If this diagnostic already has a tree, skip the
916  // second tree.
917  if (getDiags()->PrintTemplateTree && Tree.empty()) {
918  TDT.PrintFromType = true;
919  TDT.PrintTree = true;
920  getDiags()->ConvertArgToString(Kind, val,
921  StringRef(Modifier, ModifierLen),
922  StringRef(Argument, ArgumentLen),
923  FormattedArgs,
924  Tree, QualTypeVals);
925  // If there is no tree information, fall back to regular printing.
926  if (!Tree.empty()) {
927  FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
928  break;
929  }
930  }
931 
932  // Non-tree printing, also the fall-back when tree printing fails.
933  // The fall-back is triggered when the types compared are not templates.
934  const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
935  const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
936 
937  // Append before text
938  FormatDiagnostic(Argument, FirstDollar, OutStr);
939 
940  // Append first type
941  TDT.PrintTree = false;
942  TDT.PrintFromType = true;
943  getDiags()->ConvertArgToString(Kind, val,
944  StringRef(Modifier, ModifierLen),
945  StringRef(Argument, ArgumentLen),
946  FormattedArgs,
947  OutStr, QualTypeVals);
948  if (!TDT.TemplateDiffUsed)
949  FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
950  TDT.FromType));
951 
952  // Append middle text
953  FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
954 
955  // Append second type
956  TDT.PrintFromType = false;
957  getDiags()->ConvertArgToString(Kind, val,
958  StringRef(Modifier, ModifierLen),
959  StringRef(Argument, ArgumentLen),
960  FormattedArgs,
961  OutStr, QualTypeVals);
962  if (!TDT.TemplateDiffUsed)
963  FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
964  TDT.ToType));
965 
966  // Append end text
967  FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
968  break;
969  }
970 
971  // Remember this argument info for subsequent formatting operations. Turn
972  // std::strings into a null terminated string to make it be the same case as
973  // all the other ones.
975  continue;
976  else if (Kind != DiagnosticsEngine::ak_std_string)
977  FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
978  else
979  FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
980  (intptr_t)getArgStdStr(ArgNo).c_str()));
981 
982  }
983 
984  // Append the type tree to the end of the diagnostics.
985  OutStr.append(Tree.begin(), Tree.end());
986 }
987 
989  StringRef Message)
990  : ID(ID), Level(Level), Loc(), Message(Message) { }
991 
993  const Diagnostic &Info)
994  : ID(Info.getID()), Level(Level)
995 {
996  assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
997  "Valid source location without setting a source manager for diagnostic");
998  if (Info.getLocation().isValid())
999  Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
1000  SmallString<64> Message;
1001  Info.FormatDiagnostic(Message);
1002  this->Message.assign(Message.begin(), Message.end());
1003  this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
1004  this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
1005 }
1006 
1008  StringRef Message, FullSourceLoc Loc,
1010  ArrayRef<FixItHint> FixIts)
1011  : ID(ID), Level(Level), Loc(Loc), Message(Message),
1012  Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1013 {
1014 }
1015 
1016 /// IncludeInDiagnosticCounts - This method (whose default implementation
1017 /// returns true) indicates whether the diagnostics handled by this
1018 /// DiagnosticConsumer should be included in the number of diagnostics
1019 /// reported by DiagnosticsEngine.
1021 
1022 void IgnoringDiagConsumer::anchor() { }
1023 
1025 
1027  DiagnosticsEngine::Level DiagLevel,
1028  const Diagnostic &Info) {
1029  Target.HandleDiagnostic(DiagLevel, Info);
1030 }
1031 
1034  Target.clear();
1035 }
1036 
1038  return Target.IncludeInDiagnosticCounts();
1039 }
1040 
1042  for (unsigned I = 0; I != NumCached; ++I)
1043  FreeList[I] = Cached + I;
1044  NumFreeListEntries = NumCached;
1045 }
1046 
1048  // Don't assert if we are in a CrashRecovery context, as this invariant may
1049  // be invalidated during a crash.
1050  assert((NumFreeListEntries == NumCached ||
1051  llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1052  "A partial is on the lam");
1053 }
1054 
1055 char DiagnosticError::ID;
A diagnostic that indicates a problem or potential problem.
void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, SourceLocation Loc=SourceLocation())
Add the specified mapping to all diagnostics of the specified flavor.
Definition: Diagnostic.cpp:362
unsigned getID() const
Definition: Diagnostic.h:1367
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
Definition: CharInfo.h:94
DiagnosticConsumer * getClient()
Definition: Diagnostic.h:427
fixit_iterator fixit_end() const
Definition: Diagnostic.h:1385
void pushMappings(SourceLocation Loc)
Copies the current DiagMappings and pushes the new copy onto the top of the stack.
Definition: Diagnostic.cpp:97
range_iterator range_begin() const
Definition: Diagnostic.h:1375
static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandleSelectModifier - Handle the integer &#39;select&#39; modifier.
Definition: Diagnostic.cpp:485
Defines the SourceManager interface.
StringRef P
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
Definition: Diagnostic.h:1346
const DiagnosticBuilder & operator<<(const DiagnosticBuilder &DB, const Attr *At)
Definition: Attr.h:195
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
Show all overloads.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1205
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled)
Set the warning-as-error flag for the given diagnostic group.
Definition: Diagnostic.cpp:301
range_iterator range_end() const
Definition: Diagnostic.h:1376
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing)...
Definition: DiagnosticIDs.h:80
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1395
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
Definition: Diagnostic.cpp:139
bool hasSourceManager() const
Definition: Diagnostic.h:1237
static void HandleOrdinalModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleOrdinalModifier - Handle the integer &#39;ord&#39; modifier.
Definition: Diagnostic.cpp:519
unsigned getID() const
Definition: Diagnostic.h:1235
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
Definition: Diagnostic.cpp:91
LineState State
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled)
Set the error-as-fatal flag for the given diagnostic group.
Definition: Diagnostic.cpp:332
Definition: Format.h:1821
std::pair< NullabilityKind, bool > DiagNullabilityKind
A nullability kind paired with a bit indicating whether it used a context-sensitive keyword...
Definition: Diagnostic.h:1200
Values of this type can be null.
const char * getKeywordSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple keyword and contextual keyword tokens like &#39;int&#39; and &#39;dynamic_cast&#39;...
Definition: TokenKinds.cpp:41
static const char * getTokenDescForDiagnostic(tok::TokenKind Kind)
Returns the friendly description for a token kind that will appear without quotes in diagnostic messa...
Definition: Diagnostic.cpp:654
uint32_t Offset
Definition: CacheTokens.cpp:43
const SourceLocation & getLocation() const
Definition: Diagnostic.h:1236
Whether values of this type can be null is (explicitly) unspecified.
bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, diag::Severity Map, SourceLocation Loc=SourceLocation())
Change an entire diagnostic group (e.g.
Definition: Diagnostic.cpp:286
Defines the Diagnostic-related interfaces.
Values of this type can never be null.
diag::Severity getSeverity() const
Present this diagnostic as an error.
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type...
Definition: opencl-c.h:75
StringRef getMessage() const
Definition: Diagnostic.h:1370
void Reset()
Reset the state of the diagnostic object to its initial configuration.
Definition: Diagnostic.cpp:113
bool IncludeInDiagnosticCounts() const override
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
DiagnosticsEngine(IntrusiveRefCntPtr< DiagnosticIDs > Diags, DiagnosticOptions *DiagOpts, DiagnosticConsumer *client=nullptr, bool ShouldOwnClient=true)
Definition: Diagnostic.cpp:60
bool EmitCurrentDiagnostic(bool Force=false)
Emit the current diagnostic and clear the diagnostic state.
Definition: Diagnostic.cpp:400
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:953
static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End)
EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
Definition: Diagnostic.cpp:561
bool isValid() const
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
bool equals(const til::SExpr *E1, const til::SExpr *E2)
SourceLocation End
DiagnosticsEngine::Level getLevel() const
Definition: Diagnostic.h:1368
int Depth
Definition: ASTDiff.cpp:191
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like &#39;!&#39; or &#39;&#39;, and returns NULL for literal and...
Definition: TokenKinds.cpp:32
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
void Clear()
Clear out the current diagnostic.
Definition: Diagnostic.h:792
static const char * ScanFormat(const char *I, const char *E, char Target)
ScanForward - Scans forward, looking for the given character, skipping nested clauses and escaped cha...
Definition: Diagnostic.cpp:455
fixit_iterator fixit_begin() const
Definition: Diagnostic.h:1384
Kind
Encodes a location in the source.
Options for controlling the compiler diagnostics engine.
static void HandleIntegerSModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleIntegerSModifier - Handle the integer &#39;s&#39; modifier.
Definition: Diagnostic.cpp:509
void AddString(StringRef S) const
Definition: Diagnostic.h:1059
OpenMPLinearClauseKind Modifier
Modifier of &#39;linear&#39; clause.
Definition: OpenMPClause.h:86
static LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
Definition: CharInfo.h:132
void setUpgradedFromWarning(bool Value)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
void setNoErrorAsFatal(bool Value)
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info)
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
Definition: Diagnostic.cpp:435
Flavor
Flavors of diagnostics we can emit.
Definition: DiagnosticIDs.h:91
SourceManager & getSourceManager() const
Definition: Diagnostic.h:1238
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
const FullSourceLoc & getLocation() const
Definition: Diagnostic.h:1369
static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT, StringRef Modifier, StringRef Argument, ArrayRef< DiagnosticsEngine::ArgumentValue > PrevArgs, SmallVectorImpl< char > &Output, void *Cookie, ArrayRef< intptr_t > QualTypeVals)
Definition: Diagnostic.cpp:50
Level
The level of the diagnostic, after it has been through mapping.
SyntaxTree::Impl & Tree
Definition: ASTDiff.cpp:193
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
Definition: Diagnostic.cpp:245
bool popMappings(SourceLocation Loc)
Pops the current DiagMappings off the top of the stack, causing the new top of the stack to be the ac...
Definition: Diagnostic.cpp:101
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream...
static bool ModifierIs(const char *Modifier, unsigned ModifierLen, const char(&Str)[StrLen])
ModifierIs - Return true if the specified modifier matches specified string.
Definition: Diagnostic.cpp:448
void setSeverity(diag::Severity Value)
static bool TestPluralRange(unsigned Val, const char *&Start, const char *End)
TestPluralRange - Test if Val is in the parsed range. Modifies Start.
Definition: Diagnostic.cpp:544
ArrayRef< CharSourceRange > getRanges() const
Return an array reference for this diagnostic&#39;s ranges.
Definition: Diagnostic.h:1313
ArrayRef< FixItHint > getFixItHints() const
Definition: Diagnostic.h:1326
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:150
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:61
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1225
const char * getTokenName(TokenKind Kind) LLVM_READNONE
Determines the name of a token as used within the front end.
Definition: TokenKinds.cpp:25
A SourceLocation and its associated SourceManager.
static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandlePluralModifier - Handle the integer &#39;plural&#39; modifier.
Definition: Diagnostic.cpp:627
Present this diagnostic as a fatal error.
void setNoWarningAsError(bool Value)
static unsigned PluralNumber(const char *&Start, const char *End)
PluralNumber - Parse an unsigned integer and advance Start.
Definition: Diagnostic.cpp:532
Present this diagnostic as a warning.
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots...
Definition: Diagnostic.cpp:667
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
enum TokenKind : unsigned
Definition: Diagnostic.h:164