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