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