Diagnostic.cpp revision a7e1898e6b84ed7911d1f25c975b27b78a4950cb
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>
31using namespace clang;
32
33//===----------------------------------------------------------------------===//
34// Builtin Diagnostic information
35//===----------------------------------------------------------------------===//
36
37// Diagnostic classes.
38enum {
39  CLASS_NOTE       = 0x01,
40  CLASS_WARNING    = 0x02,
41  CLASS_EXTENSION  = 0x03,
42  CLASS_ERROR      = 0x04
43};
44
45struct 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
60static 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.
77static 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
103static 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.
112const 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///
120static 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
130namespace 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
177static 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
187Diagnostic::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
209Diagnostic::~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.
216unsigned 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.
227bool 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.
234bool 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///
242bool 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.
250const 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.
259Diagnostic::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.
272Diagnostic::Level
273Diagnostic::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
342struct 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.
353static const WarningOption OptionTable[] = {
354#define GET_DIAG_TABLE
355#include "clang/Basic/DiagnosticGroups.inc"
356#undef GET_DIAG_TABLE
357};
358static const size_t OptionTableSize =
359sizeof(OptionTable) / sizeof(OptionTable[0]);
360
361static bool WarningOptionCompare(const WarningOption &LHS,
362                                 const WarningOption &RHS) {
363  return strcmp(LHS.Name, RHS.Name) < 0;
364}
365
366static 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.
384bool 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.
402void 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
483DiagnosticClient::~DiagnosticClient() {}
484
485
486/// ModifierIs - Return true if the specified modifier matches specified string.
487template <std::size_t StrLen>
488static 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.
498static 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!".
521static 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.
529static 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.
541static 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.
558static 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}
624static 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.
649void DiagnosticInfo::
650FormatDiagnostic(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.
788bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }
789