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