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);
161 return Result.first->second;
164void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
165 assert(Files.empty() &&
"not first");
166 FirstDiagState = CurDiagState = State;
167 CurDiagStateLoc = SourceLocation();
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,
197 SourceLocation Loc)
const {
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,
350 SourceLocation Loc) {
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);
520 llvm::DenseMap<diag::kind, const Section *> DiagToSection;
524std::unique_ptr<WarningsSpecialCaseList>
525WarningsSpecialCaseList::create(
const llvm::MemoryBuffer &Input,
527 auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
528 if (!WarningSuppressionList->createInternal(&Input, Err))
530 return WarningSuppressionList;
535 for (
const auto &SectionEntry : sections()) {
536 StringRef DiagGroup = SectionEntry.name();
537 if (DiagGroup ==
"*") {
543 SmallVector<diag::kind> GroupDiags;
544 if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
545 WarningFlavor, DiagGroup, GroupDiags)) {
546 StringRef Suggestion =
548 Diags.Report(diag::warn_unknown_diag_option)
549 <<
static_cast<unsigned>(WarningFlavor) << DiagGroup
550 << !Suggestion.empty() << Suggestion;
556 DiagToSection[
Diag] = &SectionEntry;
562 auto WarningSuppressionList = WarningsSpecialCaseList::create(Input,
Error);
563 if (!WarningSuppressionList) {
566 Report(diag::err_drv_malformed_warning_suppression_mapping)
567 << Input.getBufferIdentifier() <<
Error;
570 WarningSuppressionList->processSections(*
this);
571 DiagSuppressionMapping =
572 [WarningSuppressionList(std::move(WarningSuppressionList))](
574 return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc,
SM);
578bool WarningsSpecialCaseList::isDiagSuppressed(
diag::kind DiagId,
584 const Section *DiagSection = DiagToSection.lookup(DiagId);
588 StringRef F = llvm::sys::path::remove_leading_dotslash(PLoc.
getFilename());
590 unsigned LastSup = DiagSection->getLastMatch(
"src", F,
"");
594 unsigned LastEmit = DiagSection->getLastMatch(
"src", F,
"emit");
595 return LastSup > LastEmit;
613 assert(Client &&
"DiagnosticConsumer not set!");
621 assert(DiagLevel !=
Ignored &&
"Cannot emit ignored diagnostics!");
623 "Trap diagnostics should not be consumed by the DiagnosticsEngine");
636 assert(
getClient() &&
"DiagnosticClient not set!");
639 unsigned DiagID = Info.
getID();
644 if (DiagLevel >=
Error) {
645 ++TrapNumErrorsOccurred;
646 if (Diags->isUnrecoverable(DiagID))
647 ++TrapNumUnrecoverableErrorsOccurred;
650 if (SuppressAllDiagnostics)
653 if (DiagLevel !=
Note) {
658 if (LastDiagLevel ==
Fatal)
659 FatalErrorOccurred =
true;
661 LastDiagLevel = DiagLevel;
666 if (FatalErrorOccurred) {
667 if (DiagLevel >=
Error && Client->IncludeInDiagnosticCounts())
678 if (DiagLevel >=
Error) {
679 if (Diags->isUnrecoverable(DiagID))
680 UnrecoverableErrorOccurred =
true;
683 if (Diags->isDefaultMappingAsError(DiagID))
684 UncompilableErrorOccurred =
true;
686 ErrorOccurred =
true;
687 if (Client->IncludeInDiagnosticCounts())
692 if (ErrorLimit && NumErrors > ErrorLimit && DiagLevel ==
Error) {
693 Report(diag::fatal_too_many_errors);
700 if (Info.
getID() == diag::fatal_too_many_errors)
701 FatalErrorOccurred =
true;
710 assert(
getClient() &&
"DiagnosticClient not set!");
720 Emitted = DiagLevel !=
Ignored;
726 Emitted = ProcessDiag(DB);
735 DiagLoc(DiagLoc), DiagID(DiagID), IsActive(
true) {
736 assert(DiagObj &&
"DiagnosticBuilder requires a valid DiagnosticsEngine!");
739DiagnosticBuilder::DiagnosticBuilder(
const DiagnosticBuilder &D)
743 FlagValue = D.FlagValue;
748 IsActive = D.IsActive;
749 IsForceEmit = D.IsForceEmit;
755 : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
756 FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.
getStorage()) {
761 StringRef StoredDiagMessage)
762 : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
763 StoredDiagMessage(StoredDiagMessage) {}
779template <std::
size_t StrLen>
780static bool ModifierIs(
const char *Modifier,
unsigned ModifierLen,
781 const char (&Str)[StrLen]) {
782 return StrLen - 1 == ModifierLen && memcmp(Modifier, Str, StrLen - 1) == 0;
790 for (; I != E; ++I) {
791 if (Depth == 0 && *I ==
Target)
793 if (Depth != 0 && *I ==
'}')
805 for (I++; I != E && !
isDigit(*I) && *I !=
'{'; I++)
823 const char *Argument,
unsigned ArgumentLen,
825 const char *ArgumentEnd = Argument + ArgumentLen;
829 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
830 assert(NextVal != ArgumentEnd &&
831 "Value for integer select modifier was"
832 " larger than the number of options in the diagnostic string!");
833 Argument = NextVal + 1;
838 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
850 OutStr.push_back(
's');
859 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
861 llvm::raw_svector_ostream Out(OutStr);
865 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
876 static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
877 {{1'000'000'000'000L,
'T'},
878 {1'000'000'000L,
'G'},
882 llvm::raw_svector_ostream Out(OutStr);
887 for (
const auto &[UnitSize, UnitSign] : Units) {
888 if (ValNo >= UnitSize) {
889 Out << llvm::format(
"%0.2f%c", ValNo /
static_cast<double>(UnitSize),
901 while (Start != End && *Start >=
'0' && *Start <=
'9') {
918 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
921 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
923 return Low <= Val && Val <= High;
938 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
940 unsigned ValMod = ValNo % Arg;
944 assert((
C ==
'[' || (
C >=
'0' &&
C <=
'9')) &&
945 "Bad plural expression syntax: unexpected character");
952 Start = std::find(Start, End,
',');
994 const char *Argument,
unsigned ArgumentLen,
996 const char *ArgumentEnd = Argument + ArgumentLen;
998 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
999 const char *ExprEnd = Argument;
1000 while (*ExprEnd !=
':') {
1001 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
1005 Argument = ExprEnd + 1;
1006 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
1013 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
1022 case tok::identifier:
1023 return "identifier";
1033 if (StoredDiagMessage.has_value()) {
1034 OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
1047 OutStr.reserve(OutStr.size() + Str.size());
1048 auto *Begin =
reinterpret_cast<const unsigned char *
>(Str.data());
1049 llvm::raw_svector_ostream OutStream(OutStr);
1050 const unsigned char *End = Begin + Str.size();
1051 while (Begin != End) {
1054 OutStream << *Begin;
1058 if (llvm::isLegalUTF8Sequence(Begin, End)) {
1059 llvm::UTF32 CodepointValue;
1060 llvm::UTF32 *CpPtr = &CodepointValue;
1061 const unsigned char *CodepointBegin = Begin;
1062 const unsigned char *CodepointEnd =
1063 Begin + llvm::getNumBytesForUTF8(*Begin);
1064 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1065 &Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1068 llvm::conversionOK == Res &&
1069 "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1070 assert(Begin == CodepointEnd &&
1071 "we must be further along in the string now");
1072 if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1073 llvm::sys::unicode::isFormatting(CodepointValue)) {
1074 OutStr.append(CodepointBegin, CodepointEnd);
1078 OutStream <<
"<U+" << llvm::format_hex_no_prefix(CodepointValue, 4,
true)
1083 OutStream <<
"<" << llvm::format_hex_no_prefix(*Begin, 2,
true) <<
">";
1093 if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) ==
"%0" &&
1111 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
1115 while (DiagStr != DiagEnd) {
1116 if (DiagStr[0] !=
'%') {
1118 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
1119 OutStr.append(DiagStr, StrEnd);
1123 OutStr.push_back(DiagStr[1]);
1136 const char *Modifier =
nullptr, *Argument =
nullptr;
1137 unsigned ModifierLen = 0, ArgumentLen = 0;
1142 while (DiagStr[0] ==
'-' || (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
1144 ModifierLen = DiagStr - Modifier;
1147 if (DiagStr[0] ==
'{') {
1152 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
1153 ArgumentLen = DiagStr - Argument;
1158 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
1159 unsigned ArgNo = *DiagStr++ -
'0';
1162 unsigned ArgNo2 = ArgNo;
1165 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
1166 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
1167 "Invalid format for diff modifier");
1169 ArgNo2 = *DiagStr++ -
'0';
1180 const char *ArgumentEnd = Argument + ArgumentLen;
1183 "Found too many '|'s in a %diff modifier!");
1185 const char *SecondDollar =
ScanFormat(FirstDollar + 1,
Pipe,
'$');
1186 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo)};
1187 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2)};
1201 StringRef S = [&]() -> StringRef {
1206 return SZ ? SZ :
"(null)";
1208 bool Quoted =
false;
1209 if (
ModifierIs(Modifier, ModifierLen,
"quoted")) {
1211 OutStr.push_back(
'\'');
1213 assert(ModifierLen == 0 &&
"unknown modifier for string");
1217 OutStr.push_back(
'\'');
1224 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1227 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1229 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1232 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1234 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1237 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1238 llvm::raw_svector_ostream(OutStr) << Val;
1245 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1247 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1249 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1252 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1254 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1257 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1258 llvm::raw_svector_ostream(OutStr) << Val;
1265 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
1267 llvm::raw_svector_ostream Out(OutStr);
1270 Out <<
'\'' << S <<
'\'';
1279 Out <<
'<' << S <<
'>';
1287 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1291 const char *S =
"(null)";
1292 OutStr.append(S, S + strlen(S));
1296 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->
getName() <<
'\'';
1310 StringRef(Modifier, ModifierLen),
1311 StringRef(Argument, ArgumentLen),
1312 FormattedArgs, OutStr, QualTypeVals);
1324 const char *ArgumentEnd = Argument + ArgumentLen;
1329 if (
getDiags()->PrintTemplateTree && Tree.empty()) {
1333 StringRef(Modifier, ModifierLen),
1334 StringRef(Argument, ArgumentLen),
1335 FormattedArgs, Tree, QualTypeVals);
1337 if (!Tree.empty()) {
1345 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
1346 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
1355 StringRef(Modifier, ModifierLen),
1356 StringRef(Argument, ArgumentLen),
1357 FormattedArgs, OutStr, QualTypeVals);
1359 FormattedArgs.push_back(
1368 StringRef(Modifier, ModifierLen),
1369 StringRef(Argument, ArgumentLen),
1370 FormattedArgs, OutStr, QualTypeVals);
1372 FormattedArgs.push_back(
1387 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
1389 FormattedArgs.push_back(
1395 OutStr.append(Tree.begin(), Tree.end());
1400 : ID(ID), Level(Level), Message(Message) {}
1404 : ID(Info.
getID()), Level(Level) {
1407 "Valid source location without setting a source manager for diagnostic");
1412 this->Message.assign(Message.begin(), Message.end());
1421 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1422 Ranges(Ranges.begin(), Ranges.end()),
1423 FixIts(FixIts.begin(), FixIts.end()) {}
1439void IgnoringDiagConsumer::anchor() {}
1445 Target.HandleDiagnostic(DiagLevel, Info);
1454 return Target.IncludeInDiagnosticCounts();
1458 for (
unsigned I = 0; I != NumCached; ++I)
1459 FreeList[I] = Cached + I;
1460 NumFreeListEntries = NumCached;
1466 assert((NumFreeListEntries == NumCached ||
1467 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1468 "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.
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',...
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