25#include "llvm/ADT/IntrusiveRefCntPtr.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringExtras.h"
28#include "llvm/ADT/StringMap.h"
29#include "llvm/ADT/StringRef.h"
30#include "llvm/Support/ConvertUTF.h"
31#include "llvm/Support/CrashRecoveryContext.h"
32#include "llvm/Support/Error.h"
33#include "llvm/Support/FormatVariadic.h"
34#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/SpecialCaseList.h"
36#include "llvm/Support/Unicode.h"
37#include "llvm/Support/VirtualFileSystem.h"
38#include "llvm/Support/raw_ostream.h"
70 StringRef Modifier, StringRef Argument,
74 StringRef Str =
"<can't format argument>";
75 Output.append(Str.begin(), Str.end());
82 : Diags(
std::move(diags)), DiagOpts(DiagOpts) {
98 DiagStatesByLoc.dump(*SourceMgr, DiagName);
102 bool ShouldOwnClient) {
103 Owner.reset(ShouldOwnClient ? client :
nullptr);
108 DiagStateOnPushStack.push_back(GetCurDiagState());
112 if (DiagStateOnPushStack.empty())
115 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
117 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
119 DiagStateOnPushStack.pop_back();
126 ErrorOccurred =
false;
127 UncompilableErrorOccurred =
false;
128 FatalErrorOccurred =
false;
129 UnrecoverableErrorOccurred =
false;
133 TrapNumErrorsOccurred = 0;
134 TrapNumUnrecoverableErrorsOccurred = 0;
141 DiagStatesByLoc.clear(
false);
142 DiagStateOnPushStack.clear();
146 DiagStates.emplace_back(*Diags);
147 DiagStatesByLoc.appendFirst(&DiagStates.back());
153 std::pair<iterator, bool>
Result = DiagMap.try_emplace(
Diag);
162 return Result.first->second;
165void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
166 assert(Files.empty() &&
"not first");
167 FirstDiagState = CurDiagState = State;
168 CurDiagStateLoc = SourceLocation();
171void DiagnosticsEngine::DiagStateMap::append(SourceManager &SrcMgr,
174 CurDiagState = State;
175 CurDiagStateLoc = Loc;
178 unsigned Offset = Decomp.second;
179 for (
File *F = getFile(SrcMgr, Decomp.first); F;
180 Offset = F->ParentOffset, F = F->Parent) {
181 F->HasLocalTransitions =
true;
182 auto &
Last = F->StateTransitions.back();
183 assert(
Last.Offset <= Offset &&
"state transitions added out of order");
185 if (
Last.Offset == Offset) {
186 if (
Last.State == State)
192 F->StateTransitions.push_back({State, Offset});
196DiagnosticsEngine::DiagState *
197DiagnosticsEngine::DiagStateMap::lookup(SourceManager &SrcMgr,
198 SourceLocation Loc)
const {
201 return FirstDiagState;
204 const File *F = getFile(SrcMgr, Decomp.first);
205 return F->lookup(Decomp.second);
208DiagnosticsEngine::DiagState *
209DiagnosticsEngine::DiagStateMap::File::lookup(
unsigned Offset)
const {
211 llvm::partition_point(StateTransitions, [=](
const DiagStatePoint &P) {
212 return P.Offset <= Offset;
214 assert(OnePastIt != StateTransitions.begin() &&
"missing initial state");
215 return OnePastIt[-1].State;
218DiagnosticsEngine::DiagStateMap::File *
219DiagnosticsEngine::DiagStateMap::getFile(SourceManager &SrcMgr,
222 if (LastLookupFileID != ID) {
224 LastLookupFile = getFileUncached(SrcMgr, ID);
225 LastLookupFileID =
ID;
227 return LastLookupFile;
230DiagnosticsEngine::DiagStateMap::File *
231DiagnosticsEngine::DiagStateMap::getFileUncached(SourceManager &SrcMgr,
234 auto Range = Files.equal_range(ID);
236 return &
Range.first->second;
237 auto &F = Files.insert(
Range.first, std::make_pair(ID,
File()))->second;
243 F.Parent = getFile(SrcMgr, Decomp.first);
244 F.ParentOffset = Decomp.second;
245 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
254 F.StateTransitions.push_back({FirstDiagState, 0});
259void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
260 StringRef DiagName)
const {
261 llvm::errs() <<
"diagnostic state at ";
262 CurDiagStateLoc.print(llvm::errs(), SrcMgr);
263 llvm::errs() <<
": " << CurDiagState <<
"\n";
265 for (
auto &F : Files) {
269 bool PrintedOuterHeading =
false;
270 auto PrintOuterHeading = [&] {
271 if (PrintedOuterHeading)
273 PrintedOuterHeading =
true;
275 llvm::errs() <<
"File " << &
File <<
" <FileID " <<
ID.getHashValue()
278 if (F.second.Parent) {
280 assert(
File.ParentOffset == Decomp.second);
281 llvm::errs() <<
" parent " <<
File.Parent <<
" <FileID "
282 << Decomp.first.getHashValue() <<
"> ";
285 .
print(llvm::errs(), SrcMgr);
287 if (
File.HasLocalTransitions)
288 llvm::errs() <<
" has_local_transitions";
289 llvm::errs() <<
"\n";
292 if (DiagName.empty())
295 for (DiagStatePoint &Transition :
File.StateTransitions) {
296 bool PrintedInnerHeading =
false;
297 auto PrintInnerHeading = [&] {
298 if (PrintedInnerHeading)
300 PrintedInnerHeading =
true;
306 .
print(llvm::errs(), SrcMgr);
307 llvm::errs() <<
": state " << Transition.State <<
":\n";
310 if (DiagName.empty())
313 for (
auto &Mapping : *Transition.State) {
317 if (!DiagName.empty() && DiagName != Option)
323 llvm::errs() <<
"<unknown " << Mapping.first <<
">";
325 llvm::errs() << Option;
326 llvm::errs() <<
": ";
328 switch (Mapping.second.getSeverity()) {
330 llvm::errs() <<
"ignored";
333 llvm::errs() <<
"remark";
336 llvm::errs() <<
"warning";
339 llvm::errs() <<
"error";
342 llvm::errs() <<
"fatal";
346 if (!Mapping.second.isUser())
347 llvm::errs() <<
" default";
348 if (Mapping.second.isPragma())
349 llvm::errs() <<
" pragma";
350 if (Mapping.second.hasNoWarningAsError())
351 llvm::errs() <<
" no-error";
352 if (Mapping.second.hasNoErrorAsFatal())
353 llvm::errs() <<
" no-fatal";
354 if (Mapping.second.wasUpgradedFromWarning())
355 llvm::errs() <<
" overruled";
356 llvm::errs() <<
"\n";
362void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
363 SourceLocation Loc) {
364 assert(Loc.
isValid() &&
"Adding invalid loc point");
365 DiagStatesByLoc.append(*SourceMgr, Loc, State);
370 assert((Diags->isWarningOrExtension(
Diag) ||
372 "Cannot map errors into warnings!");
373 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
377 bool WasUpgradedFromWarning =
false;
383 WasUpgradedFromWarning =
true;
396 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
397 DiagStatesByLoc.getCurDiagState()) {
402 DiagStatesByLoc.getCurDiagState()->setMapping(
Diag, Mapping);
409 DiagStates.push_back(*GetCurDiagState());
410 DiagStates.back().setMapping(
Diag, Mapping);
411 PushDiagStatePoint(&DiagStates.back(), L);
419 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
422 Diags->setGroupSeverity(Group, Map);
506 std::vector<diag::kind> AllDiags;
511 if (Diags->isWarningOrExtension(
Diag))
518class WarningsSpecialCaseList :
public llvm::SpecialCaseList {
520 static std::unique_ptr<WarningsSpecialCaseList>
521 create(
const llvm::MemoryBuffer &Input, std::string &Err);
533 llvm::DenseMap<diag::kind, const Section *> DiagToSection;
537std::unique_ptr<WarningsSpecialCaseList>
538WarningsSpecialCaseList::create(
const llvm::MemoryBuffer &Input,
540 auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
541 if (!WarningSuppressionList->createInternal(&Input, Err))
543 return WarningSuppressionList;
548 for (
const auto &SectionEntry : sections()) {
549 StringRef DiagGroup = SectionEntry.name();
550 if (DiagGroup ==
"*") {
556 SmallVector<diag::kind> GroupDiags;
557 if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
558 WarningFlavor, DiagGroup, GroupDiags)) {
559 StringRef Suggestion =
561 Diags.Report(diag::warn_unknown_diag_option)
562 <<
static_cast<unsigned>(WarningFlavor) << DiagGroup
563 << !Suggestion.empty() << Suggestion;
569 DiagToSection[
Diag] = &SectionEntry;
575 auto WarningSuppressionList = WarningsSpecialCaseList::create(Input,
Error);
576 if (!WarningSuppressionList) {
579 Report(diag::err_drv_malformed_warning_suppression_mapping)
580 << Input.getBufferIdentifier() <<
Error;
583 WarningSuppressionList->processSections(*
this);
584 DiagSuppressionMapping =
585 [WarningSuppressionList(std::move(WarningSuppressionList))](
587 return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc, SM);
591bool WarningsSpecialCaseList::isDiagSuppressed(
diag::kind DiagId,
594 const Section *DiagSection = DiagToSection.lookup(DiagId);
601 StringRef F = llvm::sys::path::remove_leading_dotslash(PLoc.
getFilename());
603 unsigned LastSup = DiagSection->getLastMatch(
"src", F,
"");
607 unsigned LastEmit = DiagSection->getLastMatch(
"src", F,
"emit");
608 return LastSup > LastEmit;
637 assert(Client &&
"DiagnosticConsumer not set!");
645 assert(DiagLevel !=
Ignored &&
"Cannot emit ignored diagnostics!");
647 "Trap diagnostics should not be consumed by the DiagnosticsEngine");
660 assert(
getClient() &&
"DiagnosticClient not set!");
663 unsigned DiagID = Info.
getID();
668 if (DiagLevel >=
Error) {
669 ++TrapNumErrorsOccurred;
670 if (Diags->isUnrecoverable(DiagID))
671 ++TrapNumUnrecoverableErrorsOccurred;
674 if (SuppressAllDiagnostics)
677 if (DiagLevel !=
Note) {
682 if (LastDiagLevel ==
Fatal)
683 FatalErrorOccurred =
true;
685 LastDiagLevel = DiagLevel;
690 if (FatalErrorOccurred) {
691 if (DiagLevel >=
Error && Client->IncludeInDiagnosticCounts())
702 if (DiagLevel >=
Error) {
703 if (Diags->isUnrecoverable(DiagID))
704 UnrecoverableErrorOccurred =
true;
707 if (Diags->isDefaultMappingAsError(DiagID))
708 UncompilableErrorOccurred =
true;
710 ErrorOccurred =
true;
711 if (Client->IncludeInDiagnosticCounts())
716 if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel ==
Error) {
717 Report(diag::fatal_too_many_errors);
724 if (Info.
getID() == diag::fatal_too_many_errors)
725 FatalErrorOccurred =
true;
734 assert(
getClient() &&
"DiagnosticClient not set!");
744 Emitted = DiagLevel !=
Ignored;
750 Emitted = ProcessDiag(DB);
759 DiagLoc(DiagLoc), DiagID(DiagID), IsActive(
true) {
760 assert(DiagObj &&
"DiagnosticBuilder requires a valid DiagnosticsEngine!");
763DiagnosticBuilder::DiagnosticBuilder(
const DiagnosticBuilder &D)
767 FlagValue = D.FlagValue;
772 IsActive = D.IsActive;
773 IsForceEmit = D.IsForceEmit;
779 : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
780 FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.
getStorage()) {
785 StringRef StoredDiagMessage)
786 : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
787 StoredDiagMessage(StoredDiagMessage) {}
803template <std::
size_t StrLen>
804static bool ModifierIs(
const char *Modifier,
unsigned ModifierLen,
805 const char (&Str)[StrLen]) {
806 return StrLen - 1 == ModifierLen && memcmp(Modifier, Str, StrLen - 1) == 0;
814 for (; I != E; ++I) {
815 if (Depth == 0 && *I ==
Target)
817 if (Depth != 0 && *I ==
'}')
829 for (I++; I != E && !
isDigit(*I) && *I !=
'{'; I++)
847 const char *Argument,
unsigned ArgumentLen,
849 const char *ArgumentEnd = Argument + ArgumentLen;
853 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
854 assert(NextVal != ArgumentEnd &&
855 "Value for integer select modifier was"
856 " larger than the number of options in the diagnostic string!");
857 Argument = NextVal + 1;
862 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
874 OutStr.push_back(
's');
883 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
885 llvm::raw_svector_ostream Out(OutStr);
889 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
900 static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
901 {{1'000'000'000'000L,
'T'},
902 {1'000'000'000L,
'G'},
906 llvm::raw_svector_ostream Out(OutStr);
911 for (
const auto &[UnitSize, UnitSign] : Units) {
912 if (ValNo >= UnitSize) {
913 Out << llvm::format(
"%0.2f%c", ValNo /
static_cast<double>(UnitSize),
925 while (Start != End && *Start >=
'0' && *Start <=
'9') {
942 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
945 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
947 return Low <= Val && Val <= High;
962 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
964 unsigned ValMod = ValNo % Arg;
968 assert((
C ==
'[' || (
C >=
'0' &&
C <=
'9')) &&
969 "Bad plural expression syntax: unexpected character");
976 Start = std::find(Start, End,
',');
1018 const char *Argument,
unsigned ArgumentLen,
1020 const char *ArgumentEnd = Argument + ArgumentLen;
1022 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
1023 const char *ExprEnd = Argument;
1024 while (*ExprEnd !=
':') {
1025 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
1029 Argument = ExprEnd + 1;
1030 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
1037 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
1046 case tok::identifier:
1047 return "identifier";
1057 if (StoredDiagMessage.has_value()) {
1058 OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
1071 bool ForCodepoint) {
1072 OutStr.reserve(OutStr.size() + Str.size());
1073 auto *Begin =
reinterpret_cast<const unsigned char *
>(Str.data());
1074 llvm::raw_svector_ostream OutStream(OutStr);
1075 unsigned Size = Str.size();
1076 const unsigned char *End = Begin + Size;
1078 unsigned Size = llvm::getUTF8SequenceSize(Begin, End);
1080 Size = llvm::findMaximalSubpartOfIllFormedUTF8Sequence(Begin, End);
1083 while (Begin != End) {
1085 OutStream << *Begin;
1089 if (ForCodepoint && *Begin < 0x80) {
1091 OutStream <<
"'" << *Begin <<
"'";
1096 if (llvm::isLegalUTF8Sequence(Begin, End)) {
1097 llvm::UTF32 CodepointValue;
1098 llvm::UTF32 *CpPtr = &CodepointValue;
1099 const unsigned char *CodepointBegin = Begin;
1100 const unsigned char *CodepointEnd =
1101 Begin + llvm::getNumBytesForUTF8(*Begin);
1102 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1103 &Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1106 llvm::conversionOK == Res &&
1107 "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1108 assert(Begin == CodepointEnd &&
1109 "we must be further along in the string now");
1111 if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1112 (!ForCodepoint && llvm::sys::unicode::isFormatting(CodepointValue))) {
1113 OutStream << (ForCodepoint ?
"'" :
"")
1114 << StringRef(
reinterpret_cast<const char *
>(CodepointBegin),
1115 std::distance(CodepointBegin, CodepointEnd))
1116 << (ForCodepoint ?
"' " :
"");
1121 OutStream << (ForCodepoint ?
"" :
"<") <<
"U+"
1122 << llvm::format_hex_no_prefix(CodepointValue, 4,
true)
1123 << (ForCodepoint ?
"" :
">");
1127 OutStream <<
"<0x" << llvm::format_hex_no_prefix(*Begin, 2,
true) <<
">";
1148 char ResultBuf[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
1149 char *ResultPtr = ResultBuf;
1150 if (!llvm::ConvertCodePointToUTF8(CP, ResultPtr))
1153 StringRef(ResultBuf, ResultPtr - ResultBuf));
1161 if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) ==
"%0" &&
1179 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
1183 while (DiagStr != DiagEnd) {
1184 if (DiagStr[0] !=
'%') {
1186 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
1187 OutStr.append(DiagStr, StrEnd);
1191 OutStr.push_back(DiagStr[1]);
1204 const char *Modifier =
nullptr, *Argument =
nullptr;
1205 unsigned ModifierLen = 0, ArgumentLen = 0;
1210 while (DiagStr[0] ==
'-' || (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
1212 ModifierLen = DiagStr - Modifier;
1215 if (DiagStr[0] ==
'{') {
1220 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
1221 ArgumentLen = DiagStr - Argument;
1226 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
1227 unsigned ArgNo = *DiagStr++ -
'0';
1230 unsigned ArgNo2 = ArgNo;
1233 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
1234 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
1235 "Invalid format for diff modifier");
1237 ArgNo2 = *DiagStr++ -
'0';
1248 const char *ArgumentEnd = Argument + ArgumentLen;
1251 "Found too many '|'s in a %diff modifier!");
1253 const char *SecondDollar =
ScanFormat(FirstDollar + 1,
Pipe,
'$');
1254 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo)};
1255 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2)};
1269 StringRef S = [&]() -> StringRef {
1274 return SZ ? SZ :
"(null)";
1276 bool Quoted =
false;
1277 if (
ModifierIs(Modifier, ModifierLen,
"quoted")) {
1279 OutStr.push_back(
'\'');
1281 assert(ModifierLen == 0 &&
"unknown modifier for string");
1285 OutStr.push_back(
'\'');
1292 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1295 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1297 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1300 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1302 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1305 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1306 llvm::raw_svector_ostream(OutStr) << Val;
1313 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1315 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1317 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1320 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1322 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1325 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1326 llvm::raw_svector_ostream(OutStr) << Val;
1333 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
1335 llvm::raw_svector_ostream Out(OutStr);
1338 Out <<
'\'' << S <<
'\'';
1347 Out <<
'<' << S <<
'>';
1355 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1359 const char *S =
"(null)";
1360 OutStr.append(S, S + strlen(S));
1364 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->
getName() <<
'\'';
1378 StringRef(Modifier, ModifierLen),
1379 StringRef(Argument, ArgumentLen),
1380 FormattedArgs, OutStr, QualTypeVals);
1392 const char *ArgumentEnd = Argument + ArgumentLen;
1397 if (
getDiags()->PrintTemplateTree && Tree.empty()) {
1401 StringRef(Modifier, ModifierLen),
1402 StringRef(Argument, ArgumentLen),
1403 FormattedArgs, Tree, QualTypeVals);
1405 if (!Tree.empty()) {
1413 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
1414 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
1423 StringRef(Modifier, ModifierLen),
1424 StringRef(Argument, ArgumentLen),
1425 FormattedArgs, OutStr, QualTypeVals);
1427 FormattedArgs.push_back(
1436 StringRef(Modifier, ModifierLen),
1437 StringRef(Argument, ArgumentLen),
1438 FormattedArgs, OutStr, QualTypeVals);
1440 FormattedArgs.push_back(
1455 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
1457 FormattedArgs.push_back(
1463 OutStr.append(Tree.begin(), Tree.end());
1468 : ID(ID), Level(Level), Message(Message) {}
1472 : ID(Info.
getID()), Level(Level) {
1475 "Valid source location without setting a source manager for diagnostic");
1480 this->Message.assign(Message.begin(), Message.end());
1489 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1490 Ranges(Ranges.begin(), Ranges.end()),
1491 FixIts(FixIts.begin(), FixIts.end()) {}
1507void IgnoringDiagConsumer::anchor() {}
1513 Target.HandleDiagnostic(DiagLevel, Info);
1522 return Target.IncludeInDiagnosticCounts();
1526 for (
unsigned I = 0; I != NumCached; ++I)
1527 FreeList[I] = Cached + I;
1528 NumFreeListEntries = NumCached;
1534 assert((NumFreeListEntries == NumCached ||
1535 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1536 "A partial is on the lam");
static const char * ScanFormat(const char *I, const char *E, char Target)
ScanForward - Scans forward, looking for the given character, skipping nested clauses and escaped cha...
static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandlePluralModifier - Handle the integer 'plural' modifier.
static void HandleIntegerSModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleIntegerSModifier - Handle the integer 's' modifier.
static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT, StringRef Modifier, StringRef Argument, ArrayRef< DiagnosticsEngine::ArgumentValue > PrevArgs, SmallVectorImpl< char > &Output, void *Cookie, ArrayRef< intptr_t > QualTypeVals)
static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End)
EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
static void HandleIntegerHumanModifier(int64_t ValNo, SmallVectorImpl< char > &OutStr)
static unsigned PluralNumber(const char *&Start, const char *End)
PluralNumber - Parse an unsigned integer and advance Start.
static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandleSelectModifier - Handle the integer 'select' modifier.
static bool ModifierIs(const char *Modifier, unsigned ModifierLen, const char(&Str)[StrLen])
ModifierIs - Return true if the specified modifier matches specified string.
static bool TestPluralRange(unsigned Val, const char *&Start, const char *End)
TestPluralRange - Test if Val is in the parsed range. Modifies Start.
static void HandleOrdinalModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleOrdinalModifier - Handle the integer 'ord' modifier.
static const char * getTokenDescForDiagnostic(tok::TokenKind Kind)
Returns the friendly description for a token kind that will appear without quotes in diagnostic messa...
Defines the Diagnostic-related interfaces.
static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM, StringRef Name)
Defines the Diagnostic IDs-related interfaces.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Target Target
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines various enumerations that describe declaration and type specifiers.
Defines the clang::TokenKind enum and support functions.
A little helper class used to produce diagnostics.
void Clear() const
Clear out the current diagnostic.
friend class DiagnosticsEngine
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
virtual ~DiagnosticConsumer()
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info)
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
unsigned NumErrors
Number of errors reported.
unsigned NumWarnings
Number of warnings reported.
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
void initCustomDiagMapping(DiagnosticMapping &, unsigned DiagID)
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group)
Get the diagnostic option with the closest edit distance to the given group name.
DiagnosticMapping getDefaultMapping(unsigned DiagID) const
Get the default mapping for this diagnostic.
static bool IsCustomDiag(diag::kind Diag)
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
void setNoWarningAsError(bool Value)
void setSeverity(diag::Severity Value)
diag::Severity getSeverity() const
void setUpgradedFromWarning(bool Value)
void setNoErrorAsFatal(bool Value)
bool hasNoWarningAsError() const
Options for controlling the compiler diagnostics engine.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine a...
Diagnostic(const DiagnosticsEngine *DO, const DiagnosticBuilder &DiagBuilder)
const SourceLocation & getLocation() const
const std::string & getArgStdStr(unsigned Idx) const
Return the provided argument string specified by Idx.
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots.
uint64_t getRawArg(unsigned Idx) const
Return the specified non-string argument in an opaque form.
const char * getArgCStr(unsigned Idx) const
Return the specified C string argument.
const IdentifierInfo * getArgIdentifier(unsigned Idx) const
Return the specified IdentifierInfo argument.
SourceManager & getSourceManager() const
ArrayRef< FixItHint > getFixItHints() const
unsigned getNumArgs() const
bool hasSourceManager() const
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const
Return the kind of the specified index.
int64_t getArgSInt(unsigned Idx) const
Return the specified signed integer argument.
uint64_t getArgUInt(unsigned Idx) const
Return the specified unsigned integer argument.
ArrayRef< CharSourceRange > getRanges() const
Return an array reference for this diagnostic's ranges.
const DiagnosticsEngine * getDiags() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool hasSourceManager() const
bool EmitDiagnostic(const DiagnosticBuilder &DB, bool Force=false)
Emit the diagnostic.
void setDiagSuppressionMapping(llvm::MemoryBuffer &Input)
Diagnostic suppression mappings can be used to suppress specific diagnostics in specific files.
DiagnosticsEngine(IntrusiveRefCntPtr< DiagnosticIDs > Diags, DiagnosticOptions &DiagOpts, DiagnosticConsumer *client=nullptr, bool ShouldOwnClient=true)
DiagStateSystemClass getDiagStateSystemClassForLoc(SourceLocation Loc) const
Returns whether Loc is in a system header and/or a system macro.
bool isSuppressedViaMapping(diag::kind DiagId, SourceLocation DiagLoc) const
void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, SourceLocation Loc=SourceLocation())
Add the specified mapping to all diagnostics of the specified flavor.
LLVM_DUMP_METHOD void dump() const
void ResetPragmas()
We keep a cache of FileIDs for diagnostics mapped by pragmas.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
SourceManager & getSourceManager() const
void pushMappings(SourceLocation Loc)
Copies the current DiagMappings and pushes the new copy onto the top of the stack.
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
Level
The level of the diagnostic, after it has been through mapping.
friend class DiagnosticBuilder
DiagnosticConsumer * getClient()
@ ak_nameddecl
NamedDecl *.
@ ak_declcontext
DeclContext *.
@ ak_addrspace
address space
@ ak_identifierinfo
IdentifierInfo.
@ ak_qualtype_pair
pair<QualType, QualType>
@ ak_attr_info
AttributeCommonInfo *.
@ ak_c_string
const char *
@ ak_declarationname
DeclarationName.
@ ak_tokenkind
enum TokenKind : unsigned
@ ak_std_string
std::string
@ ak_nestednamespec
NestedNameSpecifier *.
Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const
Based on the way the client configured the DiagnosticsEngine object, classify the specified diagnosti...
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled)
Set the error-as-fatal flag for the given diagnostic group.
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled)
Set the warning-as-error flag for the given diagnostic group.
void ConvertArgToString(ArgumentKind Kind, intptr_t Val, StringRef Modifier, StringRef Argument, ArrayRef< ArgumentValue > PrevArgs, SmallVectorImpl< char > &Output, ArrayRef< intptr_t > QualTypeVals) const
Converts a diagnostic argument (as an intptr_t) into the string that represents it.
bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, diag::Severity Map, SourceLocation Loc=SourceLocation())
Change an entire diagnostic group (e.g.
bool popMappings(SourceLocation Loc)
Pops the current DiagMappings off the top of the stack, causing the new top of the stack to be the ac...
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
void Reset(bool soft=false)
Reset the state of the diagnostic object to its initial configuration.
static FileID getSentinel()
bool IncludeInDiagnosticCounts() const override
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
~ForwardingDiagnosticConsumer() override
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
A SourceLocation and its associated SourceManager.
bool hasManager() const
Checks whether the SourceManager is present.
const SourceManager & getManager() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
Encodes a location in the source.
std::string printToString(const SourceManager &SM) const
bool isValid() const
Return true if this is a valid SourceLocation object.
void print(raw_ostream &OS, const SourceManager &SM) const
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
DiagnosticsEngine & getDiagnostics() const
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
bool isInSystemMacro(SourceLocation loc) const
Returns whether Loc is expanded from a macro in a system header.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
range_iterator range_begin() const
StoredDiagnostic()=default
DiagnosticsEngine::Level getLevel() const
fixit_iterator fixit_begin() const
const FullSourceLoc & getLocation() const
range_iterator range_end() const
StringRef getMessage() const
fixit_iterator fixit_end() const
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
DiagStorageAllocator * Allocator
Allocator used to allocate storage for this diagnostic.
StreamingDiagnostic()=default
DiagnosticStorage * DiagStorage
void AddString(StringRef V) const
Flavor
Flavors of diagnostics we can emit.
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing),...
@ Warning
Present this diagnostic as a warning.
@ Fatal
Present this diagnostic as a fatal error.
@ Error
Present this diagnostic as an error.
@ Remark
Present this diagnostic as a remark.
@ Ignored
Do not present this diagnostic, ignore it.
const char * getTokenName(TokenKind Kind) LLVM_READNONE
Determines the name of a token as used within the front end.
const char * getKeywordSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple keyword and contextual keyword tokens like 'int' and 'dynamic_cast'...
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like '!
Top level wrappers for InstallAPI frontend operations.
LLVM_READONLY bool isPrintable(unsigned char c)
Return true if this character is an ASCII printable character; that is, a character that should take ...
DiagStateSystemClass
Whether a source location is in a system header and/or a system macro.
std::pair< FileID, unsigned > FileIDAndOffset
std::pair< NullabilityKind, bool > DiagNullabilityKind
A nullability kind paired with a bit indicating whether it used a context-sensitive keyword.
@ Result
The result type of a method or function.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl< char > &OutStr)
EscapeStringForDiagnostic - Append Str to the diagnostic buffer, escaping non-printable characters an...
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
SmallString< 16 > EscapeSingleCodepointForDiagnostic(StringRef Str)
Displays a single Unicode codepoint in U+NNNN notation, optionally prepending the quoted codepoint it...
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)
Insertion operator for diagnostics.
LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type,...
SmallVector< CharSourceRange, 8 > DiagRanges
The list of ranges added to this diagnostic.
SmallVector< FixItHint, 6 > FixItHints
If valid, provides a hint with some code to insert, remove, or modify at a particular position.
unsigned TemplateDiffUsed