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