clang API Documentation

Diagnostic.cpp
Go to the documentation of this file.
00001 //===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file implements the Diagnostic-related interfaces.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Basic/Diagnostic.h"
00015 #include "clang/Basic/IdentifierTable.h"
00016 #include "clang/Basic/PartialDiagnostic.h"
00017 #include "llvm/ADT/SmallString.h"
00018 #include "llvm/Support/raw_ostream.h"
00019 #include "llvm/Support/CrashRecoveryContext.h"
00020 
00021 using namespace clang;
00022 
00023 static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
00024                                const char *Modifier, unsigned ML,
00025                                const char *Argument, unsigned ArgLen,
00026                                const DiagnosticsEngine::ArgumentValue *PrevArgs,
00027                                unsigned NumPrevArgs,
00028                                SmallVectorImpl<char> &Output,
00029                                void *Cookie,
00030                                ArrayRef<intptr_t> QualTypeVals) {
00031   const char *Str = "<can't format argument>";
00032   Output.append(Str, Str+strlen(Str));
00033 }
00034 
00035 
00036 DiagnosticsEngine::DiagnosticsEngine(
00037                        const IntrusiveRefCntPtr<DiagnosticIDs> &diags,
00038                        DiagnosticConsumer *client, bool ShouldOwnClient)
00039   : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient),
00040     SourceMgr(0) {
00041   ArgToStringFn = DummyArgToStringFn;
00042   ArgToStringCookie = 0;
00043 
00044   AllExtensionsSilenced = 0;
00045   IgnoreAllWarnings = false;
00046   WarningsAsErrors = false;
00047   EnableAllWarnings = false;
00048   ErrorsAsFatal = false;
00049   SuppressSystemWarnings = false;
00050   SuppressAllDiagnostics = false;
00051   ShowOverloads = Ovl_All;
00052   ExtBehavior = Ext_Ignore;
00053 
00054   ErrorLimit = 0;
00055   TemplateBacktraceLimit = 0;
00056   ConstexprBacktraceLimit = 0;
00057 
00058   Reset();
00059 }
00060 
00061 DiagnosticsEngine::~DiagnosticsEngine() {
00062   if (OwnsDiagClient)
00063     delete Client;
00064 }
00065 
00066 void DiagnosticsEngine::setClient(DiagnosticConsumer *client,
00067                                   bool ShouldOwnClient) {
00068   if (OwnsDiagClient && Client)
00069     delete Client;
00070   
00071   Client = client;
00072   OwnsDiagClient = ShouldOwnClient;
00073 }
00074 
00075 void DiagnosticsEngine::pushMappings(SourceLocation Loc) {
00076   DiagStateOnPushStack.push_back(GetCurDiagState());
00077 }
00078 
00079 bool DiagnosticsEngine::popMappings(SourceLocation Loc) {
00080   if (DiagStateOnPushStack.empty())
00081     return false;
00082 
00083   if (DiagStateOnPushStack.back() != GetCurDiagState()) {
00084     // State changed at some point between push/pop.
00085     PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
00086   }
00087   DiagStateOnPushStack.pop_back();
00088   return true;
00089 }
00090 
00091 void DiagnosticsEngine::Reset() {
00092   ErrorOccurred = false;
00093   FatalErrorOccurred = false;
00094   UnrecoverableErrorOccurred = false;
00095   
00096   NumWarnings = 0;
00097   NumErrors = 0;
00098   NumErrorsSuppressed = 0;
00099   TrapNumErrorsOccurred = 0;
00100   TrapNumUnrecoverableErrorsOccurred = 0;
00101   
00102   CurDiagID = ~0U;
00103   // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes
00104   // using a DiagnosticsEngine associated to a translation unit that follow
00105   // diagnostics from a DiagnosticsEngine associated to anoter t.u. will not be
00106   // displayed.
00107   LastDiagLevel = (DiagnosticIDs::Level)-1;
00108   DelayedDiagID = 0;
00109 
00110   // Clear state related to #pragma diagnostic.
00111   DiagStates.clear();
00112   DiagStatePoints.clear();
00113   DiagStateOnPushStack.clear();
00114 
00115   // Create a DiagState and DiagStatePoint representing diagnostic changes
00116   // through command-line.
00117   DiagStates.push_back(DiagState());
00118   PushDiagStatePoint(&DiagStates.back(), SourceLocation());
00119 }
00120 
00121 void DiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1,
00122                                              StringRef Arg2) {
00123   if (DelayedDiagID)
00124     return;
00125 
00126   DelayedDiagID = DiagID;
00127   DelayedDiagArg1 = Arg1.str();
00128   DelayedDiagArg2 = Arg2.str();
00129 }
00130 
00131 void DiagnosticsEngine::ReportDelayed() {
00132   Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2;
00133   DelayedDiagID = 0;
00134   DelayedDiagArg1.clear();
00135   DelayedDiagArg2.clear();
00136 }
00137 
00138 DiagnosticsEngine::DiagStatePointsTy::iterator
00139 DiagnosticsEngine::GetDiagStatePointForLoc(SourceLocation L) const {
00140   assert(!DiagStatePoints.empty());
00141   assert(DiagStatePoints.front().Loc.isInvalid() &&
00142          "Should have created a DiagStatePoint for command-line");
00143 
00144   FullSourceLoc Loc(L, *SourceMgr);
00145   if (Loc.isInvalid())
00146     return DiagStatePoints.end() - 1;
00147 
00148   DiagStatePointsTy::iterator Pos = DiagStatePoints.end();
00149   FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
00150   if (LastStateChangePos.isValid() &&
00151       Loc.isBeforeInTranslationUnitThan(LastStateChangePos))
00152     Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(),
00153                            DiagStatePoint(0, Loc));
00154   --Pos;
00155   return Pos;
00156 }
00157 
00158 /// \brief This allows the client to specify that certain
00159 /// warnings are ignored.  Notes can never be mapped, errors can only be
00160 /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
00161 ///
00162 /// \param The source location that this change of diagnostic state should
00163 /// take affect. It can be null if we are setting the latest state.
00164 void DiagnosticsEngine::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
00165                                              SourceLocation L) {
00166   assert(Diag < diag::DIAG_UPPER_LIMIT &&
00167          "Can only map builtin diagnostics");
00168   assert((Diags->isBuiltinWarningOrExtension(Diag) ||
00169           (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) &&
00170          "Cannot map errors into warnings!");
00171   assert(!DiagStatePoints.empty());
00172 
00173   FullSourceLoc Loc(L, *SourceMgr);
00174   FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc;
00175   // Don't allow a mapping to a warning override an error/fatal mapping.
00176   if (Map == diag::MAP_WARNING) {
00177     DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag);
00178     if (Info.getMapping() == diag::MAP_ERROR ||
00179         Info.getMapping() == diag::MAP_FATAL)
00180       Map = Info.getMapping();
00181   }
00182   DiagnosticMappingInfo MappingInfo = makeMappingInfo(Map, L);
00183 
00184   // Common case; setting all the diagnostics of a group in one place.
00185   if (Loc.isInvalid() || Loc == LastStateChangePos) {
00186     GetCurDiagState()->setMappingInfo(Diag, MappingInfo);
00187     return;
00188   }
00189 
00190   // Another common case; modifying diagnostic state in a source location
00191   // after the previous one.
00192   if ((Loc.isValid() && LastStateChangePos.isInvalid()) ||
00193       LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) {
00194     // A diagnostic pragma occurred, create a new DiagState initialized with
00195     // the current one and a new DiagStatePoint to record at which location
00196     // the new state became active.
00197     DiagStates.push_back(*GetCurDiagState());
00198     PushDiagStatePoint(&DiagStates.back(), Loc);
00199     GetCurDiagState()->setMappingInfo(Diag, MappingInfo);
00200     return;
00201   }
00202 
00203   // We allow setting the diagnostic state in random source order for
00204   // completeness but it should not be actually happening in normal practice.
00205 
00206   DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc);
00207   assert(Pos != DiagStatePoints.end());
00208 
00209   // Update all diagnostic states that are active after the given location.
00210   for (DiagStatePointsTy::iterator
00211          I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) {
00212     GetCurDiagState()->setMappingInfo(Diag, MappingInfo);
00213   }
00214 
00215   // If the location corresponds to an existing point, just update its state.
00216   if (Pos->Loc == Loc) {
00217     GetCurDiagState()->setMappingInfo(Diag, MappingInfo);
00218     return;
00219   }
00220 
00221   // Create a new state/point and fit it into the vector of DiagStatePoints
00222   // so that the vector is always ordered according to location.
00223   Pos->Loc.isBeforeInTranslationUnitThan(Loc);
00224   DiagStates.push_back(*Pos->State);
00225   DiagState *NewState = &DiagStates.back();
00226   GetCurDiagState()->setMappingInfo(Diag, MappingInfo);
00227   DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState,
00228                                                FullSourceLoc(Loc, *SourceMgr)));
00229 }
00230 
00231 bool DiagnosticsEngine::setDiagnosticGroupMapping(
00232   StringRef Group, diag::Mapping Map, SourceLocation Loc)
00233 {
00234   // Get the diagnostics in this group.
00235   llvm::SmallVector<diag::kind, 8> GroupDiags;
00236   if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
00237     return true;
00238 
00239   // Set the mapping.
00240   for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i)
00241     setDiagnosticMapping(GroupDiags[i], Map, Loc);
00242 
00243   return false;
00244 }
00245 
00246 void DiagnosticsEngine::setDiagnosticWarningAsError(diag::kind Diag,
00247                                                     bool Enabled) {
00248   // If we are enabling this feature, just set the diagnostic mappings to map to
00249   // errors.
00250   if (Enabled) 
00251     setDiagnosticMapping(Diag, diag::MAP_ERROR, SourceLocation());
00252 
00253   // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
00254   // potentially downgrade anything already mapped to be a warning.
00255   DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag);
00256 
00257   if (Info.getMapping() == diag::MAP_ERROR ||
00258       Info.getMapping() == diag::MAP_FATAL)
00259     Info.setMapping(diag::MAP_WARNING);
00260 
00261   Info.setNoWarningAsError(true);
00262 }
00263 
00264 bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
00265                                                          bool Enabled) {
00266   // If we are enabling this feature, just set the diagnostic mappings to map to
00267   // errors.
00268   if (Enabled)
00269     return setDiagnosticGroupMapping(Group, diag::MAP_ERROR);
00270 
00271   // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
00272   // potentially downgrade anything already mapped to be a warning.
00273 
00274   // Get the diagnostics in this group.
00275   llvm::SmallVector<diag::kind, 8> GroupDiags;
00276   if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
00277     return true;
00278 
00279   // Perform the mapping change.
00280   for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
00281     DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(
00282       GroupDiags[i]);
00283 
00284     if (Info.getMapping() == diag::MAP_ERROR ||
00285         Info.getMapping() == diag::MAP_FATAL)
00286       Info.setMapping(diag::MAP_WARNING);
00287 
00288     Info.setNoWarningAsError(true);
00289   }
00290 
00291   return false;
00292 }
00293 
00294 void DiagnosticsEngine::setDiagnosticErrorAsFatal(diag::kind Diag,
00295                                                   bool Enabled) {
00296   // If we are enabling this feature, just set the diagnostic mappings to map to
00297   // errors.
00298   if (Enabled)
00299     setDiagnosticMapping(Diag, diag::MAP_FATAL, SourceLocation());
00300   
00301   // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
00302   // potentially downgrade anything already mapped to be a warning.
00303   DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(Diag);
00304   
00305   if (Info.getMapping() == diag::MAP_FATAL)
00306     Info.setMapping(diag::MAP_ERROR);
00307   
00308   Info.setNoErrorAsFatal(true);
00309 }
00310 
00311 bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
00312                                                        bool Enabled) {
00313   // If we are enabling this feature, just set the diagnostic mappings to map to
00314   // fatal errors.
00315   if (Enabled)
00316     return setDiagnosticGroupMapping(Group, diag::MAP_FATAL);
00317 
00318   // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and
00319   // potentially downgrade anything already mapped to be an error.
00320 
00321   // Get the diagnostics in this group.
00322   llvm::SmallVector<diag::kind, 8> GroupDiags;
00323   if (Diags->getDiagnosticsInGroup(Group, GroupDiags))
00324     return true;
00325 
00326   // Perform the mapping change.
00327   for (unsigned i = 0, e = GroupDiags.size(); i != e; ++i) {
00328     DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(
00329       GroupDiags[i]);
00330 
00331     if (Info.getMapping() == diag::MAP_FATAL)
00332       Info.setMapping(diag::MAP_ERROR);
00333 
00334     Info.setNoErrorAsFatal(true);
00335   }
00336 
00337   return false;
00338 }
00339 
00340 void DiagnosticsEngine::setMappingToAllDiagnostics(diag::Mapping Map,
00341                                                    SourceLocation Loc) {
00342   // Get all the diagnostics.
00343   llvm::SmallVector<diag::kind, 64> AllDiags;
00344   Diags->getAllDiagnostics(AllDiags);
00345 
00346   // Set the mapping.
00347   for (unsigned i = 0, e = AllDiags.size(); i != e; ++i)
00348     if (Diags->isBuiltinWarningOrExtension(AllDiags[i]))
00349       setDiagnosticMapping(AllDiags[i], Map, Loc);
00350 }
00351 
00352 void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
00353   assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
00354 
00355   CurDiagLoc = storedDiag.getLocation();
00356   CurDiagID = storedDiag.getID();
00357   NumDiagArgs = 0;
00358 
00359   NumDiagRanges = storedDiag.range_size();
00360   assert(NumDiagRanges < DiagnosticsEngine::MaxRanges &&
00361          "Too many arguments to diagnostic!");
00362   unsigned i = 0;
00363   for (StoredDiagnostic::range_iterator
00364          RI = storedDiag.range_begin(),
00365          RE = storedDiag.range_end(); RI != RE; ++RI)
00366     DiagRanges[i++] = *RI;
00367 
00368   assert(NumDiagRanges < DiagnosticsEngine::MaxFixItHints &&
00369          "Too many arguments to diagnostic!");
00370   NumDiagFixItHints = 0;
00371   for (StoredDiagnostic::fixit_iterator
00372          FI = storedDiag.fixit_begin(),
00373          FE = storedDiag.fixit_end(); FI != FE; ++FI)
00374     DiagFixItHints[NumDiagFixItHints++] = *FI;
00375 
00376   assert(Client && "DiagnosticConsumer not set!");
00377   Level DiagLevel = storedDiag.getLevel();
00378   Diagnostic Info(this, storedDiag.getMessage());
00379   Client->HandleDiagnostic(DiagLevel, Info);
00380   if (Client->IncludeInDiagnosticCounts()) {
00381     if (DiagLevel == DiagnosticsEngine::Warning)
00382       ++NumWarnings;
00383   }
00384 
00385   CurDiagID = ~0U;
00386 }
00387 
00388 bool DiagnosticsEngine::EmitCurrentDiagnostic() {
00389   // Process the diagnostic, sending the accumulated information to the
00390   // DiagnosticConsumer.
00391   bool Emitted = ProcessDiag();
00392 
00393   // Clear out the current diagnostic object.
00394   unsigned DiagID = CurDiagID;
00395   Clear();
00396 
00397   // If there was a delayed diagnostic, emit it now.
00398   if (DelayedDiagID && DelayedDiagID != DiagID)
00399     ReportDelayed();
00400 
00401   return Emitted;
00402 }
00403 
00404 
00405 DiagnosticConsumer::~DiagnosticConsumer() {}
00406 
00407 void DiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
00408                                         const Diagnostic &Info) {
00409   if (!IncludeInDiagnosticCounts())
00410     return;
00411 
00412   if (DiagLevel == DiagnosticsEngine::Warning)
00413     ++NumWarnings;
00414   else if (DiagLevel >= DiagnosticsEngine::Error)
00415     ++NumErrors;
00416 }
00417 
00418 /// ModifierIs - Return true if the specified modifier matches specified string.
00419 template <std::size_t StrLen>
00420 static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
00421                        const char (&Str)[StrLen]) {
00422   return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
00423 }
00424 
00425 /// ScanForward - Scans forward, looking for the given character, skipping
00426 /// nested clauses and escaped characters.
00427 static const char *ScanFormat(const char *I, const char *E, char Target) {
00428   unsigned Depth = 0;
00429 
00430   for ( ; I != E; ++I) {
00431     if (Depth == 0 && *I == Target) return I;
00432     if (Depth != 0 && *I == '}') Depth--;
00433 
00434     if (*I == '%') {
00435       I++;
00436       if (I == E) break;
00437 
00438       // Escaped characters get implicitly skipped here.
00439 
00440       // Format specifier.
00441       if (!isdigit(*I) && !ispunct(*I)) {
00442         for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ;
00443         if (I == E) break;
00444         if (*I == '{')
00445           Depth++;
00446       }
00447     }
00448   }
00449   return E;
00450 }
00451 
00452 /// HandleSelectModifier - Handle the integer 'select' modifier.  This is used
00453 /// like this:  %select{foo|bar|baz}2.  This means that the integer argument
00454 /// "%2" has a value from 0-2.  If the value is 0, the diagnostic prints 'foo'.
00455 /// If the value is 1, it prints 'bar'.  If it has the value 2, it prints 'baz'.
00456 /// This is very useful for certain classes of variant diagnostics.
00457 static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo,
00458                                  const char *Argument, unsigned ArgumentLen,
00459                                  SmallVectorImpl<char> &OutStr) {
00460   const char *ArgumentEnd = Argument+ArgumentLen;
00461 
00462   // Skip over 'ValNo' |'s.
00463   while (ValNo) {
00464     const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
00465     assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
00466            " larger than the number of options in the diagnostic string!");
00467     Argument = NextVal+1;  // Skip this string.
00468     --ValNo;
00469   }
00470 
00471   // Get the end of the value.  This is either the } or the |.
00472   const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
00473 
00474   // Recursively format the result of the select clause into the output string.
00475   DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
00476 }
00477 
00478 /// HandleIntegerSModifier - Handle the integer 's' modifier.  This adds the
00479 /// letter 's' to the string if the value is not 1.  This is used in cases like
00480 /// this:  "you idiot, you have %4 parameter%s4!".
00481 static void HandleIntegerSModifier(unsigned ValNo,
00482                                    SmallVectorImpl<char> &OutStr) {
00483   if (ValNo != 1)
00484     OutStr.push_back('s');
00485 }
00486 
00487 /// HandleOrdinalModifier - Handle the integer 'ord' modifier.  This
00488 /// prints the ordinal form of the given integer, with 1 corresponding
00489 /// to the first ordinal.  Currently this is hard-coded to use the
00490 /// English form.
00491 static void HandleOrdinalModifier(unsigned ValNo,
00492                                   SmallVectorImpl<char> &OutStr) {
00493   assert(ValNo != 0 && "ValNo must be strictly positive!");
00494 
00495   llvm::raw_svector_ostream Out(OutStr);
00496 
00497   // We could use text forms for the first N ordinals, but the numeric
00498   // forms are actually nicer in diagnostics because they stand out.
00499   Out << ValNo;
00500 
00501   // It is critically important that we do this perfectly for
00502   // user-written sequences with over 100 elements.
00503   switch (ValNo % 100) {
00504   case 11:
00505   case 12:
00506   case 13:
00507     Out << "th"; return;
00508   default:
00509     switch (ValNo % 10) {
00510     case 1: Out << "st"; return;
00511     case 2: Out << "nd"; return;
00512     case 3: Out << "rd"; return;
00513     default: Out << "th"; return;
00514     }
00515   }
00516 }
00517 
00518 
00519 /// PluralNumber - Parse an unsigned integer and advance Start.
00520 static unsigned PluralNumber(const char *&Start, const char *End) {
00521   // Programming 101: Parse a decimal number :-)
00522   unsigned Val = 0;
00523   while (Start != End && *Start >= '0' && *Start <= '9') {
00524     Val *= 10;
00525     Val += *Start - '0';
00526     ++Start;
00527   }
00528   return Val;
00529 }
00530 
00531 /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
00532 static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
00533   if (*Start != '[') {
00534     unsigned Ref = PluralNumber(Start, End);
00535     return Ref == Val;
00536   }
00537 
00538   ++Start;
00539   unsigned Low = PluralNumber(Start, End);
00540   assert(*Start == ',' && "Bad plural expression syntax: expected ,");
00541   ++Start;
00542   unsigned High = PluralNumber(Start, End);
00543   assert(*Start == ']' && "Bad plural expression syntax: expected )");
00544   ++Start;
00545   return Low <= Val && Val <= High;
00546 }
00547 
00548 /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
00549 static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
00550   // Empty condition?
00551   if (*Start == ':')
00552     return true;
00553 
00554   while (1) {
00555     char C = *Start;
00556     if (C == '%') {
00557       // Modulo expression
00558       ++Start;
00559       unsigned Arg = PluralNumber(Start, End);
00560       assert(*Start == '=' && "Bad plural expression syntax: expected =");
00561       ++Start;
00562       unsigned ValMod = ValNo % Arg;
00563       if (TestPluralRange(ValMod, Start, End))
00564         return true;
00565     } else {
00566       assert((C == '[' || (C >= '0' && C <= '9')) &&
00567              "Bad plural expression syntax: unexpected character");
00568       // Range expression
00569       if (TestPluralRange(ValNo, Start, End))
00570         return true;
00571     }
00572 
00573     // Scan for next or-expr part.
00574     Start = std::find(Start, End, ',');
00575     if (Start == End)
00576       break;
00577     ++Start;
00578   }
00579   return false;
00580 }
00581 
00582 /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
00583 /// for complex plural forms, or in languages where all plurals are complex.
00584 /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
00585 /// conditions that are tested in order, the form corresponding to the first
00586 /// that applies being emitted. The empty condition is always true, making the
00587 /// last form a default case.
00588 /// Conditions are simple boolean expressions, where n is the number argument.
00589 /// Here are the rules.
00590 /// condition  := expression | empty
00591 /// empty      :=                             -> always true
00592 /// expression := numeric [',' expression]    -> logical or
00593 /// numeric    := range                       -> true if n in range
00594 ///             | '%' number '=' range        -> true if n % number in range
00595 /// range      := number
00596 ///             | '[' number ',' number ']'   -> ranges are inclusive both ends
00597 ///
00598 /// Here are some examples from the GNU gettext manual written in this form:
00599 /// English:
00600 /// {1:form0|:form1}
00601 /// Latvian:
00602 /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
00603 /// Gaeilge:
00604 /// {1:form0|2:form1|:form2}
00605 /// Romanian:
00606 /// {1:form0|0,%100=[1,19]:form1|:form2}
00607 /// Lithuanian:
00608 /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
00609 /// Russian (requires repeated form):
00610 /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
00611 /// Slovak
00612 /// {1:form0|[2,4]:form1|:form2}
00613 /// Polish (requires repeated form):
00614 /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
00615 static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo,
00616                                  const char *Argument, unsigned ArgumentLen,
00617                                  SmallVectorImpl<char> &OutStr) {
00618   const char *ArgumentEnd = Argument + ArgumentLen;
00619   while (1) {
00620     assert(Argument < ArgumentEnd && "Plural expression didn't match.");
00621     const char *ExprEnd = Argument;
00622     while (*ExprEnd != ':') {
00623       assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
00624       ++ExprEnd;
00625     }
00626     if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
00627       Argument = ExprEnd + 1;
00628       ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
00629 
00630       // Recursively format the result of the plural clause into the
00631       // output string.
00632       DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr);
00633       return;
00634     }
00635     Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
00636   }
00637 }
00638 
00639 
00640 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
00641 /// formal arguments into the %0 slots.  The result is appended onto the Str
00642 /// array.
00643 void Diagnostic::
00644 FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
00645   if (!StoredDiagMessage.empty()) {
00646     OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
00647     return;
00648   }
00649 
00650   StringRef Diag = 
00651     getDiags()->getDiagnosticIDs()->getDescription(getID());
00652 
00653   FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
00654 }
00655 
00656 void Diagnostic::
00657 FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
00658                  SmallVectorImpl<char> &OutStr) const {
00659 
00660   /// FormattedArgs - Keep track of all of the arguments formatted by
00661   /// ConvertArgToString and pass them into subsequent calls to
00662   /// ConvertArgToString, allowing the implementation to avoid redundancies in
00663   /// obvious cases.
00664   SmallVector<DiagnosticsEngine::ArgumentValue, 8> FormattedArgs;
00665 
00666   /// QualTypeVals - Pass a vector of arrays so that QualType names can be
00667   /// compared to see if more information is needed to be printed.
00668   SmallVector<intptr_t, 2> QualTypeVals;
00669   for (unsigned i = 0, e = getNumArgs(); i < e; ++i)
00670     if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)
00671       QualTypeVals.push_back(getRawArg(i));
00672 
00673   while (DiagStr != DiagEnd) {
00674     if (DiagStr[0] != '%') {
00675       // Append non-%0 substrings to Str if we have one.
00676       const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
00677       OutStr.append(DiagStr, StrEnd);
00678       DiagStr = StrEnd;
00679       continue;
00680     } else if (ispunct(DiagStr[1])) {
00681       OutStr.push_back(DiagStr[1]);  // %% -> %.
00682       DiagStr += 2;
00683       continue;
00684     }
00685 
00686     // Skip the %.
00687     ++DiagStr;
00688 
00689     // This must be a placeholder for a diagnostic argument.  The format for a
00690     // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
00691     // The digit is a number from 0-9 indicating which argument this comes from.
00692     // The modifier is a string of digits from the set [-a-z]+, arguments is a
00693     // brace enclosed string.
00694     const char *Modifier = 0, *Argument = 0;
00695     unsigned ModifierLen = 0, ArgumentLen = 0;
00696 
00697     // Check to see if we have a modifier.  If so eat it.
00698     if (!isdigit(DiagStr[0])) {
00699       Modifier = DiagStr;
00700       while (DiagStr[0] == '-' ||
00701              (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
00702         ++DiagStr;
00703       ModifierLen = DiagStr-Modifier;
00704 
00705       // If we have an argument, get it next.
00706       if (DiagStr[0] == '{') {
00707         ++DiagStr; // Skip {.
00708         Argument = DiagStr;
00709 
00710         DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
00711         assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
00712         ArgumentLen = DiagStr-Argument;
00713         ++DiagStr;  // Skip }.
00714       }
00715     }
00716 
00717     assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
00718     unsigned ArgNo = *DiagStr++ - '0';
00719 
00720     DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);
00721     
00722     switch (Kind) {
00723     // ---- STRINGS ----
00724     case DiagnosticsEngine::ak_std_string: {
00725       const std::string &S = getArgStdStr(ArgNo);
00726       assert(ModifierLen == 0 && "No modifiers for strings yet");
00727       OutStr.append(S.begin(), S.end());
00728       break;
00729     }
00730     case DiagnosticsEngine::ak_c_string: {
00731       const char *S = getArgCStr(ArgNo);
00732       assert(ModifierLen == 0 && "No modifiers for strings yet");
00733 
00734       // Don't crash if get passed a null pointer by accident.
00735       if (!S)
00736         S = "(null)";
00737 
00738       OutStr.append(S, S + strlen(S));
00739       break;
00740     }
00741     // ---- INTEGERS ----
00742     case DiagnosticsEngine::ak_sint: {
00743       int Val = getArgSInt(ArgNo);
00744 
00745       if (ModifierIs(Modifier, ModifierLen, "select")) {
00746         HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen,
00747                              OutStr);
00748       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
00749         HandleIntegerSModifier(Val, OutStr);
00750       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
00751         HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
00752                              OutStr);
00753       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
00754         HandleOrdinalModifier((unsigned)Val, OutStr);
00755       } else {
00756         assert(ModifierLen == 0 && "Unknown integer modifier");
00757         llvm::raw_svector_ostream(OutStr) << Val;
00758       }
00759       break;
00760     }
00761     case DiagnosticsEngine::ak_uint: {
00762       unsigned Val = getArgUInt(ArgNo);
00763 
00764       if (ModifierIs(Modifier, ModifierLen, "select")) {
00765         HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
00766       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
00767         HandleIntegerSModifier(Val, OutStr);
00768       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
00769         HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen,
00770                              OutStr);
00771       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
00772         HandleOrdinalModifier(Val, OutStr);
00773       } else {
00774         assert(ModifierLen == 0 && "Unknown integer modifier");
00775         llvm::raw_svector_ostream(OutStr) << Val;
00776       }
00777       break;
00778     }
00779     // ---- NAMES and TYPES ----
00780     case DiagnosticsEngine::ak_identifierinfo: {
00781       const IdentifierInfo *II = getArgIdentifier(ArgNo);
00782       assert(ModifierLen == 0 && "No modifiers for strings yet");
00783 
00784       // Don't crash if get passed a null pointer by accident.
00785       if (!II) {
00786         const char *S = "(null)";
00787         OutStr.append(S, S + strlen(S));
00788         continue;
00789       }
00790 
00791       llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
00792       break;
00793     }
00794     case DiagnosticsEngine::ak_qualtype:
00795     case DiagnosticsEngine::ak_declarationname:
00796     case DiagnosticsEngine::ak_nameddecl:
00797     case DiagnosticsEngine::ak_nestednamespec:
00798     case DiagnosticsEngine::ak_declcontext:
00799       getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
00800                                      Modifier, ModifierLen,
00801                                      Argument, ArgumentLen,
00802                                      FormattedArgs.data(), FormattedArgs.size(),
00803                                      OutStr, QualTypeVals);
00804       break;
00805     }
00806     
00807     // Remember this argument info for subsequent formatting operations.  Turn
00808     // std::strings into a null terminated string to make it be the same case as
00809     // all the other ones.
00810     if (Kind != DiagnosticsEngine::ak_std_string)
00811       FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
00812     else
00813       FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,
00814                                         (intptr_t)getArgStdStr(ArgNo).c_str()));
00815     
00816   }
00817 }
00818 
00819 StoredDiagnostic::StoredDiagnostic() { }
00820 
00821 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
00822                                    StringRef Message)
00823   : ID(ID), Level(Level), Loc(), Message(Message) { }
00824 
00825 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, 
00826                                    const Diagnostic &Info)
00827   : ID(Info.getID()), Level(Level) 
00828 {
00829   assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
00830        "Valid source location without setting a source manager for diagnostic");
00831   if (Info.getLocation().isValid())
00832     Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
00833   SmallString<64> Message;
00834   Info.FormatDiagnostic(Message);
00835   this->Message.assign(Message.begin(), Message.end());
00836 
00837   Ranges.reserve(Info.getNumRanges());
00838   for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I)
00839     Ranges.push_back(Info.getRange(I));
00840 
00841   FixIts.reserve(Info.getNumFixItHints());
00842   for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I)
00843     FixIts.push_back(Info.getFixItHint(I));
00844 }
00845 
00846 StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
00847                                    StringRef Message, FullSourceLoc Loc,
00848                                    ArrayRef<CharSourceRange> Ranges,
00849                                    ArrayRef<FixItHint> Fixits)
00850   : ID(ID), Level(Level), Loc(Loc), Message(Message) 
00851 {
00852   this->Ranges.assign(Ranges.begin(), Ranges.end());
00853   this->FixIts.assign(FixIts.begin(), FixIts.end());
00854 }
00855 
00856 StoredDiagnostic::~StoredDiagnostic() { }
00857 
00858 /// IncludeInDiagnosticCounts - This method (whose default implementation
00859 ///  returns true) indicates whether the diagnostics handled by this
00860 ///  DiagnosticConsumer should be included in the number of diagnostics
00861 ///  reported by DiagnosticsEngine.
00862 bool DiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; }
00863 
00864 void IgnoringDiagConsumer::anchor() { }
00865 
00866 PartialDiagnostic::StorageAllocator::StorageAllocator() {
00867   for (unsigned I = 0; I != NumCached; ++I)
00868     FreeList[I] = Cached + I;
00869   NumFreeListEntries = NumCached;
00870 }
00871 
00872 PartialDiagnostic::StorageAllocator::~StorageAllocator() {
00873   // Don't assert if we are in a CrashRecovery context, as this invariant may
00874   // be invalidated during a crash.
00875   assert((NumFreeListEntries == NumCached || 
00876           llvm::CrashRecoveryContext::isRecoveringFromCrash()) && 
00877          "A partial is on the lamb");
00878 }