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 auto Range = Files.equal_range(ID);
224 return &
Range.first->second;
225 auto &F = Files.insert(
Range.first, std::make_pair(ID,
File()))->second;
231 F.Parent = getFile(SrcMgr, Decomp.first);
232 F.ParentOffset = Decomp.second;
233 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
242 F.StateTransitions.push_back({FirstDiagState, 0});
247void DiagnosticsEngine::DiagStateMap::dump(SourceManager &SrcMgr,
248 StringRef DiagName)
const {
249 llvm::errs() <<
"diagnostic state at ";
250 CurDiagStateLoc.print(llvm::errs(), SrcMgr);
251 llvm::errs() <<
": " << CurDiagState <<
"\n";
253 for (
auto &F : Files) {
257 bool PrintedOuterHeading =
false;
258 auto PrintOuterHeading = [&] {
259 if (PrintedOuterHeading)
261 PrintedOuterHeading =
true;
263 llvm::errs() <<
"File " << &
File <<
" <FileID " <<
ID.getHashValue()
266 if (F.second.Parent) {
268 assert(
File.ParentOffset == Decomp.second);
269 llvm::errs() <<
" parent " <<
File.Parent <<
" <FileID "
270 << Decomp.first.getHashValue() <<
"> ";
273 .
print(llvm::errs(), SrcMgr);
275 if (
File.HasLocalTransitions)
276 llvm::errs() <<
" has_local_transitions";
277 llvm::errs() <<
"\n";
280 if (DiagName.empty())
283 for (DiagStatePoint &Transition :
File.StateTransitions) {
284 bool PrintedInnerHeading =
false;
285 auto PrintInnerHeading = [&] {
286 if (PrintedInnerHeading)
288 PrintedInnerHeading =
true;
294 .
print(llvm::errs(), SrcMgr);
295 llvm::errs() <<
": state " << Transition.State <<
":\n";
298 if (DiagName.empty())
301 for (
auto &Mapping : *Transition.State) {
305 if (!DiagName.empty() && DiagName != Option)
311 llvm::errs() <<
"<unknown " << Mapping.first <<
">";
313 llvm::errs() << Option;
314 llvm::errs() <<
": ";
316 switch (Mapping.second.getSeverity()) {
318 llvm::errs() <<
"ignored";
321 llvm::errs() <<
"remark";
324 llvm::errs() <<
"warning";
327 llvm::errs() <<
"error";
330 llvm::errs() <<
"fatal";
334 if (!Mapping.second.isUser())
335 llvm::errs() <<
" default";
336 if (Mapping.second.isPragma())
337 llvm::errs() <<
" pragma";
338 if (Mapping.second.hasNoWarningAsError())
339 llvm::errs() <<
" no-error";
340 if (Mapping.second.hasNoErrorAsFatal())
341 llvm::errs() <<
" no-fatal";
342 if (Mapping.second.wasUpgradedFromWarning())
343 llvm::errs() <<
" overruled";
344 llvm::errs() <<
"\n";
350void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
351 SourceLocation Loc) {
352 assert(Loc.
isValid() &&
"Adding invalid loc point");
353 DiagStatesByLoc.append(*SourceMgr, Loc, State);
358 assert((Diags->isWarningOrExtension(
Diag) ||
360 "Cannot map errors into warnings!");
361 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
365 bool WasUpgradedFromWarning =
false;
371 WasUpgradedFromWarning =
true;
384 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
385 DiagStatesByLoc.getCurDiagState()) {
390 DiagStatesByLoc.getCurDiagState()->setMapping(
Diag, Mapping);
397 DiagStates.push_back(*GetCurDiagState());
398 DiagStates.back().setMapping(
Diag, Mapping);
399 PushDiagStatePoint(&DiagStates.back(), L);
407 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
410 Diags->setGroupSeverity(Group, Map);
494 std::vector<diag::kind> AllDiags;
499 if (Diags->isWarningOrExtension(
Diag))
506class WarningsSpecialCaseList :
public llvm::SpecialCaseList {
508 static std::unique_ptr<WarningsSpecialCaseList>
509 create(
const llvm::MemoryBuffer &Input, std::string &Err);
521 llvm::DenseMap<diag::kind, const Section *> DiagToSection;
525std::unique_ptr<WarningsSpecialCaseList>
526WarningsSpecialCaseList::create(
const llvm::MemoryBuffer &Input,
528 auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
529 if (!WarningSuppressionList->createInternal(&Input, Err))
531 return WarningSuppressionList;
536 for (
const auto &SectionEntry : sections()) {
537 StringRef DiagGroup = SectionEntry.name();
538 if (DiagGroup ==
"*") {
544 SmallVector<diag::kind> GroupDiags;
545 if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
546 WarningFlavor, DiagGroup, GroupDiags)) {
547 StringRef Suggestion =
549 Diags.Report(diag::warn_unknown_diag_option)
550 <<
static_cast<unsigned>(WarningFlavor) << DiagGroup
551 << !Suggestion.empty() << Suggestion;
557 DiagToSection[
Diag] = &SectionEntry;
563 auto WarningSuppressionList = WarningsSpecialCaseList::create(Input,
Error);
564 if (!WarningSuppressionList) {
567 Report(diag::err_drv_malformed_warning_suppression_mapping)
568 << Input.getBufferIdentifier() <<
Error;
571 WarningSuppressionList->processSections(*
this);
572 DiagSuppressionMapping =
573 [WarningSuppressionList(std::move(WarningSuppressionList))](
575 return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc,
SM);
579bool WarningsSpecialCaseList::isDiagSuppressed(
diag::kind DiagId,
585 const Section *DiagSection = DiagToSection.lookup(DiagId);
589 StringRef F = llvm::sys::path::remove_leading_dotslash(PLoc.
getFilename());
591 unsigned LastSup = DiagSection->getLastMatch(
"src", F,
"");
595 unsigned LastEmit = DiagSection->getLastMatch(
"src", F,
"emit");
596 return LastSup > LastEmit;
614 assert(Client &&
"DiagnosticConsumer not set!");
622 assert(DiagLevel !=
Ignored &&
"Cannot emit ignored diagnostics!");
624 "Trap diagnostics should not be consumed by the DiagnosticsEngine");
637 assert(
getClient() &&
"DiagnosticClient not set!");
640 unsigned DiagID = Info.
getID();
645 if (DiagLevel >=
Error) {
646 ++TrapNumErrorsOccurred;
647 if (Diags->isUnrecoverable(DiagID))
648 ++TrapNumUnrecoverableErrorsOccurred;
651 if (SuppressAllDiagnostics)
654 if (DiagLevel !=
Note) {
659 if (LastDiagLevel ==
Fatal)
660 FatalErrorOccurred =
true;
662 LastDiagLevel = DiagLevel;
667 if (FatalErrorOccurred) {
668 if (DiagLevel >=
Error && Client->IncludeInDiagnosticCounts())
679 if (DiagLevel >=
Error) {
680 if (Diags->isUnrecoverable(DiagID))
681 UnrecoverableErrorOccurred =
true;
684 if (Diags->isDefaultMappingAsError(DiagID))
685 UncompilableErrorOccurred =
true;
687 ErrorOccurred =
true;
688 if (Client->IncludeInDiagnosticCounts())
693 if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel ==
Error) {
694 Report(diag::fatal_too_many_errors);
701 if (Info.
getID() == diag::fatal_too_many_errors)
702 FatalErrorOccurred =
true;
711 assert(
getClient() &&
"DiagnosticClient not set!");
721 Emitted = DiagLevel !=
Ignored;
727 Emitted = ProcessDiag(DB);
736 DiagLoc(DiagLoc), DiagID(DiagID), IsActive(
true) {
737 assert(DiagObj &&
"DiagnosticBuilder requires a valid DiagnosticsEngine!");
740DiagnosticBuilder::DiagnosticBuilder(
const DiagnosticBuilder &D)
744 FlagValue = D.FlagValue;
749 IsActive = D.IsActive;
750 IsForceEmit = D.IsForceEmit;
756 : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
757 FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.
getStorage()) {
762 StringRef StoredDiagMessage)
763 : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
764 StoredDiagMessage(StoredDiagMessage) {}
780template <std::
size_t StrLen>
781static bool ModifierIs(
const char *Modifier,
unsigned ModifierLen,
782 const char (&Str)[StrLen]) {
783 return StrLen - 1 == ModifierLen && memcmp(Modifier, Str, StrLen - 1) == 0;
791 for (; I != E; ++I) {
792 if (Depth == 0 && *I ==
Target)
794 if (Depth != 0 && *I ==
'}')
806 for (I++; I != E && !
isDigit(*I) && *I !=
'{'; I++)
824 const char *Argument,
unsigned ArgumentLen,
826 const char *ArgumentEnd = Argument + ArgumentLen;
830 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
831 assert(NextVal != ArgumentEnd &&
832 "Value for integer select modifier was"
833 " larger than the number of options in the diagnostic string!");
834 Argument = NextVal + 1;
839 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
851 OutStr.push_back(
's');
860 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
862 llvm::raw_svector_ostream Out(OutStr);
866 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
877 static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
878 {{1'000'000'000'000L,
'T'},
879 {1'000'000'000L,
'G'},
883 llvm::raw_svector_ostream Out(OutStr);
888 for (
const auto &[UnitSize, UnitSign] : Units) {
889 if (ValNo >= UnitSize) {
890 Out << llvm::format(
"%0.2f%c", ValNo /
static_cast<double>(UnitSize),
902 while (Start != End && *Start >=
'0' && *Start <=
'9') {
919 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
922 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
924 return Low <= Val && Val <= High;
939 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
941 unsigned ValMod = ValNo % Arg;
945 assert((
C ==
'[' || (
C >=
'0' &&
C <=
'9')) &&
946 "Bad plural expression syntax: unexpected character");
953 Start = std::find(Start, End,
',');
995 const char *Argument,
unsigned ArgumentLen,
997 const char *ArgumentEnd = Argument + ArgumentLen;
999 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
1000 const char *ExprEnd = Argument;
1001 while (*ExprEnd !=
':') {
1002 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
1006 Argument = ExprEnd + 1;
1007 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
1014 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
1023 case tok::identifier:
1024 return "identifier";
1034 if (StoredDiagMessage.has_value()) {
1035 OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
1048 bool ForCodepoint) {
1049 OutStr.reserve(OutStr.size() + Str.size());
1050 auto *Begin =
reinterpret_cast<const unsigned char *
>(Str.data());
1051 llvm::raw_svector_ostream OutStream(OutStr);
1052 unsigned Size = Str.size();
1053 const unsigned char *End = Begin + Size;
1055 unsigned Size = llvm::getUTF8SequenceSize(Begin, End);
1057 Size = llvm::findMaximalSubpartOfIllFormedUTF8Sequence(Begin, End);
1060 while (Begin != End) {
1062 OutStream << *Begin;
1066 if (ForCodepoint && *Begin < 0x80) {
1068 OutStream <<
"'" << *Begin <<
"'";
1073 if (llvm::isLegalUTF8Sequence(Begin, End)) {
1074 llvm::UTF32 CodepointValue;
1075 llvm::UTF32 *CpPtr = &CodepointValue;
1076 const unsigned char *CodepointBegin = Begin;
1077 const unsigned char *CodepointEnd =
1078 Begin + llvm::getNumBytesForUTF8(*Begin);
1079 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1080 &Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1083 llvm::conversionOK == Res &&
1084 "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1085 assert(Begin == CodepointEnd &&
1086 "we must be further along in the string now");
1088 if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1089 (!ForCodepoint && llvm::sys::unicode::isFormatting(CodepointValue))) {
1090 OutStream << (ForCodepoint ?
"'" :
"")
1091 << StringRef(
reinterpret_cast<const char *
>(CodepointBegin),
1092 std::distance(CodepointBegin, CodepointEnd))
1093 << (ForCodepoint ?
"' " :
"");
1098 OutStream << (ForCodepoint ?
"" :
"<") <<
"U+"
1099 << llvm::format_hex_no_prefix(CodepointValue, 4,
true)
1100 << (ForCodepoint ?
"" :
">");
1104 OutStream <<
"<0x" << llvm::format_hex_no_prefix(*Begin, 2,
true) <<
">";
1137 if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) ==
"%0" &&
1155 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
1159 while (DiagStr != DiagEnd) {
1160 if (DiagStr[0] !=
'%') {
1162 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
1163 OutStr.append(DiagStr, StrEnd);
1167 OutStr.push_back(DiagStr[1]);
1180 const char *Modifier =
nullptr, *Argument =
nullptr;
1181 unsigned ModifierLen = 0, ArgumentLen = 0;
1186 while (DiagStr[0] ==
'-' || (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
1188 ModifierLen = DiagStr - Modifier;
1191 if (DiagStr[0] ==
'{') {
1196 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
1197 ArgumentLen = DiagStr - Argument;
1202 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
1203 unsigned ArgNo = *DiagStr++ -
'0';
1206 unsigned ArgNo2 = ArgNo;
1209 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
1210 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
1211 "Invalid format for diff modifier");
1213 ArgNo2 = *DiagStr++ -
'0';
1224 const char *ArgumentEnd = Argument + ArgumentLen;
1227 "Found too many '|'s in a %diff modifier!");
1229 const char *SecondDollar =
ScanFormat(FirstDollar + 1,
Pipe,
'$');
1230 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo)};
1231 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2)};
1245 StringRef S = [&]() -> StringRef {
1250 return SZ ? SZ :
"(null)";
1252 bool Quoted =
false;
1253 if (
ModifierIs(Modifier, ModifierLen,
"quoted")) {
1255 OutStr.push_back(
'\'');
1257 assert(ModifierLen == 0 &&
"unknown modifier for string");
1261 OutStr.push_back(
'\'');
1268 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1271 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1273 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1276 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1278 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1281 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1282 llvm::raw_svector_ostream(OutStr) << Val;
1289 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1291 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1293 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1296 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1298 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1301 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1302 llvm::raw_svector_ostream(OutStr) << Val;
1309 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
1311 llvm::raw_svector_ostream Out(OutStr);
1314 Out <<
'\'' << S <<
'\'';
1323 Out <<
'<' << S <<
'>';
1331 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1335 const char *S =
"(null)";
1336 OutStr.append(S, S + strlen(S));
1340 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->
getName() <<
'\'';
1354 StringRef(Modifier, ModifierLen),
1355 StringRef(Argument, ArgumentLen),
1356 FormattedArgs, OutStr, QualTypeVals);
1368 const char *ArgumentEnd = Argument + ArgumentLen;
1373 if (
getDiags()->PrintTemplateTree && Tree.empty()) {
1377 StringRef(Modifier, ModifierLen),
1378 StringRef(Argument, ArgumentLen),
1379 FormattedArgs, Tree, QualTypeVals);
1381 if (!Tree.empty()) {
1389 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
1390 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
1399 StringRef(Modifier, ModifierLen),
1400 StringRef(Argument, ArgumentLen),
1401 FormattedArgs, OutStr, QualTypeVals);
1403 FormattedArgs.push_back(
1412 StringRef(Modifier, ModifierLen),
1413 StringRef(Argument, ArgumentLen),
1414 FormattedArgs, OutStr, QualTypeVals);
1416 FormattedArgs.push_back(
1431 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
1433 FormattedArgs.push_back(
1439 OutStr.append(Tree.begin(), Tree.end());
1444 : ID(ID), Level(Level), Message(Message) {}
1448 : ID(Info.
getID()), Level(Level) {
1451 "Valid source location without setting a source manager for diagnostic");
1456 this->Message.assign(Message.begin(), Message.end());
1465 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1466 Ranges(Ranges.begin(), Ranges.end()),
1467 FixIts(FixIts.begin(), FixIts.end()) {}
1483void IgnoringDiagConsumer::anchor() {}
1489 Target.HandleDiagnostic(DiagLevel, Info);
1498 return Target.IncludeInDiagnosticCounts();
1502 for (
unsigned I = 0; I != NumCached; ++I)
1503 FreeList[I] = Cached + I;
1504 NumFreeListEntries = NumCached;
1510 assert((NumFreeListEntries == NumCached ||
1511 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1512 "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)
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.
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
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.
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 '!
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
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.
__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