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/MemoryBuffer.h"
34#include "llvm/Support/SpecialCaseList.h"
35#include "llvm/Support/Unicode.h"
36#include "llvm/Support/VirtualFileSystem.h"
37#include "llvm/Support/raw_ostream.h"
69 StringRef Modifier, StringRef Argument,
73 StringRef Str =
"<can't format argument>";
74 Output.append(Str.begin(), Str.end());
81 : Diags(
std::move(diags)), DiagOpts(DiagOpts) {
97 DiagStatesByLoc.dump(*SourceMgr, DiagName);
101 bool ShouldOwnClient) {
102 Owner.reset(ShouldOwnClient ? client :
nullptr);
107 DiagStateOnPushStack.push_back(GetCurDiagState());
111 if (DiagStateOnPushStack.empty())
114 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
116 PushDiagStatePoint(DiagStateOnPushStack.back(),
Loc);
118 DiagStateOnPushStack.pop_back();
125 ErrorOccurred =
false;
126 UncompilableErrorOccurred =
false;
127 FatalErrorOccurred =
false;
128 UnrecoverableErrorOccurred =
false;
132 TrapNumErrorsOccurred = 0;
133 TrapNumUnrecoverableErrorsOccurred = 0;
140 DiagStatesByLoc.clear(
false);
141 DiagStateOnPushStack.clear();
145 DiagStates.emplace_back(*Diags);
146 DiagStatesByLoc.appendFirst(&DiagStates.back());
152 std::pair<iterator, bool>
Result = DiagMap.try_emplace(
Diag);
156 Result.first->second = DiagIDs.getDefaultMapping(
Diag);
158 DiagIDs.initCustomDiagMapping(
Result.first->second,
Diag);
161 return Result.first->second;
164void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
165 assert(Files.empty() &&
"not first");
166 FirstDiagState = CurDiagState = State;
170void DiagnosticsEngine::DiagStateMap::append(
SourceManager &SrcMgr,
173 CurDiagState = State;
174 CurDiagStateLoc =
Loc;
177 unsigned Offset = Decomp.second;
178 for (
File *F = getFile(SrcMgr, Decomp.first); F;
179 Offset = F->ParentOffset, F = F->Parent) {
180 F->HasLocalTransitions =
true;
181 auto &
Last = F->StateTransitions.back();
182 assert(
Last.Offset <= Offset &&
"state transitions added out of order");
184 if (
Last.Offset == Offset) {
185 if (
Last.State == State)
191 F->StateTransitions.push_back({State, Offset});
195DiagnosticsEngine::DiagState *
196DiagnosticsEngine::DiagStateMap::lookup(
SourceManager &SrcMgr,
200 return FirstDiagState;
203 const File *F = getFile(SrcMgr, Decomp.first);
204 return F->lookup(Decomp.second);
207DiagnosticsEngine::DiagState *
208DiagnosticsEngine::DiagStateMap::File::lookup(
unsigned Offset)
const {
210 llvm::partition_point(StateTransitions, [=](
const DiagStatePoint &
P) {
211 return P.Offset <= Offset;
213 assert(OnePastIt != StateTransitions.begin() &&
"missing initial state");
214 return OnePastIt[-1].State;
217DiagnosticsEngine::DiagStateMap::File *
218DiagnosticsEngine::DiagStateMap::getFile(
SourceManager &SrcMgr,
221 auto Range = Files.equal_range(ID);
223 return &
Range.first->second;
224 auto &F = Files.insert(
Range.first, std::make_pair(ID,
File()))->second;
230 F.Parent = getFile(SrcMgr, Decomp.first);
231 F.ParentOffset = Decomp.second;
232 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
241 F.StateTransitions.push_back({FirstDiagState, 0});
246void DiagnosticsEngine::DiagStateMap::dump(
SourceManager &SrcMgr,
247 StringRef DiagName)
const {
248 llvm::errs() <<
"diagnostic state at ";
249 CurDiagStateLoc.print(llvm::errs(), SrcMgr);
250 llvm::errs() <<
": " << CurDiagState <<
"\n";
252 for (
auto &F : Files) {
256 bool PrintedOuterHeading =
false;
257 auto PrintOuterHeading = [&] {
258 if (PrintedOuterHeading)
260 PrintedOuterHeading =
true;
262 llvm::errs() <<
"File " << &
File <<
" <FileID " <<
ID.getHashValue()
265 if (F.second.Parent) {
267 assert(
File.ParentOffset == Decomp.second);
268 llvm::errs() <<
" parent " <<
File.Parent <<
" <FileID "
269 << Decomp.first.getHashValue() <<
"> ";
272 .
print(llvm::errs(), SrcMgr);
274 if (
File.HasLocalTransitions)
275 llvm::errs() <<
" has_local_transitions";
276 llvm::errs() <<
"\n";
279 if (DiagName.empty())
282 for (DiagStatePoint &Transition :
File.StateTransitions) {
283 bool PrintedInnerHeading =
false;
284 auto PrintInnerHeading = [&] {
285 if (PrintedInnerHeading)
287 PrintedInnerHeading =
true;
293 .
print(llvm::errs(), SrcMgr);
294 llvm::errs() <<
": state " << Transition.State <<
":\n";
297 if (DiagName.empty())
300 for (
auto &Mapping : *Transition.State) {
304 if (!DiagName.empty() && DiagName != Option)
310 llvm::errs() <<
"<unknown " << Mapping.first <<
">";
312 llvm::errs() << Option;
313 llvm::errs() <<
": ";
315 switch (Mapping.second.getSeverity()) {
317 llvm::errs() <<
"ignored";
320 llvm::errs() <<
"remark";
323 llvm::errs() <<
"warning";
326 llvm::errs() <<
"error";
329 llvm::errs() <<
"fatal";
333 if (!Mapping.second.isUser())
334 llvm::errs() <<
" default";
335 if (Mapping.second.isPragma())
336 llvm::errs() <<
" pragma";
337 if (Mapping.second.hasNoWarningAsError())
338 llvm::errs() <<
" no-error";
339 if (Mapping.second.hasNoErrorAsFatal())
340 llvm::errs() <<
" no-fatal";
341 if (Mapping.second.wasUpgradedFromWarning())
342 llvm::errs() <<
" overruled";
343 llvm::errs() <<
"\n";
349void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
351 assert(
Loc.
isValid() &&
"Adding invalid loc point");
352 DiagStatesByLoc.append(*SourceMgr,
Loc, State);
357 assert((Diags->isWarningOrExtension(
Diag) ||
359 "Cannot map errors into warnings!");
360 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
364 bool WasUpgradedFromWarning =
false;
370 WasUpgradedFromWarning =
true;
383 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
384 DiagStatesByLoc.getCurDiagState()) {
389 DiagStatesByLoc.getCurDiagState()->setMapping(
Diag, Mapping);
396 DiagStates.push_back(*GetCurDiagState());
397 DiagStates.back().setMapping(
Diag, Mapping);
398 PushDiagStatePoint(&DiagStates.back(), L);
406 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
409 Diags->setGroupSeverity(Group, Map);
493 std::vector<diag::kind> AllDiags;
498 if (Diags->isWarningOrExtension(
Diag))
505class WarningsSpecialCaseList :
public llvm::SpecialCaseList {
507 static std::unique_ptr<WarningsSpecialCaseList>
508 create(
const llvm::MemoryBuffer &Input, std::string &Err);
523 bool globsMatches(
const llvm::StringMap<Matcher> &CategoriesToMatchers,
524 StringRef FilePath)
const;
526 llvm::DenseMap<diag::kind, const Section *> DiagToSection;
530std::unique_ptr<WarningsSpecialCaseList>
531WarningsSpecialCaseList::create(
const llvm::MemoryBuffer &Input,
533 auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
534 if (!WarningSuppressionList->createInternal(&Input, Err))
536 return WarningSuppressionList;
545 llvm::erase_if(Sections, [](Section &sec) {
return sec.SectionStr ==
"*"; });
547 std::vector<std::pair<unsigned, const Section *>> LineAndSectionEntry;
548 LineAndSectionEntry.reserve(Sections.size());
549 for (
const auto &Entry : Sections) {
550 StringRef DiagName = Entry.SectionStr;
553 const auto &DiagSectionMatcher = Entry.SectionMatcher;
554 unsigned DiagLine = 0;
555 for (
const auto &Glob : DiagSectionMatcher->Globs)
556 if (Glob->Name == DiagName) {
557 DiagLine = Glob->LineNo;
560 LineAndSectionEntry.emplace_back(DiagLine, &Entry);
562 llvm::sort(LineAndSectionEntry);
564 for (
const auto &[_, SectionEntry] : LineAndSectionEntry) {
566 StringRef DiagGroup = SectionEntry->SectionStr;
568 WarningFlavor, DiagGroup, GroupDiags)) {
569 StringRef Suggestion =
571 Diags.
Report(diag::warn_unknown_diag_option)
572 <<
static_cast<unsigned>(WarningFlavor) << DiagGroup
573 << !Suggestion.empty() << Suggestion;
579 DiagToSection[
Diag] = SectionEntry;
585 auto WarningSuppressionList = WarningsSpecialCaseList::create(Input,
Error);
586 if (!WarningSuppressionList) {
589 Report(diag::err_drv_malformed_warning_suppression_mapping)
590 << Input.getBufferIdentifier() <<
Error;
593 WarningSuppressionList->processSections(*
this);
594 DiagSuppressionMapping =
595 [WarningSuppressionList(std::move(WarningSuppressionList))](
597 return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc,
SM);
601bool WarningsSpecialCaseList::isDiagSuppressed(
diag::kind DiagId,
604 const Section *DiagSection = DiagToSection.lookup(DiagId);
607 const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
608 auto SrcEntriesIt = EntityTypeToCategories.find(
"src");
609 if (SrcEntriesIt == EntityTypeToCategories.end())
611 const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
612 SrcEntriesIt->getValue();
615 if (
PresumedLoc PLoc =
SM.getPresumedLoc(DiagLoc); PLoc.isValid())
617 CategoriesToMatchers,
618 llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
622bool WarningsSpecialCaseList::globsMatches(
623 const llvm::StringMap<Matcher> &CategoriesToMatchers,
624 StringRef FilePath)
const {
625 StringRef LongestMatch;
626 bool LongestIsPositive =
false;
627 for (
const auto &Entry : CategoriesToMatchers) {
628 StringRef
Category = Entry.getKey();
629 const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue();
630 bool IsPositive =
Category !=
"emit";
631 for (
const auto &Glob : Matcher.Globs) {
632 if (Glob->Name.size() < LongestMatch.size())
634 if (!Glob->Pattern.match(FilePath))
636 LongestMatch = Glob->Name;
637 LongestIsPositive = IsPositive;
640 return LongestIsPositive;
658 assert(Client &&
"DiagnosticConsumer not set!");
666 assert(DiagLevel !=
Ignored &&
"Cannot emit ignored diagnostics!");
668 "Trap diagnostics should not be consumed by the DiagnosticsEngine");
681 assert(
getClient() &&
"DiagnosticClient not set!");
684 unsigned DiagID = Info.
getID();
689 if (DiagLevel >=
Error) {
690 ++TrapNumErrorsOccurred;
691 if (Diags->isUnrecoverable(DiagID))
692 ++TrapNumUnrecoverableErrorsOccurred;
695 if (SuppressAllDiagnostics)
698 if (DiagLevel !=
Note) {
703 if (LastDiagLevel ==
Fatal)
704 FatalErrorOccurred =
true;
706 LastDiagLevel = DiagLevel;
711 if (FatalErrorOccurred) {
723 if (DiagLevel >=
Error) {
724 if (Diags->isUnrecoverable(DiagID))
725 UnrecoverableErrorOccurred =
true;
728 if (Diags->isDefaultMappingAsError(DiagID))
729 UncompilableErrorOccurred =
true;
731 ErrorOccurred =
true;
737 if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel ==
Error) {
738 Report(diag::fatal_too_many_errors);
745 if (Info.
getID() == diag::fatal_too_many_errors)
746 FatalErrorOccurred =
true;
755 assert(
getClient() &&
"DiagnosticClient not set!");
765 Emitted = DiagLevel !=
Ignored;
771 Emitted = ProcessDiag(DB);
780 DiagLoc(DiagLoc), DiagID(DiagID), IsActive(
true) {
781 assert(DiagObj &&
"DiagnosticBuilder requires a valid DiagnosticsEngine!");
788 FlagValue =
D.FlagValue;
791 D.DiagStorage =
nullptr;
793 IsActive =
D.IsActive;
794 IsForceEmit =
D.IsForceEmit;
800 : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
801 FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.
getStorage()) {
806 StringRef StoredDiagMessage)
807 : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
808 StoredDiagMessage(StoredDiagMessage) {}
824template <std::
size_t StrLen>
825static bool ModifierIs(
const char *Modifier,
unsigned ModifierLen,
826 const char (&Str)[StrLen]) {
827 return StrLen - 1 == ModifierLen && memcmp(Modifier, Str, StrLen - 1) == 0;
835 for (; I !=
E; ++I) {
836 if (Depth == 0 && *I ==
Target)
838 if (Depth != 0 && *I ==
'}')
850 for (I++; I !=
E && !
isDigit(*I) && *I !=
'{'; I++)
868 const char *Argument,
unsigned ArgumentLen,
870 const char *ArgumentEnd = Argument + ArgumentLen;
874 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
875 assert(NextVal != ArgumentEnd &&
876 "Value for integer select modifier was"
877 " larger than the number of options in the diagnostic string!");
878 Argument = NextVal + 1;
883 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
895 OutStr.push_back(
's');
904 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
906 llvm::raw_svector_ostream Out(OutStr);
910 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
921 static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
922 {{1'000'000'000'000L,
'T'},
923 {1'000'000'000L,
'G'},
927 llvm::raw_svector_ostream Out(OutStr);
932 for (
const auto &[UnitSize, UnitSign] : Units) {
933 if (ValNo >= UnitSize) {
934 Out << llvm::format(
"%0.2f%c", ValNo /
static_cast<double>(UnitSize),
946 while (Start != End && *Start >=
'0' && *Start <=
'9') {
963 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
966 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
968 return Low <= Val && Val <= High;
983 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
985 unsigned ValMod = ValNo % Arg;
989 assert((
C ==
'[' || (
C >=
'0' &&
C <=
'9')) &&
990 "Bad plural expression syntax: unexpected character");
997 Start = std::find(Start, End,
',');
1039 const char *Argument,
unsigned ArgumentLen,
1041 const char *ArgumentEnd = Argument + ArgumentLen;
1043 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
1044 const char *ExprEnd = Argument;
1045 while (*ExprEnd !=
':') {
1046 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
1050 Argument = ExprEnd + 1;
1051 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
1058 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
1067 case tok::identifier:
1068 return "identifier";
1078 if (StoredDiagMessage.has_value()) {
1079 OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
1092 OutStr.reserve(OutStr.size() + Str.size());
1093 auto *
Begin =
reinterpret_cast<const unsigned char *
>(Str.data());
1094 llvm::raw_svector_ostream OutStream(OutStr);
1095 const unsigned char *End =
Begin + Str.size();
1096 while (
Begin != End) {
1099 OutStream << *
Begin;
1103 if (llvm::isLegalUTF8Sequence(
Begin, End)) {
1104 llvm::UTF32 CodepointValue;
1105 llvm::UTF32 *CpPtr = &CodepointValue;
1106 const unsigned char *CodepointBegin =
Begin;
1107 const unsigned char *CodepointEnd =
1109 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1110 &
Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1113 llvm::conversionOK == Res &&
1114 "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1115 assert(
Begin == CodepointEnd &&
1116 "we must be further along in the string now");
1117 if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1118 llvm::sys::unicode::isFormatting(CodepointValue)) {
1119 OutStr.append(CodepointBegin, CodepointEnd);
1123 OutStream <<
"<U+" << llvm::format_hex_no_prefix(CodepointValue, 4,
true)
1128 OutStream <<
"<" << llvm::format_hex_no_prefix(*
Begin, 2,
true) <<
">";
1138 if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) ==
"%0" &&
1156 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
1160 while (DiagStr != DiagEnd) {
1161 if (DiagStr[0] !=
'%') {
1163 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
1164 OutStr.append(DiagStr, StrEnd);
1168 OutStr.push_back(DiagStr[1]);
1181 const char *Modifier =
nullptr, *Argument =
nullptr;
1182 unsigned ModifierLen = 0, ArgumentLen = 0;
1187 while (DiagStr[0] ==
'-' || (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
1189 ModifierLen = DiagStr - Modifier;
1192 if (DiagStr[0] ==
'{') {
1197 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
1198 ArgumentLen = DiagStr - Argument;
1203 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
1204 unsigned ArgNo = *DiagStr++ -
'0';
1207 unsigned ArgNo2 = ArgNo;
1210 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
1211 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
1212 "Invalid format for diff modifier");
1214 ArgNo2 = *DiagStr++ -
'0';
1225 const char *ArgumentEnd = Argument + ArgumentLen;
1228 "Found too many '|'s in a %diff modifier!");
1230 const char *SecondDollar =
ScanFormat(FirstDollar + 1,
Pipe,
'$');
1231 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo)};
1232 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2)};
1246 StringRef S = [&]() -> StringRef {
1251 return SZ ? SZ :
"(null)";
1253 bool Quoted =
false;
1254 if (
ModifierIs(Modifier, ModifierLen,
"quoted")) {
1256 OutStr.push_back(
'\'');
1258 assert(ModifierLen == 0 &&
"unknown modifier for string");
1262 OutStr.push_back(
'\'');
1269 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1272 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1274 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1277 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1279 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1282 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1283 llvm::raw_svector_ostream(OutStr) << Val;
1290 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1292 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1294 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1297 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1299 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1302 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1303 llvm::raw_svector_ostream(OutStr) << Val;
1310 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
1312 llvm::raw_svector_ostream Out(OutStr);
1315 Out <<
'\'' << S <<
'\'';
1324 Out <<
'<' << S <<
'>';
1332 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1336 const char *S =
"(null)";
1337 OutStr.append(S, S + strlen(S));
1341 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->
getName() <<
'\'';
1355 StringRef(Modifier, ModifierLen),
1356 StringRef(Argument, ArgumentLen),
1357 FormattedArgs, OutStr, QualTypeVals);
1369 const char *ArgumentEnd = Argument + ArgumentLen;
1378 StringRef(Modifier, ModifierLen),
1379 StringRef(Argument, ArgumentLen),
1380 FormattedArgs,
Tree, QualTypeVals);
1382 if (!
Tree.empty()) {
1390 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
1391 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
1400 StringRef(Modifier, ModifierLen),
1401 StringRef(Argument, ArgumentLen),
1402 FormattedArgs, OutStr, QualTypeVals);
1404 FormattedArgs.push_back(
1413 StringRef(Modifier, ModifierLen),
1414 StringRef(Argument, ArgumentLen),
1415 FormattedArgs, OutStr, QualTypeVals);
1417 FormattedArgs.push_back(
1432 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
1434 FormattedArgs.push_back(
1440 OutStr.append(
Tree.begin(),
Tree.end());
1445 : ID(ID), Level(Level), Message(Message) {}
1449 : ID(Info.getID()), Level(Level) {
1452 "Valid source location without setting a source manager for diagnostic");
1457 this->Message.assign(Message.begin(), Message.end());
1466 : ID(ID), Level(Level),
Loc(
Loc), Message(Message),
1467 Ranges(Ranges.begin(), Ranges.end()),
1468 FixIts(FixIts.begin(), FixIts.end()) {}
1484void IgnoringDiagConsumer::anchor() {}
1490 Target.HandleDiagnostic(DiagLevel, Info);
1499 return Target.IncludeInDiagnosticCounts();
1503 for (
unsigned I = 0; I != NumCached; ++I)
1504 FreeList[I] = Cached + I;
1505 NumFreeListEntries = NumCached;
1511 assert((NumFreeListEntries == NumCached ||
1512 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1513 "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.
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.
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...
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group)
Get the diagnostic option with the closest edit distance to the given group name.
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)
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.
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.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
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.
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
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
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.
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.
DiagnosticStorage * DiagStorage
void AddString(StringRef V) const
Flavor
Flavors of diagnostics we can emit.
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
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 '!' or '', and returns NULL for literal and...
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY bool isPrintable(unsigned char c)
Return true if this character is an ASCII printable character; that is, a character that should take ...
std::pair< FileID, unsigned > FileIDAndOffset
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
@ 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',...
std::pair< NullabilityKind, bool > DiagNullabilityKind
A nullability kind paired with a bit indicating whether it used a context-sensitive keyword.
LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
__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