21 #include "llvm/ADT/SmallString.h" 22 #include "llvm/ADT/StringExtras.h" 23 #include "llvm/Support/CrashRecoveryContext.h" 24 #include "llvm/Support/Locale.h" 25 #include "llvm/Support/raw_ostream.h" 27 using namespace clang;
32 switch (nullability.first) {
34 string = nullability.second ?
"'nonnull'" :
"'_Nonnull'";
38 string = nullability.second ?
"'nullable'" :
"'_Nullable'";
42 string = nullability.second ?
"'null_unspecified'" :
"'_Null_unspecified'";
51 StringRef
Modifier, StringRef Argument,
56 StringRef Str =
"<can't format argument>";
57 Output.append(Str.begin(), Str.end());
64 : Diags(
std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
68 ArgToStringCookie =
nullptr;
70 AllExtensionsSilenced = 0;
71 SuppressAfterFatalError =
true;
72 SuppressAllDiagnostics =
false;
74 PrintTemplateTree =
false;
79 TemplateBacktraceLimit = 0;
80 ConstexprBacktraceLimit = 0;
92 bool ShouldOwnClient) {
93 Owner.reset(ShouldOwnClient ? client :
nullptr);
98 DiagStateOnPushStack.push_back(GetCurDiagState());
102 if (DiagStateOnPushStack.empty())
105 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
107 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
109 DiagStateOnPushStack.pop_back();
114 ErrorOccurred =
false;
115 UncompilableErrorOccurred =
false;
116 FatalErrorOccurred =
false;
117 UnrecoverableErrorOccurred =
false;
121 TrapNumErrorsOccurred = 0;
122 TrapNumUnrecoverableErrorsOccurred = 0;
130 DiagStatesByLoc.clear();
131 DiagStateOnPushStack.clear();
135 DiagStates.emplace_back();
136 DiagStatesByLoc.appendFirst(&DiagStates.back());
144 DelayedDiagID = DiagID;
145 DelayedDiagArg1 = Arg1.str();
146 DelayedDiagArg2 = Arg2.str();
149 void DiagnosticsEngine::ReportDelayed() {
150 unsigned ID = DelayedDiagID;
152 Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
155 void DiagnosticsEngine::DiagStateMap::appendFirst(
157 assert(Files.empty() &&
"not first");
158 FirstDiagState = CurDiagState =
State;
162 void DiagnosticsEngine::DiagStateMap::append(
SourceManager &SrcMgr,
165 CurDiagState =
State;
166 CurDiagStateLoc = Loc;
169 unsigned Offset = Decomp.second;
170 for (File *F = getFile(SrcMgr, Decomp.first); F;
171 Offset = F->ParentOffset, F = F->Parent) {
172 F->HasLocalTransitions =
true;
173 auto &
Last = F->StateTransitions.back();
174 assert(
Last.Offset <= Offset &&
"state transitions added out of order");
176 if (
Last.Offset == Offset) {
177 if (
Last.State == State)
183 F->StateTransitions.push_back({
State, Offset});
187 DiagnosticsEngine::DiagState *
188 DiagnosticsEngine::DiagStateMap::lookup(
SourceManager &SrcMgr,
192 return FirstDiagState;
195 const File *F = getFile(SrcMgr, Decomp.first);
196 return F->lookup(Decomp.second);
199 DiagnosticsEngine::DiagState *
200 DiagnosticsEngine::DiagStateMap::File::lookup(
unsigned Offset)
const {
201 auto OnePastIt = std::upper_bound(
202 StateTransitions.begin(), StateTransitions.end(),
Offset,
203 [](
unsigned Offset,
const DiagStatePoint &
P) {
204 return Offset <
P.Offset;
206 assert(OnePastIt != StateTransitions.begin() &&
"missing initial state");
207 return OnePastIt[-1].State;
210 DiagnosticsEngine::DiagStateMap::File *
211 DiagnosticsEngine::DiagStateMap::getFile(
SourceManager &SrcMgr,
214 auto Range = Files.equal_range(ID);
215 if (Range.first != Range.second)
216 return &Range.first->second;
217 auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
223 F.Parent = getFile(SrcMgr, Decomp.first);
224 F.ParentOffset = Decomp.second;
225 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
234 F.StateTransitions.push_back({FirstDiagState, 0});
239 void DiagnosticsEngine::PushDiagStatePoint(DiagState *
State,
241 assert(Loc.
isValid() &&
"Adding invalid loc point");
242 DiagStatesByLoc.append(*SourceMgr, Loc,
State);
248 "Can only map builtin diagnostics");
249 assert((Diags->isBuiltinWarningOrExtension(Diag) ||
251 "Cannot map errors into warnings!");
252 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
255 bool WasUpgradedFromWarning =
false;
261 WasUpgradedFromWarning =
true;
268 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
269 DiagStatesByLoc.getCurDiagState()) {
274 DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
281 DiagStates.push_back(*GetCurDiagState());
282 DiagStates.back().setMapping(Diag, Mapping);
283 PushDiagStatePoint(&DiagStates.back(), L);
291 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
366 std::vector<diag::kind> AllDiags;
371 if (Diags->isBuiltinWarningOrExtension(
Diag))
376 assert(CurDiagID == ~0U &&
"Multiple diagnostics in flight at once!");
379 CurDiagID = storedDiag.
getID();
385 DiagFixItHints.clear();
388 assert(Client &&
"DiagnosticConsumer not set!");
401 assert(
getClient() &&
"DiagnosticClient not set!");
414 Diags->EmitDiag(*
this, DiagLevel);
419 Emitted = ProcessDiag();
426 if (!Force && DelayedDiagID)
437 if (!IncludeInDiagnosticCounts())
447 template <std::
size_t StrLen>
449 const char (&Str)[StrLen]) {
450 return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
455 static const char *
ScanFormat(
const char *I,
const char *E,
char Target) {
458 for ( ; I != E; ++I) {
459 if (Depth == 0 && *I == Target)
return I;
460 if (Depth != 0 && *I ==
'}') Depth--;
470 for (I++; I != E && !
isDigit(*I) && *I !=
'{'; I++) ;
486 const char *Argument,
unsigned ArgumentLen,
488 const char *ArgumentEnd = Argument+ArgumentLen;
492 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
493 assert(NextVal != ArgumentEnd &&
"Value for integer select modifier was" 494 " larger than the number of options in the diagnostic string!");
495 Argument = NextVal+1;
500 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
512 OutStr.push_back(
's');
521 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
523 llvm::raw_svector_ostream Out(OutStr);
527 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
535 while (Start != End && *Start >=
'0' && *Start <=
'9') {
552 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
555 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
557 return Low <= Val && Val <= High;
572 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
574 unsigned ValMod = ValNo % Arg;
578 assert((C ==
'[' || (C >=
'0' && C <=
'9')) &&
579 "Bad plural expression syntax: unexpected character");
586 Start = std::find(Start, End,
',');
628 const char *Argument,
unsigned ArgumentLen,
630 const char *ArgumentEnd = Argument + ArgumentLen;
632 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
633 const char *ExprEnd = Argument;
634 while (*ExprEnd !=
':') {
635 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
639 Argument = ExprEnd + 1;
640 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
647 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
656 case tok::identifier:
668 if (!StoredDiagMessage.empty()) {
669 OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
674 getDiags()->getDiagnosticIDs()->getDescription(getID());
676 FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
686 if (DiagEnd - DiagStr == 2 &&
687 StringRef(DiagStr, DiagEnd - DiagStr).
equals(
"%0") &&
689 const std::string &S = getArgStdStr(0);
691 if (llvm::sys::locale::isPrint(c) || c ==
'\t') {
709 for (
unsigned i = 0, e = getNumArgs(); i < e; ++i)
711 QualTypeVals.push_back(getRawArg(i));
713 while (DiagStr != DiagEnd) {
714 if (DiagStr[0] !=
'%') {
716 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
717 OutStr.append(DiagStr, StrEnd);
721 OutStr.push_back(DiagStr[1]);
734 const char *Modifier =
nullptr, *Argument =
nullptr;
735 unsigned ModifierLen = 0, ArgumentLen = 0;
740 while (DiagStr[0] ==
'-' ||
741 (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
746 if (DiagStr[0] ==
'{') {
751 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
752 ArgumentLen = DiagStr-Argument;
757 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
758 unsigned ArgNo = *DiagStr++ -
'0';
761 unsigned ArgNo2 = ArgNo;
764 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
765 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
766 "Invalid format for diff modifier");
768 ArgNo2 = *DiagStr++ -
'0';
779 const char *ArgumentEnd = Argument + ArgumentLen;
780 const char *Pipe =
ScanFormat(Argument, ArgumentEnd,
'|');
781 assert(
ScanFormat(Pipe + 1, ArgumentEnd,
'|') == ArgumentEnd &&
782 "Found too many '|'s in a %diff modifier!");
783 const char *FirstDollar =
ScanFormat(Argument, Pipe,
'$');
784 const char *SecondDollar =
ScanFormat(FirstDollar + 1, Pipe,
'$');
785 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo) };
786 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2) };
787 FormatDiagnostic(Argument, FirstDollar, OutStr);
788 FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr);
789 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
790 FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr);
791 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
799 const std::string &S = getArgStdStr(ArgNo);
800 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
801 OutStr.append(S.begin(), S.end());
805 const char *S = getArgCStr(ArgNo);
806 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
812 OutStr.append(S, S + strlen(S));
817 int Val = getArgSInt(ArgNo);
819 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
822 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
824 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
827 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
830 assert(ModifierLen == 0 &&
"Unknown integer modifier");
831 llvm::raw_svector_ostream(OutStr) << Val;
836 unsigned Val = getArgUInt(ArgNo);
838 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
840 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
842 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
845 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
848 assert(ModifierLen == 0 &&
"Unknown integer modifier");
849 llvm::raw_svector_ostream(OutStr) << Val;
856 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
858 llvm::raw_svector_ostream Out(OutStr);
861 Out <<
'\'' << S <<
'\'';
870 Out << '<' << S << '>
'; 875 // ---- NAMES and TYPES ---- 876 case DiagnosticsEngine::ak_identifierinfo: { 877 const IdentifierInfo *II = getArgIdentifier(ArgNo); 878 assert(ModifierLen == 0 && "No modifiers for strings yet"); 880 // Don't crash
if get passed a null pointer by accident.
882 const char *S =
"(null)";
883 OutStr.append(S, S + strlen(S));
887 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->getName() <<
'\'';
896 getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
897 StringRef(Modifier, ModifierLen),
898 StringRef(Argument, ArgumentLen),
900 OutStr, QualTypeVals);
906 TDT.
ToType = getRawArg(ArgNo2);
912 const char *ArgumentEnd = Argument + ArgumentLen;
913 const char *Pipe =
ScanFormat(Argument, ArgumentEnd,
'|');
917 if (getDiags()->PrintTemplateTree && Tree.empty()) {
920 getDiags()->ConvertArgToString(Kind, val,
921 StringRef(Modifier, ModifierLen),
922 StringRef(Argument, ArgumentLen),
927 FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr);
934 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
935 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
938 FormatDiagnostic(Argument, FirstDollar, OutStr);
943 getDiags()->ConvertArgToString(Kind, val,
944 StringRef(Modifier, ModifierLen),
945 StringRef(Argument, ArgumentLen),
947 OutStr, QualTypeVals);
953 FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr);
957 getDiags()->ConvertArgToString(Kind, val,
958 StringRef(Modifier, ModifierLen),
959 StringRef(Argument, ArgumentLen),
961 OutStr, QualTypeVals);
967 FormatDiagnostic(SecondDollar + 1, Pipe, OutStr);
977 FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
980 (
intptr_t)getArgStdStr(ArgNo).c_str()));
985 OutStr.append(Tree.begin(), Tree.end());
990 : ID(ID), Level(Level), Loc(), Message(Message) { }
994 : ID(Info.
getID()), Level(Level)
997 "Valid source location without setting a source manager for diagnostic");
1002 this->Message.assign(Message.begin(), Message.end());
1011 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1012 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1022 void IgnoringDiagConsumer::anchor() { }
1029 Target.HandleDiagnostic(DiagLevel, Info);
1038 return Target.IncludeInDiagnosticCounts();
1042 for (
unsigned I = 0; I != NumCached; ++I)
1043 FreeList[I] = Cached + I;
1044 NumFreeListEntries = NumCached;
1050 assert((NumFreeListEntries == NumCached ||
1051 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1052 "A partial is on the lam");
A diagnostic that indicates a problem or potential problem.
void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, SourceLocation Loc=SourceLocation())
Add the specified mapping to all diagnostics of the specified flavor.
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.
DiagnosticConsumer * getClient()
fixit_iterator fixit_end() const
void pushMappings(SourceLocation Loc)
Copies the current DiagMappings and pushes the new copy onto the top of the stack.
range_iterator range_begin() const
static void HandleSelectModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandleSelectModifier - Handle the integer 'select' modifier.
Defines the SourceManager interface.
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
const DiagnosticBuilder & operator<<(const DiagnosticBuilder &DB, const Attr *At)
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.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled)
Set the warning-as-error flag for the given diagnostic group.
range_iterator range_end() const
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing)...
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
bool hasSourceManager() const
static void HandleOrdinalModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleOrdinalModifier - Handle the integer 'ord' modifier.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled)
Set the error-as-fatal flag for the given diagnostic group.
std::pair< NullabilityKind, bool > DiagNullabilityKind
A nullability kind paired with a bit indicating whether it used a context-sensitive keyword...
Values of this type can be null.
const char * getKeywordSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple keyword and contextual keyword tokens like 'int' and 'dynamic_cast'...
static const char * getTokenDescForDiagnostic(tok::TokenKind Kind)
Returns the friendly description for a token kind that will appear without quotes in diagnostic messa...
const SourceLocation & getLocation() const
Whether values of this type can be null is (explicitly) unspecified.
bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, diag::Severity Map, SourceLocation Loc=SourceLocation())
Change an entire diagnostic group (e.g.
Defines the Diagnostic-related interfaces.
Values of this type can never be null.
diag::Severity getSeverity() const
Present this diagnostic as an error.
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type...
StringRef getMessage() const
void Reset()
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...
DiagnosticsEngine(IntrusiveRefCntPtr< DiagnosticIDs > Diags, DiagnosticOptions *DiagOpts, DiagnosticConsumer *client=nullptr, bool ShouldOwnClient=true)
bool EmitCurrentDiagnostic(bool Force=false)
Emit the current diagnostic and clear the diagnostic state.
A little helper class used to produce diagnostics.
static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End)
EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
virtual ~DiagnosticConsumer()
bool equals(const til::SExpr *E1, const til::SExpr *E2)
DiagnosticsEngine::Level getLevel() const
unsigned TemplateDiffUsed
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like '!' or '', and returns NULL for literal and...
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
void Clear()
Clear out the current diagnostic.
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...
fixit_iterator fixit_begin() const
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
Encodes a location in the source.
Options for controlling the compiler diagnostics engine.
static void HandleIntegerSModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleIntegerSModifier - Handle the integer 's' modifier.
void AddString(StringRef S) const
OpenMPLinearClauseKind Modifier
Modifier of 'linear' clause.
void setUpgradedFromWarning(bool Value)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
void setNoErrorAsFatal(bool Value)
~ForwardingDiagnosticConsumer() override
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.
Flavor
Flavors of diagnostics we can emit.
SourceManager & getSourceManager() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
const FullSourceLoc & getLocation() const
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)
Level
The level of the diagnostic, after it has been through mapping.
StoredDiagnostic()=default
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc)
This allows the client to specify that certain warnings are ignored.
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...
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream...
static bool ModifierIs(const char *Modifier, unsigned ModifierLen, const char(&Str)[StrLen])
ModifierIs - Return true if the specified modifier matches specified string.
void setSeverity(diag::Severity Value)
static bool TestPluralRange(unsigned Val, const char *&Start, const char *End)
TestPluralRange - Test if Val is in the parsed range. Modifies Start.
ArrayRef< CharSourceRange > getRanges() const
Return an array reference for this diagnostic's ranges.
ArrayRef< FixItHint > getFixItHints() const
Level
The level of the diagnostic, after it has been through mapping.
LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
const char * getTokenName(TokenKind Kind) LLVM_READNONE
Determines the name of a token as used within the front end.
A SourceLocation and its associated SourceManager.
static void HandlePluralModifier(const Diagnostic &DInfo, unsigned ValNo, const char *Argument, unsigned ArgumentLen, SmallVectorImpl< char > &OutStr)
HandlePluralModifier - Handle the integer 'plural' modifier.
Present this diagnostic as a fatal error.
void setNoWarningAsError(bool Value)
static unsigned PluralNumber(const char *&Start, const char *End)
PluralNumber - Parse an unsigned integer and advance Start.
Present this diagnostic as a warning.
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots...
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
enum TokenKind : unsigned