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