Diagnostic.cpp revision cd1eecfe4f43a542c8f9a6e7d12fa69b28c23a67
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implements the Diagnostic-related interfaces. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "clang/Basic/Diagnostic.h" 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "clang/Basic/IdentifierTable.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Basic/PartialDiagnostic.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallVector.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/raw_ostream.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "llvm/Support/CrashRecoveryContext.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *Modifier, unsigned ML, 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *Argument, unsigned ArgLen, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Diagnostic::ArgumentValue *PrevArgs, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned NumPrevArgs, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::SmallVectorImpl<char> &Output, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *Cookie) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *Str = "<can't format argument>"; 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Output.append(Str, Str+strlen(Str)); 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochDiagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagnosticClient *client, bool ShouldOwnClient) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceMgr(0) { 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ArgToStringFn = DummyArgToStringFn; 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ArgToStringCookie = 0; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllExtensionsSilenced = 0; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreAllWarnings = false; 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WarningsAsErrors = false; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorsAsFatal = false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SuppressSystemWarnings = false; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SuppressAllDiagnostics = false; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowOverloads = Ovl_All; 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExtBehavior = Ext_Ignore; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ErrorLimit = 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TemplateBacktraceLimit = 0; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a DiagState and DiagStatePoint representing diagnostic changes 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // through command-line. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStates.push_back(DiagState()); 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PushDiagStatePoint(&DiagStates.back(), SourceLocation()); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Reset(); 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Diagnostic::~Diagnostic() { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OwnsDiagClient) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete Client; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Diagnostic::setClient(DiagnosticClient *client, bool ShouldOwnClient) { 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (OwnsDiagClient && Client) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete Client; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Client = client; 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) OwnsDiagClient = ShouldOwnClient; 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Diagnostic::pushMappings(SourceLocation Loc) { 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DiagStateOnPushStack.push_back(GetCurDiagState()); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool Diagnostic::popMappings(SourceLocation Loc) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DiagStateOnPushStack.empty()) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (DiagStateOnPushStack.back() != GetCurDiagState()) { 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // State changed at some point between push/pop. 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PushDiagStatePoint(DiagStateOnPushStack.back(), Loc); 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DiagStateOnPushStack.pop_back(); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Diagnostic::Reset() { 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ErrorOccurred = false; 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FatalErrorOccurred = false; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NumWarnings = 0; 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NumErrors = 0; 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NumErrorsSuppressed = 0; 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CurDiagID = ~0U; 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // using a Diagnostic associated to a translation unit that follow 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // diagnostics from a Diagnostic associated to anoter t.u. will not be 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // displayed. 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LastDiagLevel = (DiagnosticIDs::Level)-1; 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DelayedDiagID = 0; 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) llvm::StringRef Arg2) { 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (DelayedDiagID) 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DelayedDiagID = DiagID; 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DelayedDiagArg1 = Arg1.str(); 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DelayedDiagArg2 = Arg2.str(); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Diagnostic::ReportDelayed() { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DelayedDiagID = 0; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DelayedDiagArg1.clear(); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DelayedDiagArg2.clear(); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Diagnostic::DiagStatePointsTy::iterator 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Diagnostic::GetDiagStatePointForLoc(SourceLocation L) const { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(!DiagStatePoints.empty()); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(DiagStatePoints.front().Loc.isInvalid() && 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Should have created a DiagStatePoint for command-line"); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FullSourceLoc Loc(L, *SourceMgr); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (Loc.isInvalid()) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return DiagStatePoints.end() - 1; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DiagStatePointsTy::iterator Pos = DiagStatePoints.end(); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (LastStateChangePos.isValid() && 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DiagStatePoint(0, Loc)); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --Pos; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Pos; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief This allows the client to specify that certain 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// warnings are ignored. Notes can never be mapped, errors can only be 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \param The source location that this change of diagnostic state should 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// take affect. It can be null if we are setting the latest state. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Diagnostic::setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SourceLocation L) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(Diag < diag::DIAG_UPPER_LIMIT && 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Can only map builtin diagnostics"); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert((Diags->isBuiltinWarningOrExtension(Diag) || 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Cannot map errors into warnings!"); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(!DiagStatePoints.empty()); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool isPragma = L.isValid(); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FullSourceLoc Loc(L, *SourceMgr); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Common case; setting all the diagnostics of a group in one place. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (Loc.isInvalid() || Loc == LastStateChangePos) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Another common case; modifying diagnostic state in a source location 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // after the previous one. 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((Loc.isValid() && LastStateChangePos.isInvalid()) || 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LastStateChangePos.isBeforeInTranslationUnitThan(Loc)) { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A diagnostic pragma occured, create a new DiagState initialized with 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the current one and a new DiagStatePoint to record at which location 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the new state became active. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStates.push_back(*GetCurDiagState()); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PushDiagStatePoint(&DiagStates.back(), Loc); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setDiagnosticMappingInternal(Diag, Map, GetCurDiagState(), true, isPragma); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We allow setting the diagnostic state in random source order for 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // completeness but it should not be actually happening in normal practice. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStatePointsTy::iterator Pos = GetDiagStatePointForLoc(Loc); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Pos != DiagStatePoints.end()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update all diagnostic states that are active after the given location. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (DiagStatePointsTy::iterator 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = Pos+1, E = DiagStatePoints.end(); I != E; ++I) { 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) setDiagnosticMappingInternal(Diag, Map, I->State, true, isPragma); 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the location corresponds to an existing point, just update its state. 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (Pos->Loc == Loc) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setDiagnosticMappingInternal(Diag, Map, Pos->State, true, isPragma); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new state/point and fit it into the vector of DiagStatePoints 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so that the vector is always ordered according to location. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pos->Loc.isBeforeInTranslationUnitThan(Loc); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStates.push_back(*Pos->State); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagState *NewState = &DiagStates.back(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setDiagnosticMappingInternal(Diag, Map, NewState, true, isPragma); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStatePoints.insert(Pos+1, DiagStatePoint(NewState, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FullSourceLoc(Loc, *SourceMgr))); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DiagnosticBuilder::FlushCounts() { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagObj->NumDiagArgs = NumArgs; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagObj->NumDiagRanges = NumRanges; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagObj->NumFixItHints = NumFixItHints; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DiagnosticBuilder::Emit() { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If DiagObj is null, then its soul was stolen by the copy ctor 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // or the user called Emit(). 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DiagObj == 0) return false; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When emitting diagnostics, we set the final argument count into 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Diagnostic object. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FlushCounts(); 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Process the diagnostic, sending the accumulated information to the 22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // DiagnosticClient. 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool Emitted = DiagObj->ProcessDiag(); 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Clear out the current diagnostic object. 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned DiagID = DiagObj->CurDiagID; 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DiagObj->Clear(); 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If there was a delayed diagnostic, emit it now. 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (DiagObj->DelayedDiagID && DiagObj->DelayedDiagID != DiagID) 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DiagObj->ReportDelayed(); 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This diagnostic is dead. 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DiagObj = 0; 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Emitted; 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DiagnosticClient::~DiagnosticClient() {} 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel, 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DiagnosticInfo &Info) { 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!IncludeInDiagnosticCounts()) 24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (DiagLevel == Diagnostic::Warning) 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++NumWarnings; 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) else if (DiagLevel >= Diagnostic::Error) 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++NumErrors; 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/// ModifierIs - Return true if the specified modifier matches specified string. 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)template <std::size_t StrLen> 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ModifierIs(const char *Modifier, unsigned ModifierLen, 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const char (&Str)[StrLen]) { 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/// ScanForward - Scans forward, looking for the given character, skipping 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/// nested clauses and escaped characters. 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char *ScanFormat(const char *I, const char *E, char Target) { 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned Depth = 0; 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for ( ; I != E; ++I) { 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (Depth == 0 && *I == Target) return I; 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (Depth != 0 && *I == '}') Depth--; 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (*I == '%') { 27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) I++; 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (I == E) break; 27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Escaped characters get implicitly skipped here. 27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Format specifier. 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!isdigit(*I) && !ispunct(*I)) { 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ; 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (I == E) break; 28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (*I == '{') 28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Depth++; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return E; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// HandleSelectModifier - Handle the integer 'select' modifier. This is used 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// like this: %select{foo|bar|baz}2. This means that the integer argument 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'. 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'. 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// This is very useful for certain classes of variant diagnostics. 296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo, 297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char *Argument, unsigned ArgumentLen, 298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) llvm::SmallVectorImpl<char> &OutStr) { 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char *ArgumentEnd = Argument+ArgumentLen; 300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Skip over 'ValNo' |'s. 302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) while (ValNo) { 303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|'); 304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(NextVal != ArgumentEnd && "Value for integer select modifier was" 305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) " larger than the number of options in the diagnostic string!"); 306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Argument = NextVal+1; // Skip this string. 307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) --ValNo; 308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Get the end of the value. This is either the } or the |. 311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|'); 312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Recursively format the result of the select clause into the output string. 314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DInfo.FormatDiagnostic(Argument, EndPtr, OutStr); 315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the 318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// letter 's' to the string if the value is not 1. This is used in cases like 319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// this: "you idiot, you have %4 parameter%s4!". 320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static void HandleIntegerSModifier(unsigned ValNo, 321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) llvm::SmallVectorImpl<char> &OutStr) { 322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (ValNo != 1) 323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OutStr.push_back('s'); 324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This 327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// prints the ordinal form of the given integer, with 1 corresponding 328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// to the first ordinal. Currently this is hard-coded to use the 329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// English form. 330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static void HandleOrdinalModifier(unsigned ValNo, 331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) llvm::SmallVectorImpl<char> &OutStr) { 332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(ValNo != 0 && "ValNo must be strictly positive!"); 333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) llvm::raw_svector_ostream Out(OutStr); 335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // We could use text forms for the first N ordinals, but the numeric 337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // forms are actually nicer in diagnostics because they stand out. 338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Out << ValNo; 339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // It is critically important that we do this perfectly for 341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // user-written sequences with over 100 elements. 342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (ValNo % 100) { 343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 11: 344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 12: 345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 13: 346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Out << "th"; return; 347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) default: 348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (ValNo % 10) { 349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 1: Out << "st"; return; 350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 2: Out << "nd"; return; 351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case 3: Out << "rd"; return; 352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) default: Out << "th"; return; 353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// PluralNumber - Parse an unsigned integer and advance Start. 359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static unsigned PluralNumber(const char *&Start, const char *End) { 360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Programming 101: Parse a decimal number :-) 361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned Val = 0; 362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) while (Start != End && *Start >= '0' && *Start <= '9') { 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Val *= 10; 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Val += *Start - '0'; 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++Start; 366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return Val; 368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// TestPluralRange - Test if Val is in the parsed range. Modifies Start. 371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) { 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (*Start != '[') { 373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned Ref = PluralNumber(Start, End); 374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return Ref == Val; 375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ++Start; 378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned Low = PluralNumber(Start, End); 379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(*Start == ',' && "Bad plural expression syntax: expected ,"); 380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ++Start; 381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned High = PluralNumber(Start, End); 382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(*Start == ']' && "Bad plural expression syntax: expected )"); 383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ++Start; 38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return Low <= Val && Val <= High; 385a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier. 388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { 389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Empty condition? 390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (*Start == ':') 391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) while (1) { 394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) char C = *Start; 395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (C == '%') { 396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Modulo expression 397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ++Start; 398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned Arg = PluralNumber(Start, End); 399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(*Start == '=' && "Bad plural expression syntax: expected ="); 400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ++Start; 401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) unsigned ValMod = ValNo % Arg; 402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (TestPluralRange(ValMod, Start, End)) 403a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 404a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 405a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert((C == '[' || (C >= '0' && C <= '9')) && 406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "Bad plural expression syntax: unexpected character"); 407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Range expression 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (TestPluralRange(ValNo, Start, End)) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Scan for next or-expr part. 4130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Start = std::find(Start, End, ','); 4140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (Start == End) 4150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++Start; 4170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// for complex plural forms, or in languages where all plurals are complex. 4230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// conditions that are tested in order, the form corresponding to the first 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// that applies being emitted. The empty condition is always true, making the 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// last form a default case. 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Conditions are simple boolean expressions, where n is the number argument. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Here are the rules. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// condition := expression | empty 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// empty := -> always true 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// expression := numeric [',' expression] -> logical or 432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// numeric := range -> true if n in range 433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// | '%' number '=' range -> true if n % number in range 434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// range := number 435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// | '[' number ',' number ']' -> ranges are inclusive both ends 436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// 437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Here are some examples from the GNU gettext manual written in this form: 438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// English: 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {1:form0|:form1} 440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Latvian: 441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0} 442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Gaeilge: 443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {1:form0|2:form1|:form2} 444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Romanian: 445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {1:form0|0,%100=[1,19]:form1|:form2} 446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Lithuanian: 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1} 448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Russian (requires repeated form): 449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2} 450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// Slovak 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/// {1:form0|[2,4]:form1|:form2} 4520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// Polish (requires repeated form): 4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2} 4540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)static void HandlePluralModifier(const DiagnosticInfo &DInfo, unsigned ValNo, 4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const char *Argument, unsigned ArgumentLen, 4560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) llvm::SmallVectorImpl<char> &OutStr) { 4570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const char *ArgumentEnd = Argument + ArgumentLen; 4580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) while (1) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(Argument < ArgumentEnd && "Plural expression didn't match."); 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *ExprEnd = Argument; 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (*ExprEnd != ':') { 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert(ExprEnd != ArgumentEnd && "Plural missing expression end"); 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++ExprEnd; 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (EvalPluralExpr(ValNo, Argument, ExprEnd)) { 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Argument = ExprEnd + 1; 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEnd = ScanFormat(Argument, ArgumentEnd, '|'); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Recursively format the result of the plural clause into the 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // output string. 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// FormatDiagnostic - Format this diagnostic into a string, substituting the 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// formal arguments into the %0 slots. The result is appended onto the Str 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// array. 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DiagnosticInfo:: 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *DiagStr = getDiags()->getDiagnosticIDs()->getDescription(getID()); 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *DiagEnd = DiagStr+strlen(DiagStr); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FormatDiagnostic(DiagStr, DiagEnd, OutStr); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DiagnosticInfo:: 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FormatDiagnostic(const char *DiagStr, const char *DiagEnd, 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::SmallVectorImpl<char> &OutStr) const { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// FormattedArgs - Keep track of all of the arguments formatted by 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// ConvertArgToString and pass them into subsequent calls to 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// ConvertArgToString, allowing the implementation to avoid redundancies in 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// obvious cases. 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (DiagStr != DiagEnd) { 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DiagStr[0] != '%') { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append non-%0 substrings to Str if we have one. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *StrEnd = std::find(DiagStr, DiagEnd, '%'); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStr.append(DiagStr, StrEnd); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStr = StrEnd; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ispunct(DiagStr[1])) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStr.push_back(DiagStr[1]); // %% -> %. 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DiagStr += 2; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip the %. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++DiagStr; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This must be a placeholder for a diagnostic argument. The format for a 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0". 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The digit is a number from 0-9 indicating which argument this comes from. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The modifier is a string of digits from the set [-a-z]+, arguments is a 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // brace enclosed string. 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *Modifier = 0, *Argument = 0; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned ModifierLen = 0, ArgumentLen = 0; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Check to see if we have a modifier. If so eat it. 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isdigit(DiagStr[0])) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Modifier = DiagStr; 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (DiagStr[0] == '-' || 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (DiagStr[0] >= 'a' && DiagStr[0] <= 'z')) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++DiagStr; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModifierLen = DiagStr-Modifier; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have an argument, get it next. 53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (DiagStr[0] == '{') { 53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++DiagStr; // Skip {. 53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Argument = DiagStr; 53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DiagStr = ScanFormat(DiagStr, DiagEnd, '}'); 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!"); 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ArgumentLen = DiagStr-Argument; 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++DiagStr; // Skip }. 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned ArgNo = *DiagStr++ - '0'; 546effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 547effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Diagnostic::ArgumentKind Kind = getArgKind(ArgNo); 548effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 549effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch switch (Kind) { 550effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // ---- STRINGS ---- 551effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case Diagnostic::ak_std_string: { 552effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::string &S = getArgStdStr(ArgNo); 553effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch assert(ModifierLen == 0 && "No modifiers for strings yet"); 554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OutStr.append(S.begin(), S.end()); 555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 556effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 557effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case Diagnostic::ak_c_string: { 558a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char *S = getArgCStr(ArgNo); 559a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) assert(ModifierLen == 0 && "No modifiers for strings yet"); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't crash if get passed a null pointer by accident. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!S) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) S = "(null)"; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStr.append(S, S + strlen(S)); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ---- INTEGERS ---- 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Diagnostic::ak_sint: { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Val = getArgSInt(ArgNo); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ModifierIs(Modifier, ModifierLen, "select")) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStr); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ModifierIs(Modifier, ModifierLen, "s")) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleIntegerSModifier(Val, OutStr); 577a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStr); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleOrdinalModifier((unsigned)Val, OutStr); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(ModifierLen == 0 && "Unknown integer modifier"); 584effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch llvm::raw_svector_ostream(OutStr) << Val; 585effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 586effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch break; 587effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 588effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case Diagnostic::ak_uint: { 589effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch unsigned Val = getArgUInt(ArgNo); 590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 591effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (ModifierIs(Modifier, ModifierLen, "select")) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr); 593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else if (ModifierIs(Modifier, ModifierLen, "s")) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleIntegerSModifier(Val, OutStr); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen, 597a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OutStr); 598ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { 599ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch HandleOrdinalModifier(Val, OutStr); 600a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 601a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) assert(ModifierLen == 0 && "Unknown integer modifier"); 602a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) llvm::raw_svector_ostream(OutStr) << Val; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ---- NAMES and TYPES ---- 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Diagnostic::ak_identifierinfo: { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IdentifierInfo *II = getArgIdentifier(ArgNo); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(ModifierLen == 0 && "No modifiers for strings yet"); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Don't crash if get passed a null pointer by accident. 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!II) { 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char *S = "(null)"; 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OutStr.append(S, S + strlen(S)); 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) continue; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\''; 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case Diagnostic::ak_qualtype: 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Diagnostic::ak_declarationname: 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Diagnostic::ak_nameddecl: 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case Diagnostic::ak_nestednamespec: 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case Diagnostic::ak_declcontext: 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Modifier, ModifierLen, 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Argument, ArgumentLen, 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FormattedArgs.data(), FormattedArgs.size(), 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OutStr); 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remember this argument info for subsequent formatting operations. Turn 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // std::strings into a null terminated string to make it be the same case as 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all the other ones. 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Kind != Diagnostic::ak_std_string) 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); 639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string, 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (intptr_t)getArgStdStr(ArgNo).c_str())); 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StoredDiagnostic::StoredDiagnostic() { } 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, unsigned ID, 649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) llvm::StringRef Message) 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : ID(ID), Level(Level), Loc(), Message(Message) { } 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level, 653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const DiagnosticInfo &Info) 654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : ID(Info.getID()), Level(Level) 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) && 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Valid source location without setting a source manager for diagnostic"); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Info.getLocation().isValid()) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager()); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::SmallString<64> Message; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Info.FormatDiagnostic(Message); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->Message.assign(Message.begin(), Message.end()); 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Ranges.reserve(Info.getNumRanges()); 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (unsigned I = 0, N = Info.getNumRanges(); I != N; ++I) 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Ranges.push_back(Info.getRange(I)); 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FixIts.reserve(Info.getNumFixItHints()); 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (unsigned I = 0, N = Info.getNumFixItHints(); I != N; ++I) 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FixIts.push_back(Info.getFixItHint(I)); 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StoredDiagnostic::~StoredDiagnostic() { } 674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// IncludeInDiagnosticCounts - This method (whose default implementation 676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// returns true) indicates whether the diagnostics handled by this 677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// DiagnosticClient should be included in the number of diagnostics 678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// reported by Diagnostic. 679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; } 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PartialDiagnostic::StorageAllocator::StorageAllocator() { 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (unsigned I = 0; I != NumCached; ++I) 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FreeList[I] = Cached + I; 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NumFreeListEntries = NumCached; 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PartialDiagnostic::StorageAllocator::~StorageAllocator() { 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't assert if we are in a CrashRecovery context, as this 689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // invariant may be invalidated during a crash. 690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert((NumFreeListEntries == NumCached || llvm::CrashRecoveryContext::isRecoveringFromCrash()) && "A partial is on the lamb"); 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 692a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)