1 //===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the Diagnostic-related interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Basic/Diagnostic.h"
15 
16 #include "clang/Lex/LexDiagnostic.h"
17 #include "clang/Parse/ParseDiagnostic.h"
18 #include "clang/AST/ASTDiagnostic.h"
19 #include "clang/Sema/SemaDiagnostic.h"
20 #include "clang/Frontend/FrontendDiagnostic.h"
21 #include "clang/Analysis/AnalysisDiagnostic.h"
22 #include "clang/Driver/DriverDiagnostic.h"
23 
24 #include "clang/Basic/IdentifierTable.h"
25 #include "clang/Basic/SourceLocation.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include <vector>
29 #include <map>
30 #include <cstring>
31 using namespace clang;
32 
33 //===----------------------------------------------------------------------===//
34 // Builtin Diagnostic information
35 //===----------------------------------------------------------------------===//
36 
37 // Diagnostic classes.
38 enum {
39   CLASS_NOTE       = 0x01,
40   CLASS_WARNING    = 0x02,
41   CLASS_EXTENSION  = 0x03,
42   CLASS_ERROR      = 0x04
43 };
44 
45 struct StaticDiagInfoRec {
46   unsigned short DiagID;
47   unsigned Mapping : 3;
48   unsigned Class : 3;
49   const char *Description;
50   const char *OptionGroup;
51 
52   bool operator<(const StaticDiagInfoRec &RHS) const {
53     return DiagID < RHS.DiagID;
54   }
55   bool operator>(const StaticDiagInfoRec &RHS) const {
56     return DiagID > RHS.DiagID;
57   }
58 };
59 
60 static const StaticDiagInfoRec StaticDiagInfo[] = {
61 #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP) \
62   { diag::ENUM, DEFAULT_MAPPING, CLASS, DESC, GROUP },
63 #include "clang/Basic/DiagnosticCommonKinds.inc"
64 #include "clang/Basic/DiagnosticDriverKinds.inc"
65 #include "clang/Basic/DiagnosticFrontendKinds.inc"
66 #include "clang/Basic/DiagnosticLexKinds.inc"
67 #include "clang/Basic/DiagnosticParseKinds.inc"
68 #include "clang/Basic/DiagnosticASTKinds.inc"
69 #include "clang/Basic/DiagnosticSemaKinds.inc"
70 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
71 { 0, 0, 0, 0, 0 }
72 };
73 #undef DIAG
74 
75 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
76 /// or null if the ID is invalid.
77 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
78   unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
79 
80   // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
81 #ifndef NDEBUG
82   static bool IsFirst = true;
83   if (IsFirst) {
84     for (unsigned i = 1; i != NumDiagEntries; ++i)
85       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
86              "Improperly sorted diag info");
87     IsFirst = false;
88   }
89 #endif
90 
91   // Search the diagnostic table with a binary search.
92   StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0 };
93 
94   const StaticDiagInfoRec *Found =
95     std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
96   if (Found == StaticDiagInfo + NumDiagEntries ||
97       Found->DiagID != DiagID)
98     return 0;
99 
100   return Found;
101 }
102 
103 static unsigned GetDefaultDiagMapping(unsigned DiagID) {
104   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
105     return Info->Mapping;
106   return diag::MAP_FATAL;
107 }
108 
109 /// getWarningOptionForDiag - Return the lowest-level warning option that
110 /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
111 /// the diagnostic, this returns null.
112 const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
113   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
114     return Info->OptionGroup;
115   return 0;
116 }
117 
118 /// getDiagClass - Return the class field of the diagnostic.
119 ///
120 static unsigned getBuiltinDiagClass(unsigned DiagID) {
121   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
122     return Info->Class;
123   return ~0U;
124 }
125 
126 //===----------------------------------------------------------------------===//
127 // Custom Diagnostic information
128 //===----------------------------------------------------------------------===//
129 
130 namespace clang {
131   namespace diag {
132     class CustomDiagInfo {
133       typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
134       std::vector<DiagDesc> DiagInfo;
135       std::map<DiagDesc, unsigned> DiagIDs;
136     public:
137 
138       /// getDescription - Return the description of the specified custom
139       /// diagnostic.
140       const char *getDescription(unsigned DiagID) const {
141         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
142                "Invalid diagnosic ID");
143         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
144       }
145 
146       /// getLevel - Return the level of the specified custom diagnostic.
147       Diagnostic::Level getLevel(unsigned DiagID) const {
148         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
149                "Invalid diagnosic ID");
150         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
151       }
152 
153       unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message,
154                                  Diagnostic &Diags) {
155         DiagDesc D(L, Message);
156         // Check to see if it already exists.
157         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
158         if (I != DiagIDs.end() && I->first == D)
159           return I->second;
160 
161         // If not, assign a new ID.
162         unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
163         DiagIDs.insert(std::make_pair(D, ID));
164         DiagInfo.push_back(D);
165         return ID;
166       }
167     };
168 
169   } // end diag namespace
170 } // end clang namespace
171 
172 
173 //===----------------------------------------------------------------------===//
174 // Common Diagnostic implementation
175 //===----------------------------------------------------------------------===//
176 
177 static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
178                                const char *Modifier, unsigned ML,
179                                const char *Argument, unsigned ArgLen,
180                                llvm::SmallVectorImpl<char> &Output,
181                                void *Cookie) {
182   const char *Str = "<can't format argument>";
183   Output.append(Str, Str+strlen(Str));
184 }
185 
186 
187 Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
188   AllExtensionsSilenced = 0;
189   IgnoreAllWarnings = false;
190   WarningsAsErrors = false;
191   SuppressSystemWarnings = false;
192   ExtBehavior = Ext_Ignore;
193 
194   ErrorOccurred = false;
195   FatalErrorOccurred = false;
196   NumDiagnostics = 0;
197   NumErrors = 0;
198   CustomDiagInfo = 0;
199   CurDiagID = ~0U;
200   LastDiagLevel = Ignored;
201 
202   ArgToStringFn = DummyArgToStringFn;
203   ArgToStringCookie = 0;
204 
205   // Set all mappings to 'unset'.
206   memset(DiagMappings, 0, sizeof(DiagMappings));
207 }
208 
209 Diagnostic::~Diagnostic() {
210   delete CustomDiagInfo;
211 }
212 
213 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
214 /// and level.  If this is the first request for this diagnosic, it is
215 /// registered and created, otherwise the existing ID is returned.
216 unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) {
217   if (CustomDiagInfo == 0)
218     CustomDiagInfo = new diag::CustomDiagInfo();
219   return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
220 }
221 
222 
223 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
224 /// level of the specified diagnostic ID is a Warning or Extension.
225 /// This only works on builtin diagnostics, not custom ones, and is not legal to
226 /// call on NOTEs.
227 bool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) {
228   return DiagID < diag::DIAG_UPPER_LIMIT &&
229          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
230 }
231 
232 /// \brief Determine whether the given built-in diagnostic ID is a
233 /// Note.
234 bool Diagnostic::isBuiltinNote(unsigned DiagID) {
235   return DiagID < diag::DIAG_UPPER_LIMIT &&
236     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
237 }
238 
239 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
240 /// ID is for an extension of some sort.
241 ///
242 bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) {
243   return DiagID < diag::DIAG_UPPER_LIMIT &&
244          getBuiltinDiagClass(DiagID) == CLASS_EXTENSION;
245 }
246 
247 
248 /// getDescription - Given a diagnostic ID, return a description of the
249 /// issue.
250 const char *Diagnostic::getDescription(unsigned DiagID) const {
251   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
252     return Info->Description;
253   return CustomDiagInfo->getDescription(DiagID);
254 }
255 
256 /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
257 /// object, classify the specified diagnostic ID into a Level, consumable by
258 /// the DiagnosticClient.
259 Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
260   // Handle custom diagnostics, which cannot be mapped.
261   if (DiagID >= diag::DIAG_UPPER_LIMIT)
262     return CustomDiagInfo->getLevel(DiagID);
263 
264   unsigned DiagClass = getBuiltinDiagClass(DiagID);
265   assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
266   return getDiagnosticLevel(DiagID, DiagClass);
267 }
268 
269 /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
270 /// object, classify the specified diagnostic ID into a Level, consumable by
271 /// the DiagnosticClient.
272 Diagnostic::Level
273 Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
274   // Specific non-error diagnostics may be mapped to various levels from ignored
275   // to error.  Errors can only be mapped to fatal.
276   Diagnostic::Level Result = Diagnostic::Fatal;
277 
278   // Get the mapping information, if unset, compute it lazily.
279   unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID);
280   if (MappingInfo == 0) {
281     MappingInfo = GetDefaultDiagMapping(DiagID);
282     setDiagnosticMappingInternal(DiagID, MappingInfo, false);
283   }
284 
285   switch (MappingInfo & 7) {
286   default: assert(0 && "Unknown mapping!");
287   case diag::MAP_IGNORE:
288     // Ignore this, unless this is an extension diagnostic and we're mapping
289     // them onto warnings or errors.
290     if (!isBuiltinExtensionDiag(DiagID) ||  // Not an extension
291         ExtBehavior == Ext_Ignore ||        // Extensions ignored anyway
292         (MappingInfo & 8) != 0)             // User explicitly mapped it.
293       return Diagnostic::Ignored;
294     Result = Diagnostic::Warning;
295     if (ExtBehavior == Ext_Error) Result = Diagnostic::Error;
296     break;
297   case diag::MAP_ERROR:
298     Result = Diagnostic::Error;
299     break;
300   case diag::MAP_FATAL:
301     Result = Diagnostic::Fatal;
302     break;
303   case diag::MAP_WARNING:
304     // If warnings are globally mapped to ignore or error, do it.
305     if (IgnoreAllWarnings)
306       return Diagnostic::Ignored;
307 
308     Result = Diagnostic::Warning;
309 
310     // If this is an extension diagnostic and we're in -pedantic-error mode, and
311     // if the user didn't explicitly map it, upgrade to an error.
312     if (ExtBehavior == Ext_Error &&
313         (MappingInfo & 8) == 0 &&
314         isBuiltinExtensionDiag(DiagID))
315       Result = Diagnostic::Error;
316 
317     if (WarningsAsErrors)
318       Result = Diagnostic::Error;
319     break;
320 
321   case diag::MAP_WARNING_NO_WERROR:
322     // Diagnostics specified with -Wno-error=foo should be set to warnings, but
323     // not be adjusted by -Werror or -pedantic-errors.
324     Result = Diagnostic::Warning;
325 
326     // If warnings are globally mapped to ignore or error, do it.
327     if (IgnoreAllWarnings)
328       return Diagnostic::Ignored;
329 
330     break;
331   }
332 
333   // Okay, we're about to return this as a "diagnostic to emit" one last check:
334   // if this is any sort of extension warning, and if we're in an __extension__
335   // block, silence it.
336   if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
337     return Diagnostic::Ignored;
338 
339   return Result;
340 }
341 
342 struct WarningOption {
343   const char  *Name;
344   const short *Members;
345   const char  *SubGroups;
346 };
347 
348 #define GET_DIAG_ARRAYS
349 #include "clang/Basic/DiagnosticGroups.inc"
350 #undef GET_DIAG_ARRAYS
351 
352 // Second the table of options, sorted by name for fast binary lookup.
353 static const WarningOption OptionTable[] = {
354 #define GET_DIAG_TABLE
355 #include "clang/Basic/DiagnosticGroups.inc"
356 #undef GET_DIAG_TABLE
357 };
358 static const size_t OptionTableSize =
359 sizeof(OptionTable) / sizeof(OptionTable[0]);
360 
361 static bool WarningOptionCompare(const WarningOption &LHS,
362                                  const WarningOption &RHS) {
363   return strcmp(LHS.Name, RHS.Name) < 0;
364 }
365 
366 static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
367                             Diagnostic &Diags) {
368   // Option exists, poke all the members of its diagnostic set.
369   if (const short *Member = Group->Members) {
370     for (; *Member != -1; ++Member)
371       Diags.setDiagnosticMapping(*Member, Mapping);
372   }
373 
374   // Enable/disable all subgroups along with this one.
375   if (const char *SubGroups = Group->SubGroups) {
376     for (; *SubGroups != (char)-1; ++SubGroups)
377       MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping, Diags);
378   }
379 }
380 
381 /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
382 /// "unknown-pragmas" to have the specified mapping.  This returns true and
383 /// ignores the request if "Group" was unknown, false otherwise.
384 bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
385                                            diag::Mapping Map) {
386 
387   WarningOption Key = { Group, 0, 0 };
388   const WarningOption *Found =
389   std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
390                    WarningOptionCompare);
391   if (Found == OptionTable + OptionTableSize ||
392       strcmp(Found->Name, Group) != 0)
393     return true;  // Option not found.
394 
395   MapGroupMembers(Found, Map, *this);
396   return false;
397 }
398 
399 
400 /// ProcessDiag - This is the method used to report a diagnostic that is
401 /// finally fully formed.
402 void Diagnostic::ProcessDiag() {
403   DiagnosticInfo Info(this);
404 
405   // Figure out the diagnostic level of this message.
406   Diagnostic::Level DiagLevel;
407   unsigned DiagID = Info.getID();
408 
409   // ShouldEmitInSystemHeader - True if this diagnostic should be produced even
410   // in a system header.
411   bool ShouldEmitInSystemHeader;
412 
413   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
414     // Handle custom diagnostics, which cannot be mapped.
415     DiagLevel = CustomDiagInfo->getLevel(DiagID);
416 
417     // Custom diagnostics always are emitted in system headers.
418     ShouldEmitInSystemHeader = true;
419   } else {
420     // Get the class of the diagnostic.  If this is a NOTE, map it onto whatever
421     // the diagnostic level was for the previous diagnostic so that it is
422     // filtered the same as the previous diagnostic.
423     unsigned DiagClass = getBuiltinDiagClass(DiagID);
424     if (DiagClass == CLASS_NOTE) {
425       DiagLevel = Diagnostic::Note;
426       ShouldEmitInSystemHeader = false;  // extra consideration is needed
427     } else {
428       // If this is not an error and we are in a system header, we ignore it.
429       // Check the original Diag ID here, because we also want to ignore
430       // extensions and warnings in -Werror and -pedantic-errors modes, which
431       // *map* warnings/extensions to errors.
432       ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
433 
434       DiagLevel = getDiagnosticLevel(DiagID, DiagClass);
435     }
436   }
437 
438   if (DiagLevel != Diagnostic::Note) {
439     // Record that a fatal error occurred only when we see a second
440     // non-note diagnostic. This allows notes to be attached to the
441     // fatal error, but suppresses any diagnostics that follow those
442     // notes.
443     if (LastDiagLevel == Diagnostic::Fatal)
444       FatalErrorOccurred = true;
445 
446     LastDiagLevel = DiagLevel;
447   }
448 
449   // If a fatal error has already been emitted, silence all subsequent
450   // diagnostics.
451   if (FatalErrorOccurred)
452     return;
453 
454   // If the client doesn't care about this message, don't issue it.  If this is
455   // a note and the last real diagnostic was ignored, ignore it too.
456   if (DiagLevel == Diagnostic::Ignored ||
457       (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
458     return;
459 
460   // If this diagnostic is in a system header and is not a clang error, suppress
461   // it.
462   if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
463       Info.getLocation().isValid() &&
464       Info.getLocation().getSpellingLoc().isInSystemHeader() &&
465       (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
466     LastDiagLevel = Diagnostic::Ignored;
467     return;
468   }
469 
470   if (DiagLevel >= Diagnostic::Error) {
471     ErrorOccurred = true;
472     ++NumErrors;
473   }
474 
475   // Finally, report it.
476   Client->HandleDiagnostic(DiagLevel, Info);
477   if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
478 
479   CurDiagID = ~0U;
480 }
481 
482 
483 DiagnosticClient::~DiagnosticClient() {}
484 
485 
486 /// ModifierIs - Return true if the specified modifier matches specified string.
487 template <std::size_t StrLen>
488 static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
489                        const char (&Str)[StrLen]) {
490   return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
491 }
492 
493 /// HandleSelectModifier - Handle the integer 'select' modifier.  This is used
494 /// like this:  %select{foo|bar|baz}2.  This means that the integer argument
495 /// "%2" has a value from 0-2.  If the value is 0, the diagnostic prints 'foo'.
496 /// If the value is 1, it prints 'bar'.  If it has the value 2, it prints 'baz'.
497 /// This is very useful for certain classes of variant diagnostics.
498 static void HandleSelectModifier(unsigned ValNo,
499                                  const char *Argument, unsigned ArgumentLen,
500                                  llvm::SmallVectorImpl<char> &OutStr) {
501   const char *ArgumentEnd = Argument+ArgumentLen;
502 
503   // Skip over 'ValNo' |'s.
504   while (ValNo) {
505     const char *NextVal = std::find(Argument, ArgumentEnd, '|');
506     assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
507            " larger than the number of options in the diagnostic string!");
508     Argument = NextVal+1;  // Skip this string.
509     --ValNo;
510   }
511 
512   // Get the end of the value.  This is either the } or the |.
513   const char *EndPtr = std::find(Argument, ArgumentEnd, '|');
514   // Add the value to the output string.
515   OutStr.append(Argument, EndPtr);
516 }
517 
518 /// HandleIntegerSModifier - Handle the integer 's' modifier.  This adds the
519 /// letter 's' to the string if the value is not 1.  This is used in cases like
520 /// this:  "you idiot, you have %4 parameter%s4!".
521 static void HandleIntegerSModifier(unsigned ValNo,
522                                    llvm::SmallVectorImpl<char> &OutStr) {
523   if (ValNo != 1)
524     OutStr.push_back('s');
525 }
526 
527 
528 /// PluralNumber - Parse an unsigned integer and advance Start.
529 static unsigned PluralNumber(const char *&Start, const char *End) {
530   // Programming 101: Parse a decimal number :-)
531   unsigned Val = 0;
532   while (Start != End && *Start >= '0' && *Start <= '9') {
533     Val *= 10;
534     Val += *Start - '0';
535     ++Start;
536   }
537   return Val;
538 }
539 
540 /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
541 static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
542   if (*Start != '[') {
543     unsigned Ref = PluralNumber(Start, End);
544     return Ref == Val;
545   }
546 
547   ++Start;
548   unsigned Low = PluralNumber(Start, End);
549   assert(*Start == ',' && "Bad plural expression syntax: expected ,");
550   ++Start;
551   unsigned High = PluralNumber(Start, End);
552   assert(*Start == ']' && "Bad plural expression syntax: expected )");
553   ++Start;
554   return Low <= Val && Val <= High;
555 }
556 
557 /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
558 static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
559   // Empty condition?
560   if (*Start == ':')
561     return true;
562 
563   while (1) {
564     char C = *Start;
565     if (C == '%') {
566       // Modulo expression
567       ++Start;
568       unsigned Arg = PluralNumber(Start, End);
569       assert(*Start == '=' && "Bad plural expression syntax: expected =");
570       ++Start;
571       unsigned ValMod = ValNo % Arg;
572       if (TestPluralRange(ValMod, Start, End))
573         return true;
574     } else {
575       assert((C == '[' || (C >= '0' && C <= '9')) &&
576              "Bad plural expression syntax: unexpected character");
577       // Range expression
578       if (TestPluralRange(ValNo, Start, End))
579         return true;
580     }
581 
582     // Scan for next or-expr part.
583     Start = std::find(Start, End, ',');
584     if(Start == End)
585       break;
586     ++Start;
587   }
588   return false;
589 }
590 
591 /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
592 /// for complex plural forms, or in languages where all plurals are complex.
593 /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
594 /// conditions that are tested in order, the form corresponding to the first
595 /// that applies being emitted. The empty condition is always true, making the
596 /// last form a default case.
597 /// Conditions are simple boolean expressions, where n is the number argument.
598 /// Here are the rules.
599 /// condition  := expression | empty
600 /// empty      :=                             -> always true
601 /// expression := numeric [',' expression]    -> logical or
602 /// numeric    := range                       -> true if n in range
603 ///             | '%' number '=' range        -> true if n % number in range
604 /// range      := number
605 ///             | '[' number ',' number ']'   -> ranges are inclusive both ends
606 ///
607 /// Here are some examples from the GNU gettext manual written in this form:
608 /// English:
609 /// {1:form0|:form1}
610 /// Latvian:
611 /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
612 /// Gaeilge:
613 /// {1:form0|2:form1|:form2}
614 /// Romanian:
615 /// {1:form0|0,%100=[1,19]:form1|:form2}
616 /// Lithuanian:
617 /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
618 /// Russian (requires repeated form):
619 /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
620 /// Slovak
621 /// {1:form0|[2,4]:form1|:form2}
622 /// Polish (requires repeated form):
623 /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
624 static void HandlePluralModifier(unsigned ValNo,
625                                  const char *Argument, unsigned ArgumentLen,
626                                  llvm::SmallVectorImpl<char> &OutStr) {
627   const char *ArgumentEnd = Argument + ArgumentLen;
628   while (1) {
629     assert(Argument < ArgumentEnd && "Plural expression didn't match.");
630     const char *ExprEnd = Argument;
631     while (*ExprEnd != ':') {
632       assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
633       ++ExprEnd;
634     }
635     if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
636       Argument = ExprEnd + 1;
637       ExprEnd = std::find(Argument, ArgumentEnd, '|');
638       OutStr.append(Argument, ExprEnd);
639       return;
640     }
641     Argument = std::find(Argument, ArgumentEnd - 1, '|') + 1;
642   }
643 }
644 
645 
646 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
647 /// formal arguments into the %0 slots.  The result is appended onto the Str
648 /// array.
649 void DiagnosticInfo::
650 FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
651   const char *DiagStr = getDiags()->getDescription(getID());
652   const char *DiagEnd = DiagStr+strlen(DiagStr);
653 
654   while (DiagStr != DiagEnd) {
655     if (DiagStr[0] != '%') {
656       // Append non-%0 substrings to Str if we have one.
657       const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
658       OutStr.append(DiagStr, StrEnd);
659       DiagStr = StrEnd;
660       continue;
661     } else if (DiagStr[1] == '%') {
662       OutStr.push_back('%');  // %% -> %.
663       DiagStr += 2;
664       continue;
665     }
666 
667     // Skip the %.
668     ++DiagStr;
669 
670     // This must be a placeholder for a diagnostic argument.  The format for a
671     // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
672     // The digit is a number from 0-9 indicating which argument this comes from.
673     // The modifier is a string of digits from the set [-a-z]+, arguments is a
674     // brace enclosed string.
675     const char *Modifier = 0, *Argument = 0;
676     unsigned ModifierLen = 0, ArgumentLen = 0;
677 
678     // Check to see if we have a modifier.  If so eat it.
679     if (!isdigit(DiagStr[0])) {
680       Modifier = DiagStr;
681       while (DiagStr[0] == '-' ||
682              (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
683         ++DiagStr;
684       ModifierLen = DiagStr-Modifier;
685 
686       // If we have an argument, get it next.
687       if (DiagStr[0] == '{') {
688         ++DiagStr; // Skip {.
689         Argument = DiagStr;
690 
691         for (; DiagStr[0] != '}'; ++DiagStr)
692           assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!");
693         ArgumentLen = DiagStr-Argument;
694         ++DiagStr;  // Skip }.
695       }
696     }
697 
698     assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
699     unsigned ArgNo = *DiagStr++ - '0';
700 
701     switch (getArgKind(ArgNo)) {
702     // ---- STRINGS ----
703     case Diagnostic::ak_std_string: {
704       const std::string &S = getArgStdStr(ArgNo);
705       assert(ModifierLen == 0 && "No modifiers for strings yet");
706       OutStr.append(S.begin(), S.end());
707       break;
708     }
709     case Diagnostic::ak_c_string: {
710       const char *S = getArgCStr(ArgNo);
711       assert(ModifierLen == 0 && "No modifiers for strings yet");
712 
713       // Don't crash if get passed a null pointer by accident.
714       if (!S)
715         S = "(null)";
716 
717       OutStr.append(S, S + strlen(S));
718       break;
719     }
720     // ---- INTEGERS ----
721     case Diagnostic::ak_sint: {
722       int Val = getArgSInt(ArgNo);
723 
724       if (ModifierIs(Modifier, ModifierLen, "select")) {
725         HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
726       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
727         HandleIntegerSModifier(Val, OutStr);
728       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
729         HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
730       } else {
731         assert(ModifierLen == 0 && "Unknown integer modifier");
732         // FIXME: Optimize
733         std::string S = llvm::itostr(Val);
734         OutStr.append(S.begin(), S.end());
735       }
736       break;
737     }
738     case Diagnostic::ak_uint: {
739       unsigned Val = getArgUInt(ArgNo);
740 
741       if (ModifierIs(Modifier, ModifierLen, "select")) {
742         HandleSelectModifier(Val, Argument, ArgumentLen, OutStr);
743       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
744         HandleIntegerSModifier(Val, OutStr);
745       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
746         HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
747       } else {
748         assert(ModifierLen == 0 && "Unknown integer modifier");
749 
750         // FIXME: Optimize
751         std::string S = llvm::utostr_32(Val);
752         OutStr.append(S.begin(), S.end());
753       }
754       break;
755     }
756     // ---- NAMES and TYPES ----
757     case Diagnostic::ak_identifierinfo: {
758       const IdentifierInfo *II = getArgIdentifier(ArgNo);
759       assert(ModifierLen == 0 && "No modifiers for strings yet");
760 
761       // Don't crash if get passed a null pointer by accident.
762       if (!II) {
763         const char *S = "(null)";
764         OutStr.append(S, S + strlen(S));
765         continue;
766       }
767 
768       OutStr.push_back('\'');
769       OutStr.append(II->getName(), II->getName() + II->getLength());
770       OutStr.push_back('\'');
771       break;
772     }
773     case Diagnostic::ak_qualtype:
774     case Diagnostic::ak_declarationname:
775     case Diagnostic::ak_nameddecl:
776       getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo),
777                                      Modifier, ModifierLen,
778                                      Argument, ArgumentLen, OutStr);
779       break;
780     }
781   }
782 }
783 
784 /// IncludeInDiagnosticCounts - This method (whose default implementation
785 ///  returns true) indicates whether the diagnostics handled by this
786 ///  DiagnosticClient should be included in the number of diagnostics
787 ///  reported by Diagnostic.
788 bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }
789