26#include "llvm/ADT/IntrusiveRefCntPtr.h"
27#include "llvm/ADT/SmallString.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/ADT/StringExtras.h"
30#include "llvm/ADT/StringMap.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/Support/ConvertUTF.h"
33#include "llvm/Support/CrashRecoveryContext.h"
34#include "llvm/Support/Error.h"
35#include "llvm/Support/MemoryBuffer.h"
36#include "llvm/Support/SpecialCaseList.h"
37#include "llvm/Support/Unicode.h"
38#include "llvm/Support/VirtualFileSystem.h"
39#include "llvm/Support/raw_ostream.h"
71 StringRef Modifier, StringRef Argument,
76 StringRef Str =
"<can't format argument>";
77 Output.append(Str.begin(), Str.end());
84 : Diags(
std::move(diags)), DiagOpts(
std::move(DiagOpts)) {
98 DiagStatesByLoc.dump(*SourceMgr);
102 DiagStatesByLoc.dump(*SourceMgr, DiagName);
106 bool ShouldOwnClient) {
107 Owner.reset(ShouldOwnClient ? client :
nullptr);
112 DiagStateOnPushStack.push_back(GetCurDiagState());
116 if (DiagStateOnPushStack.empty())
119 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
121 PushDiagStatePoint(DiagStateOnPushStack.back(),
Loc);
123 DiagStateOnPushStack.pop_back();
128 ErrorOccurred =
false;
129 UncompilableErrorOccurred =
false;
130 FatalErrorOccurred =
false;
131 UnrecoverableErrorOccurred =
false;
135 TrapNumErrorsOccurred = 0;
136 TrapNumUnrecoverableErrorsOccurred = 0;
143 DiagStatesByLoc.clear();
144 DiagStateOnPushStack.clear();
148 DiagStates.emplace_back();
149 DiagStatesByLoc.appendFirst(&DiagStates.back());
155 std::pair<iterator, bool>
Result =
162 return Result.first->second;
165void DiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) {
166 assert(Files.empty() &&
"not first");
167 FirstDiagState = CurDiagState = State;
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,
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)
return;
260 PrintedOuterHeading =
true;
262 llvm::errs() <<
"File " << &
File <<
" <FileID " <<
ID.getHashValue()
265 if (F.second.Parent) {
266 std::pair<FileID, unsigned> Decomp =
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)
return;
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) {
303 if (!DiagName.empty() && DiagName != Option)
309 llvm::errs() <<
"<unknown " << Mapping.first <<
">";
311 llvm::errs() << Option;
312 llvm::errs() <<
": ";
314 switch (Mapping.second.getSeverity()) {
322 if (!Mapping.second.isUser())
323 llvm::errs() <<
" default";
324 if (Mapping.second.isPragma())
325 llvm::errs() <<
" pragma";
326 if (Mapping.second.hasNoWarningAsError())
327 llvm::errs() <<
" no-error";
328 if (Mapping.second.hasNoErrorAsFatal())
329 llvm::errs() <<
" no-fatal";
330 if (Mapping.second.wasUpgradedFromWarning())
331 llvm::errs() <<
" overruled";
332 llvm::errs() <<
"\n";
338void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
340 assert(
Loc.
isValid() &&
"Adding invalid loc point");
341 DiagStatesByLoc.append(*SourceMgr,
Loc, State);
347 "Can only map builtin diagnostics");
348 assert((Diags->isBuiltinWarningOrExtension(
Diag) ||
350 "Cannot map errors into warnings!");
351 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
355 bool WasUpgradedFromWarning =
false;
361 WasUpgradedFromWarning =
true;
374 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
375 DiagStatesByLoc.getCurDiagState()) {
380 DiagStatesByLoc.getCurDiagState()->setMapping(
Diag, Mapping);
387 DiagStates.push_back(*GetCurDiagState());
388 DiagStates.back().setMapping(
Diag, Mapping);
389 PushDiagStatePoint(&DiagStates.back(), L);
397 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
480 std::vector<diag::kind> AllDiags;
485 if (Diags->isBuiltinWarningOrExtension(
Diag))
492class WarningsSpecialCaseList :
public llvm::SpecialCaseList {
494 static std::unique_ptr<WarningsSpecialCaseList>
495 create(
const llvm::MemoryBuffer &Input, std::string &Err);
510 bool globsMatches(
const llvm::StringMap<Matcher> &CategoriesToMatchers,
511 StringRef FilePath)
const;
513 llvm::DenseMap<diag::kind, const Section *> DiagToSection;
517std::unique_ptr<WarningsSpecialCaseList>
518WarningsSpecialCaseList::create(
const llvm::MemoryBuffer &Input,
520 auto WarningSuppressionList = std::make_unique<WarningsSpecialCaseList>();
521 if (!WarningSuppressionList->createInternal(&Input, Err))
523 return WarningSuppressionList;
532 std::vector<std::pair<unsigned, const llvm::StringMapEntry<Section> *>>
534 LineAndSectionEntry.reserve(Sections.size());
535 for (
const auto &Entry : Sections) {
536 StringRef DiagName = Entry.getKey();
539 const auto &DiagSectionMatcher = Entry.getValue().SectionMatcher;
540 unsigned DiagLine = DiagSectionMatcher->Globs.at(DiagName).second;
541 LineAndSectionEntry.emplace_back(DiagLine, &Entry);
543 llvm::sort(LineAndSectionEntry);
545 for (
const auto &[_, SectionEntry] : LineAndSectionEntry) {
547 StringRef DiagGroup = SectionEntry->getKey();
549 WarningFlavor, DiagGroup, GroupDiags)) {
550 StringRef Suggestion =
552 Diags.
Report(diag::warn_unknown_diag_option)
553 <<
static_cast<unsigned>(WarningFlavor) << DiagGroup
554 << !Suggestion.empty() << Suggestion;
560 DiagToSection[
Diag] = &SectionEntry->getValue();
566 auto WarningSuppressionList = WarningsSpecialCaseList::create(Input,
Error);
567 if (!WarningSuppressionList) {
570 Report(diag::err_drv_malformed_warning_suppression_mapping)
571 << Input.getBufferIdentifier() <<
Error;
574 WarningSuppressionList->processSections(*
this);
575 DiagSuppressionMapping =
576 [WarningSuppressionList(std::move(WarningSuppressionList))](
578 return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc,
SM);
582bool WarningsSpecialCaseList::isDiagSuppressed(
diag::kind DiagId,
585 const Section *DiagSection = DiagToSection.lookup(DiagId);
588 const SectionEntries &EntityTypeToCategories = DiagSection->Entries;
589 auto SrcEntriesIt = EntityTypeToCategories.find(
"src");
590 if (SrcEntriesIt == EntityTypeToCategories.end())
592 const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
593 SrcEntriesIt->getValue();
596 if (
PresumedLoc PLoc =
SM.getPresumedLoc(DiagLoc); PLoc.isValid())
598 CategoriesToMatchers,
599 llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
603bool WarningsSpecialCaseList::globsMatches(
604 const llvm::StringMap<Matcher> &CategoriesToMatchers,
605 StringRef FilePath)
const {
606 StringRef LongestMatch;
607 bool LongestIsPositive =
false;
608 for (
const auto &Entry : CategoriesToMatchers) {
609 StringRef
Category = Entry.getKey();
610 const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue();
611 bool IsPositive =
Category !=
"emit";
612 for (
const auto &[Pattern, Glob] : Matcher.Globs) {
613 if (Pattern.size() < LongestMatch.size())
615 if (!Glob.first.match(FilePath))
617 LongestMatch = Pattern;
618 LongestIsPositive = IsPositive;
621 return LongestIsPositive;
639 assert(Client &&
"DiagnosticConsumer not set!");
652 assert(
getClient() &&
"DiagnosticClient not set!");
665 Diags->EmitDiag(*
this, DB, DiagLevel);
670 Emitted = ProcessDiag(DB);
679 DiagLoc(DiagLoc), DiagID(DiagID), IsActive(
true) {
680 assert(DiagObj &&
"DiagnosticBuilder requires a valid DiagnosticsEngine!");
687 FlagValue =
D.FlagValue;
690 D.DiagStorage =
nullptr;
692 IsActive =
D.IsActive;
693 IsForceEmit =
D.IsForceEmit;
699 : DiagObj(DO), DiagLoc(DiagBuilder.DiagLoc), DiagID(DiagBuilder.DiagID),
700 FlagValue(DiagBuilder.FlagValue), DiagStorage(*DiagBuilder.
getStorage()) {
705 StringRef StoredDiagMessage)
706 : DiagObj(DO), DiagLoc(DiagLoc), DiagID(DiagID), DiagStorage(DiagStorage),
707 StoredDiagMessage(StoredDiagMessage) {}
723template <std::
size_t StrLen>
724static bool ModifierIs(
const char *Modifier,
unsigned ModifierLen,
725 const char (&Str)[StrLen]) {
726 return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0;
734 for ( ; I !=
E; ++I) {
735 if (Depth == 0 && *I ==
Target)
return I;
736 if (Depth != 0 && *I ==
'}') Depth--;
746 for (I++; I !=
E && !
isDigit(*I) && *I !=
'{'; I++) ;
762 const char *Argument,
unsigned ArgumentLen,
764 const char *ArgumentEnd = Argument+ArgumentLen;
768 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
769 assert(NextVal != ArgumentEnd &&
"Value for integer select modifier was"
770 " larger than the number of options in the diagnostic string!");
771 Argument = NextVal+1;
776 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
788 OutStr.push_back(
's');
797 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
799 llvm::raw_svector_ostream Out(OutStr);
803 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
814 static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
815 {{1'000'000'000'000L,
'T'},
816 {1'000'000'000L,
'G'},
820 llvm::raw_svector_ostream Out(OutStr);
825 for (
const auto &[UnitSize, UnitSign] : Units) {
826 if (ValNo >= UnitSize) {
827 Out << llvm::format(
"%0.2f%c", ValNo /
static_cast<double>(UnitSize),
839 while (Start != End && *Start >=
'0' && *Start <=
'9') {
856 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
859 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
861 return Low <= Val && Val <= High;
876 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
878 unsigned ValMod = ValNo % Arg;
882 assert((
C ==
'[' || (
C >=
'0' &&
C <=
'9')) &&
883 "Bad plural expression syntax: unexpected character");
890 Start = std::find(Start, End,
',');
932 const char *Argument,
unsigned ArgumentLen,
934 const char *ArgumentEnd = Argument + ArgumentLen;
936 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
937 const char *ExprEnd = Argument;
938 while (*ExprEnd !=
':') {
939 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
943 Argument = ExprEnd + 1;
944 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
951 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
960 case tok::identifier:
972 if (StoredDiagMessage.has_value()) {
973 OutStr.append(StoredDiagMessage->begin(), StoredDiagMessage->end());
987 OutStr.reserve(OutStr.size() + Str.size());
988 auto *
Begin =
reinterpret_cast<const unsigned char *
>(Str.data());
989 llvm::raw_svector_ostream OutStream(OutStr);
990 const unsigned char *End =
Begin + Str.size();
991 while (
Begin != End) {
998 if (llvm::isLegalUTF8Sequence(
Begin, End)) {
999 llvm::UTF32 CodepointValue;
1000 llvm::UTF32 *CpPtr = &CodepointValue;
1001 const unsigned char *CodepointBegin =
Begin;
1002 const unsigned char *CodepointEnd =
1004 llvm::ConversionResult Res = llvm::ConvertUTF8toUTF32(
1005 &
Begin, CodepointEnd, &CpPtr, CpPtr + 1, llvm::strictConversion);
1008 llvm::conversionOK == Res &&
1009 "the sequence is legal UTF-8 but we couldn't convert it to UTF-32");
1010 assert(
Begin == CodepointEnd &&
1011 "we must be further along in the string now");
1012 if (llvm::sys::unicode::isPrintable(CodepointValue) ||
1013 llvm::sys::unicode::isFormatting(CodepointValue)) {
1014 OutStr.append(CodepointBegin, CodepointEnd);
1018 OutStream <<
"<U+" << llvm::format_hex_no_prefix(CodepointValue, 4,
true)
1023 OutStream <<
"<" << llvm::format_hex_no_prefix(*
Begin, 2,
true) <<
">";
1034 if (DiagEnd - DiagStr == 2 && StringRef(DiagStr, DiagEnd - DiagStr) ==
"%0" &&
1052 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
1056 while (DiagStr != DiagEnd) {
1057 if (DiagStr[0] !=
'%') {
1059 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
1060 OutStr.append(DiagStr, StrEnd);
1064 OutStr.push_back(DiagStr[1]);
1077 const char *Modifier =
nullptr, *Argument =
nullptr;
1078 unsigned ModifierLen = 0, ArgumentLen = 0;
1083 while (DiagStr[0] ==
'-' ||
1084 (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
1086 ModifierLen = DiagStr-Modifier;
1089 if (DiagStr[0] ==
'{') {
1094 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
1095 ArgumentLen = DiagStr-Argument;
1100 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
1101 unsigned ArgNo = *DiagStr++ -
'0';
1104 unsigned ArgNo2 = ArgNo;
1107 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
1108 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
1109 "Invalid format for diff modifier");
1111 ArgNo2 = *DiagStr++ -
'0';
1122 const char *ArgumentEnd = Argument + ArgumentLen;
1125 "Found too many '|'s in a %diff modifier!");
1127 const char *SecondDollar =
ScanFormat(FirstDollar + 1,
Pipe,
'$');
1128 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo) };
1129 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2) };
1143 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1149 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1161 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1164 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1166 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1169 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1171 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1174 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1175 llvm::raw_svector_ostream(OutStr) << Val;
1182 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
1184 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
1186 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
1189 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
1191 }
else if (
ModifierIs(Modifier, ModifierLen,
"human")) {
1194 assert(ModifierLen == 0 &&
"Unknown integer modifier");
1195 llvm::raw_svector_ostream(OutStr) << Val;
1202 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
1204 llvm::raw_svector_ostream Out(OutStr);
1207 Out <<
'\'' << S <<
'\'';
1216 Out <<
'<' << S <<
'>';
1224 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
1228 const char *S =
"(null)";
1229 OutStr.append(S, S + strlen(S));
1233 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->
getName() <<
'\'';
1245 StringRef(Modifier, ModifierLen),
1246 StringRef(Argument, ArgumentLen),
1248 OutStr, QualTypeVals);
1260 const char *ArgumentEnd = Argument + ArgumentLen;
1269 StringRef(Modifier, ModifierLen),
1270 StringRef(Argument, ArgumentLen),
1272 Tree, QualTypeVals);
1274 if (!
Tree.empty()) {
1282 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
1283 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
1292 StringRef(Modifier, ModifierLen),
1293 StringRef(Argument, ArgumentLen),
1295 OutStr, QualTypeVals);
1306 StringRef(Modifier, ModifierLen),
1307 StringRef(Argument, ArgumentLen),
1309 OutStr, QualTypeVals);
1326 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
1333 OutStr.append(
Tree.begin(),
Tree.end());
1338 : ID(ID), Level(Level), Message(Message) {}
1342 : ID(Info.getID()), Level(Level) {
1344 "Valid source location without setting a source manager for diagnostic");
1349 this->Message.assign(Message.begin(), Message.end());
1358 : ID(ID), Level(Level),
Loc(
Loc), Message(Message),
1359 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1377void IgnoringDiagConsumer::anchor() {}
1384 Target.HandleDiagnostic(DiagLevel, Info);
1393 return Target.IncludeInDiagnosticCounts();
1397 for (
unsigned I = 0; I != NumCached; ++I)
1398 FreeList[I] = Cached + I;
1399 NumFreeListEntries = NumCached;
1405 assert((NumFreeListEntries == NumCached ||
1406 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1407 "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
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
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 StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
Level
The level of the diagnostic, after it has been through mapping.
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
static DiagnosticMapping getDefaultMapping(unsigned DiagID)
Get the default mapping for this diagnostic.
void setNoWarningAsError(bool Value)
void setSeverity(diag::Severity Value)
diag::Severity getSeverity() const
void setUpgradedFromWarning(bool Value)
void setNoErrorAsFatal(bool Value)
bool hasNoWarningAsError() const
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.
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 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_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...
DiagnosticsEngine(IntrusiveRefCntPtr< DiagnosticIDs > Diags, IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts, DiagnosticConsumer *client=nullptr, bool ShouldOwnClient=true)
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.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
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
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.
Flavor
Flavors of diagnostics we can emit.
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
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 ...
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