1 //===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Diagnostic-related interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Basic/CharInfo.h"
15 #include "clang/Basic/Diagnostic.h"
16 #include "clang/Basic/DiagnosticOptions.h"
17 #include "clang/Basic/IdentifierTable.h"
18 #include "clang/Basic/PartialDiagnostic.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/Support/CrashRecoveryContext.h"
22 #include "llvm/Support/raw_ostream.h"
23
24 using namespace clang;
25
DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK,intptr_t QT,StringRef Modifier,StringRef Argument,ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,SmallVectorImpl<char> & Output,void * Cookie,ArrayRef<intptr_t> QualTypeVals)26 static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
27 StringRef Modifier, StringRef Argument,
28 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
29 SmallVectorImpl<char> &Output,
30 void *Cookie,
31 ArrayRef<intptr_t> QualTypeVals) {
32 StringRef Str = "<can't format argument>";
33 Output.append(Str.begin(), Str.end());
34 }
35
36
DiagnosticsEngine(const IntrusiveRefCntPtr<DiagnosticIDs> & diags,DiagnosticOptions * DiagOpts,DiagnosticConsumer * client,bool ShouldOwnClient)37 DiagnosticsEngine::DiagnosticsEngine(
38 const IntrusiveRefCntPtr<DiagnosticIDs> &diags,
39 DiagnosticOptions *DiagOpts,
40 DiagnosticConsumer *client, bool ShouldOwnClient)
41 : Diags(diags), DiagOpts(DiagOpts), Client(client),
42 OwnsDiagClient(ShouldOwnClient), SourceMgr(nullptr) {
43 ArgToStringFn = DummyArgToStringFn;
44 ArgToStringCookie = nullptr;
45
46 AllExtensionsSilenced = 0;
47 IgnoreAllWarnings = false;
48 WarningsAsErrors = false;
49 EnableAllWarnings = false;
50 ErrorsAsFatal = false;
51 SuppressSystemWarnings = false;
52 SuppressAllDiagnostics = false;
53 ElideType = true;
54 PrintTemplateTree = false;
55 ShowColors = false;
56 ShowOverloads = Ovl_All;
57 ExtBehavior = diag::Severity::Ignored;
58
59 ErrorLimit = 0;
60 TemplateBacktraceLimit = 0;
61 ConstexprBacktraceLimit = 0;
62
63 Reset();
64 }
65
~DiagnosticsEngine()66 DiagnosticsEngine::~DiagnosticsEngine() {
67 if (OwnsDiagClient)
68 delete Client;
69 }
70
setClient(DiagnosticConsumer * client,bool ShouldOwnClient)71 void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
72 bool ShouldOwnClient) {
73 if (OwnsDiagClient && Client)
74 delete Client;
75
76 Client = client;
77 OwnsDiagClient = ShouldOwnClient;
78 }
79
pushMappings(SourceLocation Loc)80 void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
81 DiagStateOnPushStack.push_back(GetCurDiagState());
82 }
83
popMappings(SourceLocation Loc)84 bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
85 if (DiagStateOnPushStack.empty())
86 return false;
87
88 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
89 // State changed at some point between push/pop.
90 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
91 }
92 DiagStateOnPushStack.pop_back();
93 return true;
94 }
95
Reset()96 void DiagnosticsEngine::Reset() {
97 ErrorOccurred = false;
98 UncompilableErrorOccurred = false;
99 FatalErrorOccurred = false;
100 UnrecoverableErrorOccurred = false;
101
102 NumWarnings = 0;
103 NumErrors = 0;
104 NumErrorsSuppressed = 0;
105 TrapNumErrorsOccurred = 0;
106 TrapNumUnrecoverableErrorsOccurred = 0;
107
108 CurDiagID = ~0U;
109 LastDiagLevel = DiagnosticIDs::Ignored;
110 DelayedDiagID = 0;
111
112 // Clear state related to #pragma diagnostic.
113 DiagStates.clear();
114 DiagStatePoints.clear();
115 DiagStateOnPushStack.clear();
116
117 // Create a DiagState and DiagStatePoint representing diagnostic changes
118 // through command-line.
119 DiagStates.push_back(DiagState());
120 DiagStatePoints.push_back(DiagStatePoint(&DiagStates.back(), FullSourceLoc()));
121 }
122
SetDelayedDiagnostic(unsigned DiagID,StringRef Arg1,StringRef Arg2)123 void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
124 StringRef Arg2) {
125 if (DelayedDiagID)
126 return;
127
128 DelayedDiagID = DiagID;
129 DelayedDiagArg1 = Arg1.str();
130 DelayedDiagArg2 = Arg2.str();
131 }
132
ReportDelayed()133 void DiagnosticsEngine::ReportDelayed() {
134 Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2;
135 DelayedDiagID = 0;
136 DelayedDiagArg1.clear();
137 DelayedDiagArg2.clear();
138 }
139
140 DiagnosticsEngine::DiagStatePointsTy::iterator
GetDiagStatePointForLoc(SourceLocation L) const141 DiagnosticsEngine::GetDiagStatePointForLoc(SourceLocation L) const {
142 assert(!DiagStatePoints.empty());
143 assert(DiagStatePoints.front().Loc.isInvalid() &&
144 "Should have created a DiagStatePoint for command-line");
145
146 if (!SourceMgr)
147 return DiagStatePoints.end() - 1;
148
149 FullSourceLoc Loc(L, *SourceMgr);
150 if (Loc.isInvalid())
151 return DiagStatePoints.end() - 1;
152
153 DiagStatePointsTy::iterator Pos = DiagStatePoints.end();
154 FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
155 if (LastStateChangePos.isValid() &&
156 Loc.isBeforeInTranslationUnitThan(LastStateChangePos))
157 Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(),
158 DiagStatePoint(nullptr, Loc));
159 --Pos;
160 return Pos;
161 }
162
setSeverity(diag::kind Diag,diag::Severity Map,SourceLocation L)163 void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
164 SourceLocation L) {
165 assert(Diag < diag::DIAG_UPPER_LIMIT &&
166 "Can only map builtin diagnostics");
167 assert((Diags->isBuiltinWarningOrExtension(Diag) ||
168 (Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
169 "Cannot map errors into warnings!");
170 assert(!DiagStatePoints.empty());
171 assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location");
172
173 FullSourceLoc Loc = SourceMgr? FullSourceLoc(L, *SourceMgr) : FullSourceLoc();
174 FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
175 // Don't allow a mapping to a warning override an error/fatal mapping.
176 if (Map == diag::Severity::Warning) {
177 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
178 if (Info.getSeverity() == diag::Severity::Error ||
179 Info.getSeverity() == diag::Severity::Fatal)
180 Map = Info.getSeverity();
181 }
182 DiagnosticMapping Mapping = makeUserMapping(Map, L);
183
184 // Common case; setting all the diagnostics of a group in one place.
185 if (Loc.isInvalid() || Loc == LastStateChangePos) {
186 GetCurDiagState()->setMapping(Diag, Mapping);
187 return;
188 }
189
190 // Another common case; modifying diagnostic state in a source location
191 // after the previous one.
192 if ((Loc.isValid() && LastStateChangePos.isInvalid()) ||
193 LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) {
194 // A diagnostic pragma occurred, create a new DiagState initialized with
195 // the current one and a new DiagStatePoint to record at which location
196 // the new state became active.
197 DiagStates.push_back(*GetCurDiagState());
198 PushDiagStatePoint(&DiagStates.back(), Loc);
199 GetCurDiagState()->setMapping(Diag, Mapping);
200 return;
201 }
202
203 // We allow setting the diagnostic state in random source order for
204 // completeness but it should not be actually happening in normal practice.
205
206 DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc);
207 assert(Pos != DiagStatePoints.end());
208
209 // Update all diagnostic states that are active after the given location.
210 for (DiagStatePointsTy::iterator
211 I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) {
212 GetCurDiagState()->setMapping(Diag, Mapping);
213 }
214
215 // If the location corresponds to an existing point, just update its state.
216 if (Pos->Loc == Loc) {
217 GetCurDiagState()->setMapping(Diag, Mapping);
218 return;
219 }
220
221 // Create a new state/point and fit it into the vector of DiagStatePoints
222 // so that the vector is always ordered according to location.
223 assert(Pos->Loc.isBeforeInTranslationUnitThan(Loc));
224 DiagStates.push_back(*Pos->State);
225 DiagState *NewState = &DiagStates.back();
226 GetCurDiagState()->setMapping(Diag, Mapping);
227 DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState,
228 FullSourceLoc(Loc, *SourceMgr)));
229 }
230
setSeverityForGroup(StringRef Group,diag::Severity Map,SourceLocation Loc)231 bool DiagnosticsEngine::setSeverityForGroup(StringRef Group, diag::Severity Map,
232 SourceLocation Loc) {
233 // Get the diagnostics in this group.
234 SmallVector<diag::kind, 8> GroupDiags;
235 if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
236 return true;
237
238 // Set the mapping.
239 for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i)
240 setSeverity(GroupDiags[i], Map, Loc);
241
242 return false;
243 }
244
setDiagnosticGroupWarningAsError(StringRef Group,bool Enabled)245 bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
246 bool Enabled) {
247 // If we are enabling this feature, just set the diagnostic mappings to map to
248 // errors.
249 if (Enabled)
250 return setSeverityForGroup(Group, diag::Severity::Error);
251
252 // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
253 // potentially downgrade anything already mapped to be a warning.
254
255 // Get the diagnostics in this group.
256 SmallVector<diag::kind, 8> GroupDiags;
257 if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
258 return true;
259
260 // Perform the mapping change.
261 for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
262 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]);
263
264 if (Info.getSeverity() == diag::Severity::Error ||
265 Info.getSeverity() == diag::Severity::Fatal)
266 Info.setSeverity(diag::Severity::Warning);
267
268 Info.setNoWarningAsError(true);
269 }
270
271 return false;
272 }
273
setDiagnosticGroupErrorAsFatal(StringRef Group,bool Enabled)274 bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
275 bool Enabled) {
276 // If we are enabling this feature, just set the diagnostic mappings to map to
277 // fatal errors.
278 if (Enabled)
279 return setSeverityForGroup(Group, diag::Severity::Fatal);
280
281 // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
282 // potentially downgrade anything already mapped to be an error.
283
284 // Get the diagnostics in this group.
285 SmallVector<diag::kind, 8> GroupDiags;
286 if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
287 return true;
288
289 // Perform the mapping change.
290 for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
291 DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(GroupDiags[i]);
292
293 if (Info.getSeverity() == diag::Severity::Fatal)
294 Info.setSeverity(diag::Severity::Error);
295
296 Info.setNoErrorAsFatal(true);
297 }
298
299 return false;
300 }
301
setSeverityForAll(diag::Severity Map,SourceLocation Loc)302 void DiagnosticsEngine::setSeverityForAll(diag::Severity Map,
303 SourceLocation Loc) {
304 // Get all the diagnostics.
305 SmallVector<diag::kind, 64> AllDiags;
306 Diags->getAllDiagnostics(AllDiags);
307
308 // Set the mapping.
309 for (unsigned i = 0, e = AllDiags.size(); i != e; ++i)
310 if (Diags->isBuiltinWarningOrExtension(AllDiags[i]))
311 setSeverity(AllDiags[i], Map, Loc);
312 }
313
Report(const StoredDiagnostic & storedDiag)314 void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
315 assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
316
317 CurDiagLoc = storedDiag.getLocation();
318 CurDiagID = storedDiag.getID();
319 NumDiagArgs = 0;
320
321 DiagRanges.clear();
322 DiagRanges.reserve(storedDiag.range_size());
323 for (StoredDiagnostic::range_iterator
324 RI = storedDiag.range_begin(),
325 RE = storedDiag.range_end(); RI != RE; ++RI)
326 DiagRanges.push_back(*RI);
327
328 DiagFixItHints.clear();
329 DiagFixItHints.reserve(storedDiag.fixit_size());
330 for (StoredDiagnostic::fixit_iterator
331 FI = storedDiag.fixit_begin(),
332 FE = storedDiag.fixit_end(); FI != FE; ++FI)
333 DiagFixItHints.push_back(*FI);
334
335 assert(Client && "DiagnosticConsumer not set!");
336 Level DiagLevel = storedDiag.getLevel();
337 Diagnostic Info(this, storedDiag.getMessage());
338 Client->HandleDiagnostic(DiagLevel, Info);
339 if (Client->IncludeInDiagnosticCounts()) {
340 if (DiagLevel == DiagnosticsEngine::Warning)
341 ++NumWarnings;
342 }
343
344 CurDiagID = ~0U;
345 }
346
EmitCurrentDiagnostic(bool Force)347 bool DiagnosticsEngine::EmitCurrentDiagnostic(bool Force) {
348 assert(getClient() && "DiagnosticClient not set!");
349
350 bool Emitted;
351 if (Force) {
352 Diagnostic Info(this);
353
354 // Figure out the diagnostic level of this message.
355 DiagnosticIDs::Level DiagLevel
356 = Diags->getDiagnosticLevel(Info.getID(), Info.getLocation(), *this);
357
358 Emitted = (DiagLevel != DiagnosticIDs::Ignored);
359 if (Emitted) {
360 // Emit the diagnostic regardless of suppression level.
361 Diags->EmitDiag(*this, DiagLevel);
362 }
363 } else {
364 // Process the diagnostic, sending the accumulated information to the
365 // DiagnosticConsumer.
366 Emitted = ProcessDiag();
367 }
368
369 // Clear out the current diagnostic object.
370 unsigned DiagID = CurDiagID;
371 Clear();
372
373 // If there was a delayed diagnostic, emit it now.
374 if (!Force && DelayedDiagID && DelayedDiagID != DiagID)
375 ReportDelayed();
376
377 return Emitted;
378 }
379
380
~DiagnosticConsumer()381 DiagnosticConsumer::~DiagnosticConsumer() {}
382
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)383 void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
384 const Diagnostic &Info) {
385 if (!IncludeInDiagnosticCounts())
386 return;
387
388 if (DiagLevel == DiagnosticsEngine::Warning)
389 ++NumWarnings;
390 else if (DiagLevel >= DiagnosticsEngine::Error)
391 ++NumErrors;
392 }
393
394 /// ModifierIs - Return true if the specified modifier matches specified string.
395 template <std::size_t StrLen>
ModifierIs(const char * Modifier,unsigned ModifierLen,const char (& Str)[StrLen])396 static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
397 const char (&Str)[StrLen]) {
398 return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
399 }
400
401 /// ScanForward - Scans forward, looking for the given character, skipping
402 /// nested clauses and escaped characters.
ScanFormat(const char * I,const char * E,char Target)403 static const char *ScanFormat(const char *I, const char *E, char Target) {
404 unsigned Depth = 0;
405
406 for ( ; I != E; ++I) {
407 if (Depth == 0 && *I == Target) return I;
408 if (Depth != 0 && *I == '}') Depth--;
409
410 if (*I == '%') {
411 I++;
412 if (I == E) break;
413
414 // Escaped characters get implicitly skipped here.
415
416 // Format specifier.
417 if (!isDigit(*I) && !isPunctuation(*I)) {
418 for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ;
419 if (I == E) break;
420 if (*I == '{')
421 Depth++;
422 }
423 }
424 }
425 return E;
426 }
427
428 /// HandleSelectModifier - Handle the integer 'select' modifier. This is used
429 /// like this: %select{foo|bar|baz}2. This means that the integer argument
430 /// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'.
431 /// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'.
432 /// This is very useful for certain classes of variant diagnostics.
HandleSelectModifier(const Diagnostic & DInfo,unsigned ValNo,const char * Argument,unsigned ArgumentLen,SmallVectorImpl<char> & OutStr)433 static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
434 const char *Argument, unsigned ArgumentLen,
435 SmallVectorImpl<char> &OutStr) {
436 const char *ArgumentEnd = Argument+ArgumentLen;
437
438 // Skip over 'ValNo' |'s.
439 while (ValNo) {
440 const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
441 assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
442 " larger than the number of options in the diagnostic string!");
443 Argument = NextVal+1; // Skip this string.
444 --ValNo;
445 }
446
447 // Get the end of the value. This is either the } or the |.
448 const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
449
450 // Recursively format the result of the select clause into the output string.
451 DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
452 }
453
454 /// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the
455 /// letter 's' to the string if the value is not 1. This is used in cases like
456 /// this: "you idiot, you have %4 parameter%s4!".
HandleIntegerSModifier(unsigned ValNo,SmallVectorImpl<char> & OutStr)457 static void HandleIntegerSModifier(unsigned ValNo,
458 SmallVectorImpl<char> &OutStr) {
459 if (ValNo != 1)
460 OutStr.push_back('s');
461 }
462
463 /// HandleOrdinalModifier - Handle the integer 'ord' modifier. This
464 /// prints the ordinal form of the given integer, with 1 corresponding
465 /// to the first ordinal. Currently this is hard-coded to use the
466 /// English form.
HandleOrdinalModifier(unsigned ValNo,SmallVectorImpl<char> & OutStr)467 static void HandleOrdinalModifier(unsigned ValNo,
468 SmallVectorImpl<char> &OutStr) {
469 assert(ValNo != 0 && "ValNo must be strictly positive!");
470
471 llvm::raw_svector_ostream Out(OutStr);
472
473 // We could use text forms for the first N ordinals, but the numeric
474 // forms are actually nicer in diagnostics because they stand out.
475 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
476 }
477
478
479 /// PluralNumber - Parse an unsigned integer and advance Start.
PluralNumber(const char * & Start,const char * End)480 static unsigned PluralNumber(const char *&Start, const char *End) {
481 // Programming 101: Parse a decimal number :-)
482 unsigned Val = 0;
483 while (Start != End && *Start >= '0' && *Start <= '9') {
484 Val *= 10;
485 Val += *Start - '0';
486 ++Start;
487 }
488 return Val;
489 }
490
491 /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
TestPluralRange(unsigned Val,const char * & Start,const char * End)492 static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
493 if (*Start != '[') {
494 unsigned Ref = PluralNumber(Start, End);
495 return Ref == Val;
496 }
497
498 ++Start;
499 unsigned Low = PluralNumber(Start, End);
500 assert(*Start == ',' && "Bad plural expression syntax: expected ,");
501 ++Start;
502 unsigned High = PluralNumber(Start, End);
503 assert(*Start == ']' && "Bad plural expression syntax: expected )");
504 ++Start;
505 return Low <= Val && Val <= High;
506 }
507
508 /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
EvalPluralExpr(unsigned ValNo,const char * Start,const char * End)509 static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
510 // Empty condition?
511 if (*Start == ':')
512 return true;
513
514 while (1) {
515 char C = *Start;
516 if (C == '%') {
517 // Modulo expression
518 ++Start;
519 unsigned Arg = PluralNumber(Start, End);
520 assert(*Start == '=' && "Bad plural expression syntax: expected =");
521 ++Start;
522 unsigned ValMod = ValNo % Arg;
523 if (TestPluralRange(ValMod, Start, End))
524 return true;
525 } else {
526 assert((C == '[' || (C >= '0' && C <= '9')) &&
527 "Bad plural expression syntax: unexpected character");
528 // Range expression
529 if (TestPluralRange(ValNo, Start, End))
530 return true;
531 }
532
533 // Scan for next or-expr part.
534 Start = std::find(Start, End, ',');
535 if (Start == End)
536 break;
537 ++Start;
538 }
539 return false;
540 }
541
542 /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
543 /// for complex plural forms, or in languages where all plurals are complex.
544 /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
545 /// conditions that are tested in order, the form corresponding to the first
546 /// that applies being emitted. The empty condition is always true, making the
547 /// last form a default case.
548 /// Conditions are simple boolean expressions, where n is the number argument.
549 /// Here are the rules.
550 /// condition := expression | empty
551 /// empty := -> always true
552 /// expression := numeric [',' expression] -> logical or
553 /// numeric := range -> true if n in range
554 /// | '%' number '=' range -> true if n % number in range
555 /// range := number
556 /// | '[' number ',' number ']' -> ranges are inclusive both ends
557 ///
558 /// Here are some examples from the GNU gettext manual written in this form:
559 /// English:
560 /// {1:form0|:form1}
561 /// Latvian:
562 /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
563 /// Gaeilge:
564 /// {1:form0|2:form1|:form2}
565 /// Romanian:
566 /// {1:form0|0,%100=[1,19]:form1|:form2}
567 /// Lithuanian:
568 /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
569 /// Russian (requires repeated form):
570 /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
571 /// Slovak
572 /// {1:form0|[2,4]:form1|:form2}
573 /// Polish (requires repeated form):
574 /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
HandlePluralModifier(const Diagnostic & DInfo,unsigned ValNo,const char * Argument,unsigned ArgumentLen,SmallVectorImpl<char> & OutStr)575 static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
576 const char *Argument, unsigned ArgumentLen,
577 SmallVectorImpl<char> &OutStr) {
578 const char *ArgumentEnd = Argument + ArgumentLen;
579 while (1) {
580 assert(Argument < ArgumentEnd && "Plural expression didn't match.");
581 const char *ExprEnd = Argument;
582 while (*ExprEnd != ':') {
583 assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
584 ++ExprEnd;
585 }
586 if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
587 Argument = ExprEnd + 1;
588 ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
589
590 // Recursively format the result of the plural clause into the
591 // output string.
592 DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
593 return;
594 }
595 Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
596 }
597 }
598
599 /// \brief Returns the friendly description for a token kind that will appear
600 /// without quotes in diagnostic messages. These strings may be translatable in
601 /// future.
getTokenDescForDiagnostic(tok::TokenKind Kind)602 static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) {
603 switch (Kind) {
604 case tok::identifier:
605 return "identifier";
606 default:
607 return nullptr;
608 }
609 }
610
611 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
612 /// formal arguments into the %0 slots. The result is appended onto the Str
613 /// array.
614 void Diagnostic::
FormatDiagnostic(SmallVectorImpl<char> & OutStr) const615 FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
616 if (!StoredDiagMessage.empty()) {
617 OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
618 return;
619 }
620
621 StringRef Diag =
622 getDiags()->getDiagnosticIDs()->getDescription(getID());
623
624 FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
625 }
626
627 void Diagnostic::
FormatDiagnostic(const char * DiagStr,const char * DiagEnd,SmallVectorImpl<char> & OutStr) const628 FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
629 SmallVectorImpl<char> &OutStr) const {
630
631 /// FormattedArgs - Keep track of all of the arguments formatted by
632 /// ConvertArgToString and pass them into subsequent calls to
633 /// ConvertArgToString, allowing the implementation to avoid redundancies in
634 /// obvious cases.
635 SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
636
637 /// QualTypeVals - Pass a vector of arrays so that QualType names can be
638 /// compared to see if more information is needed to be printed.
639 SmallVector<intptr_t, 2> QualTypeVals;
640 SmallVector<char, 64> Tree;
641
642 for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
643 if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
644 QualTypeVals.push_back(getRawArg(i));
645
646 while (DiagStr != DiagEnd) {
647 if (DiagStr[0] != '%') {
648 // Append non-%0 substrings to Str if we have one.
649 const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
650 OutStr.append(DiagStr, StrEnd);
651 DiagStr = StrEnd;
652 continue;
653 } else if (isPunctuation(DiagStr[1])) {
654 OutStr.push_back(DiagStr[1]); // %% -> %.
655 DiagStr += 2;
656 continue;
657 }
658
659 // Skip the %.
660 ++DiagStr;
661
662 // This must be a placeholder for a diagnostic argument. The format for a
663 // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
664 // The digit is a number from 0-9 indicating which argument this comes from.
665 // The modifier is a string of digits from the set [-a-z]+, arguments is a
666 // brace enclosed string.
667 const char *Modifier = nullptr, *Argument = nullptr;
668 unsigned ModifierLen = 0, ArgumentLen = 0;
669
670 // Check to see if we have a modifier. If so eat it.
671 if (!isDigit(DiagStr[0])) {
672 Modifier = DiagStr;
673 while (DiagStr[0] == '-' ||
674 (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
675 ++DiagStr;
676 ModifierLen = DiagStr-Modifier;
677
678 // If we have an argument, get it next.
679 if (DiagStr[0] == '{') {
680 ++DiagStr; // Skip {.
681 Argument = DiagStr;
682
683 DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
684 assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
685 ArgumentLen = DiagStr-Argument;
686 ++DiagStr; // Skip }.
687 }
688 }
689
690 assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic");
691 unsigned ArgNo = *DiagStr++ - '0';
692
693 // Only used for type diffing.
694 unsigned ArgNo2 = ArgNo;
695
696 DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
697 if (ModifierIs(Modifier, ModifierLen, "diff")) {
698 assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) &&
699 "Invalid format for diff modifier");
700 ++DiagStr; // Comma.
701 ArgNo2 = *DiagStr++ - '0';
702 DiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2);
703 if (Kind == DiagnosticsEngine::ak_qualtype &&
704 Kind2 == DiagnosticsEngine::ak_qualtype)
705 Kind = DiagnosticsEngine::ak_qualtype_pair;
706 else {
707 // %diff only supports QualTypes. For other kinds of arguments,
708 // use the default printing. For example, if the modifier is:
709 // "%diff{compare $ to $|other text}1,2"
710 // treat it as:
711 // "compare %1 to %2"
712 const char *Pipe = ScanFormat(Argument, Argument + ArgumentLen, '|');
713 const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
714 const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
715 const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
716 const char ArgStr2[] = { '%', static_cast<char>('0' + ArgNo2) };
717 FormatDiagnostic(Argument, FirstDollar, OutStr);
718 FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
719 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
720 FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
721 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
722 continue;
723 }
724 }
725
726 switch (Kind) {
727 // ---- STRINGS ----
728 case DiagnosticsEngine::ak_std_string: {
729 const std::string &S = getArgStdStr(ArgNo);
730 assert(ModifierLen == 0 && "No modifiers for strings yet");
731 OutStr.append(S.begin(), S.end());
732 break;
733 }
734 case DiagnosticsEngine::ak_c_string: {
735 const char *S = getArgCStr(ArgNo);
736 assert(ModifierLen == 0 && "No modifiers for strings yet");
737
738 // Don't crash if get passed a null pointer by accident.
739 if (!S)
740 S = "(null)";
741
742 OutStr.append(S, S + strlen(S));
743 break;
744 }
745 // ---- INTEGERS ----
746 case DiagnosticsEngine::ak_sint: {
747 int Val = getArgSInt(ArgNo);
748
749 if (ModifierIs(Modifier, ModifierLen, "select")) {
750 HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
751 OutStr);
752 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
753 HandleIntegerSModifier(Val, OutStr);
754 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
755 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
756 OutStr);
757 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
758 HandleOrdinalModifier((unsigned)Val, OutStr);
759 } else {
760 assert(ModifierLen == 0 && "Unknown integer modifier");
761 llvm::raw_svector_ostream(OutStr) << Val;
762 }
763 break;
764 }
765 case DiagnosticsEngine::ak_uint: {
766 unsigned Val = getArgUInt(ArgNo);
767
768 if (ModifierIs(Modifier, ModifierLen, "select")) {
769 HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
770 } else if (ModifierIs(Modifier, ModifierLen, "s")) {
771 HandleIntegerSModifier(Val, OutStr);
772 } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
773 HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
774 OutStr);
775 } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
776 HandleOrdinalModifier(Val, OutStr);
777 } else {
778 assert(ModifierLen == 0 && "Unknown integer modifier");
779 llvm::raw_svector_ostream(OutStr) << Val;
780 }
781 break;
782 }
783 // ---- TOKEN SPELLINGS ----
784 case DiagnosticsEngine::ak_tokenkind: {
785 tok::TokenKind Kind = static_cast<tok::TokenKind>(getRawArg(ArgNo));
786 assert(ModifierLen == 0 && "No modifiers for token kinds yet");
787
788 llvm::raw_svector_ostream Out(OutStr);
789 if (const char *S = tok::getPunctuatorSpelling(Kind))
790 // Quoted token spelling for punctuators.
791 Out << '\'' << S << '\'';
792 else if (const char *S = tok::getKeywordSpelling(Kind))
793 // Unquoted token spelling for keywords.
794 Out << S;
795 else if (const char *S = getTokenDescForDiagnostic(Kind))
796 // Unquoted translatable token name.
797 Out << S;
798 else if (const char *S = tok::getTokenName(Kind))
799 // Debug name, shouldn't appear in user-facing diagnostics.
800 Out << '<' << S << '>';
801 else
802 Out << "(null)";
803 break;
804 }
805 // ---- NAMES and TYPES ----
806 case DiagnosticsEngine::ak_identifierinfo: {
807 const IdentifierInfo *II = getArgIdentifier(ArgNo);
808 assert(ModifierLen == 0 && "No modifiers for strings yet");
809
810 // Don't crash if get passed a null pointer by accident.
811 if (!II) {
812 const char *S = "(null)";
813 OutStr.append(S, S + strlen(S));
814 continue;
815 }
816
817 llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
818 break;
819 }
820 case DiagnosticsEngine::ak_qualtype:
821 case DiagnosticsEngine::ak_declarationname:
822 case DiagnosticsEngine::ak_nameddecl:
823 case DiagnosticsEngine::ak_nestednamespec:
824 case DiagnosticsEngine::ak_declcontext:
825 case DiagnosticsEngine::ak_attr:
826 getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
827 StringRef(Modifier, ModifierLen),
828 StringRef(Argument, ArgumentLen),
829 FormattedArgs,
830 OutStr, QualTypeVals);
831 break;
832 case DiagnosticsEngine::ak_qualtype_pair:
833 // Create a struct with all the info needed for printing.
834 TemplateDiffTypes TDT;
835 TDT.FromType = getRawArg(ArgNo);
836 TDT.ToType = getRawArg(ArgNo2);
837 TDT.ElideType = getDiags()->ElideType;
838 TDT.ShowColors = getDiags()->ShowColors;
839 TDT.TemplateDiffUsed = false;
840 intptr_t val = reinterpret_cast<intptr_t>(&TDT);
841
842 const char *ArgumentEnd = Argument + ArgumentLen;
843 const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
844
845 // Print the tree. If this diagnostic already has a tree, skip the
846 // second tree.
847 if (getDiags()->PrintTemplateTree && Tree.empty()) {
848 TDT.PrintFromType = true;
849 TDT.PrintTree = true;
850 getDiags()->ConvertArgToString(Kind, val,
851 StringRef(Modifier, ModifierLen),
852 StringRef(Argument, ArgumentLen),
853 FormattedArgs,
854 Tree, QualTypeVals);
855 // If there is no tree information, fall back to regular printing.
856 if (!Tree.empty()) {
857 FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
858 break;
859 }
860 }
861
862 // Non-tree printing, also the fall-back when tree printing fails.
863 // The fall-back is triggered when the types compared are not templates.
864 const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$');
865 const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$');
866
867 // Append before text
868 FormatDiagnostic(Argument, FirstDollar, OutStr);
869
870 // Append first type
871 TDT.PrintTree = false;
872 TDT.PrintFromType = true;
873 getDiags()->ConvertArgToString(Kind, val,
874 StringRef(Modifier, ModifierLen),
875 StringRef(Argument, ArgumentLen),
876 FormattedArgs,
877 OutStr, QualTypeVals);
878 if (!TDT.TemplateDiffUsed)
879 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
880 TDT.FromType));
881
882 // Append middle text
883 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
884
885 // Append second type
886 TDT.PrintFromType = false;
887 getDiags()->ConvertArgToString(Kind, val,
888 StringRef(Modifier, ModifierLen),
889 StringRef(Argument, ArgumentLen),
890 FormattedArgs,
891 OutStr, QualTypeVals);
892 if (!TDT.TemplateDiffUsed)
893 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_qualtype,
894 TDT.ToType));
895
896 // Append end text
897 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
898 break;
899 }
900
901 // Remember this argument info for subsequent formatting operations. Turn
902 // std::strings into a null terminated string to make it be the same case as
903 // all the other ones.
904 if (Kind == DiagnosticsEngine::ak_qualtype_pair)
905 continue;
906 else if (Kind != DiagnosticsEngine::ak_std_string)
907 FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
908 else
909 FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
910 (intptr_t)getArgStdStr(ArgNo).c_str()));
911
912 }
913
914 // Append the type tree to the end of the diagnostics.
915 OutStr.append(Tree.begin(), Tree.end());
916 }
917
StoredDiagnostic()918 StoredDiagnostic::StoredDiagnostic() { }
919
StoredDiagnostic(DiagnosticsEngine::Level Level,unsigned ID,StringRef Message)920 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
921 StringRef Message)
922 : ID(ID), Level(Level), Loc(), Message(Message) { }
923
StoredDiagnostic(DiagnosticsEngine::Level Level,const Diagnostic & Info)924 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
925 const Diagnostic &Info)
926 : ID(Info.getID()), Level(Level)
927 {
928 assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
929 "Valid source location without setting a source manager for diagnostic");
930 if (Info.getLocation().isValid())
931 Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
932 SmallString<64> Message;
933 Info.FormatDiagnostic(Message);
934 this->Message.assign(Message.begin(), Message.end());
935
936 Ranges.reserve(Info.getNumRanges());
937 for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
938 Ranges.push_back(Info.getRange(I));
939
940 FixIts.reserve(Info.getNumFixItHints());
941 for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
942 FixIts.push_back(Info.getFixItHint(I));
943 }
944
StoredDiagnostic(DiagnosticsEngine::Level Level,unsigned ID,StringRef Message,FullSourceLoc Loc,ArrayRef<CharSourceRange> Ranges,ArrayRef<FixItHint> FixIts)945 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
946 StringRef Message, FullSourceLoc Loc,
947 ArrayRef<CharSourceRange> Ranges,
948 ArrayRef<FixItHint> FixIts)
949 : ID(ID), Level(Level), Loc(Loc), Message(Message),
950 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
951 {
952 }
953
~StoredDiagnostic()954 StoredDiagnostic::~StoredDiagnostic() { }
955
956 /// IncludeInDiagnosticCounts - This method (whose default implementation
957 /// returns true) indicates whether the diagnostics handled by this
958 /// DiagnosticConsumer should be included in the number of diagnostics
959 /// reported by DiagnosticsEngine.
IncludeInDiagnosticCounts() const960 bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
961
anchor()962 void IgnoringDiagConsumer::anchor() { }
963
~ForwardingDiagnosticConsumer()964 ForwardingDiagnosticConsumer::~ForwardingDiagnosticConsumer() {}
965
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)966 void ForwardingDiagnosticConsumer::HandleDiagnostic(
967 DiagnosticsEngine::Level DiagLevel,
968 const Diagnostic &Info) {
969 Target.HandleDiagnostic(DiagLevel, Info);
970 }
971
clear()972 void ForwardingDiagnosticConsumer::clear() {
973 DiagnosticConsumer::clear();
974 Target.clear();
975 }
976
IncludeInDiagnosticCounts() const977 bool ForwardingDiagnosticConsumer::IncludeInDiagnosticCounts() const {
978 return Target.IncludeInDiagnosticCounts();
979 }
980
StorageAllocator()981 PartialDiagnostic::StorageAllocator::StorageAllocator() {
982 for (unsigned I = 0; I != NumCached; ++I)
983 FreeList[I] = Cached + I;
984 NumFreeListEntries = NumCached;
985 }
986
~StorageAllocator()987 PartialDiagnostic::StorageAllocator::~StorageAllocator() {
988 // Don't assert if we are in a CrashRecovery context, as this invariant may
989 // be invalidated during a crash.
990 assert((NumFreeListEntries == NumCached ||
991 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
992 "A partial is on the lamb");
993 }
994