20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/CrashRecoveryContext.h"
23 #include "llvm/Support/Locale.h"
24 #include "llvm/Support/raw_ostream.h"
26 using namespace clang;
31 switch (nullability.first) {
33 string = nullability.second ?
"'nonnull'" :
"'_Nonnull'";
37 string = nullability.second ?
"'nullable'" :
"'_Nullable'";
41 string = nullability.second ?
"'null_unspecified'" :
"'_Null_unspecified'";
50 StringRef
Modifier, StringRef Argument,
55 StringRef Str =
"<can't format argument>";
56 Output.append(Str.begin(), Str.end());
63 : Diags(std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
67 ArgToStringCookie =
nullptr;
69 AllExtensionsSilenced = 0;
70 SuppressAfterFatalError =
true;
71 SuppressAllDiagnostics =
false;
73 PrintTemplateTree =
false;
78 TemplateBacktraceLimit = 0;
79 ConstexprBacktraceLimit = 0;
91 bool ShouldOwnClient) {
92 Owner.reset(ShouldOwnClient ? client :
nullptr);
97 DiagStateOnPushStack.push_back(GetCurDiagState());
101 if (DiagStateOnPushStack.empty())
104 if (DiagStateOnPushStack.back() != GetCurDiagState()) {
106 PushDiagStatePoint(DiagStateOnPushStack.back(), Loc);
108 DiagStateOnPushStack.pop_back();
113 ErrorOccurred =
false;
114 UncompilableErrorOccurred =
false;
115 FatalErrorOccurred =
false;
116 UnrecoverableErrorOccurred =
false;
120 TrapNumErrorsOccurred = 0;
121 TrapNumUnrecoverableErrorsOccurred = 0;
129 DiagStatesByLoc.clear();
130 DiagStateOnPushStack.clear();
134 DiagStates.emplace_back();
135 DiagStatesByLoc.appendFirst(&DiagStates.back());
143 DelayedDiagID = DiagID;
144 DelayedDiagArg1 = Arg1.str();
145 DelayedDiagArg2 = Arg2.str();
148 void DiagnosticsEngine::ReportDelayed() {
149 unsigned ID = DelayedDiagID;
151 Report(ID) << DelayedDiagArg1 << DelayedDiagArg2;
154 void DiagnosticsEngine::DiagStateMap::appendFirst(
156 assert(Files.empty() &&
"not first");
157 FirstDiagState = CurDiagState =
State;
161 void DiagnosticsEngine::DiagStateMap::append(
SourceManager &SrcMgr,
164 CurDiagState =
State;
165 CurDiagStateLoc = Loc;
168 unsigned Offset = Decomp.second;
169 for (File *F = getFile(SrcMgr, Decomp.first); F;
170 Offset = F->ParentOffset, F = F->Parent) {
171 F->HasLocalTransitions =
true;
172 auto &Last = F->StateTransitions.back();
173 assert(Last.Offset <= Offset &&
"state transitions added out of order");
175 if (Last.Offset == Offset) {
176 if (Last.State == State)
182 F->StateTransitions.push_back({
State, Offset});
186 DiagnosticsEngine::DiagState *
187 DiagnosticsEngine::DiagStateMap::lookup(
SourceManager &SrcMgr,
191 return FirstDiagState;
194 const File *F = getFile(SrcMgr, Decomp.first);
195 return F->lookup(Decomp.second);
198 DiagnosticsEngine::DiagState *
199 DiagnosticsEngine::DiagStateMap::File::lookup(
unsigned Offset)
const {
200 auto OnePastIt = std::upper_bound(
201 StateTransitions.begin(), StateTransitions.end(),
Offset,
202 [](
unsigned Offset,
const DiagStatePoint &
P) {
203 return Offset <
P.Offset;
205 assert(OnePastIt != StateTransitions.begin() &&
"missing initial state");
206 return OnePastIt[-1].State;
209 DiagnosticsEngine::DiagStateMap::File *
210 DiagnosticsEngine::DiagStateMap::getFile(
SourceManager &SrcMgr,
213 auto Range = Files.equal_range(ID);
214 if (Range.first != Range.second)
215 return &Range.first->second;
216 auto &F = Files.insert(Range.first, std::make_pair(ID, File()))->second;
222 F.Parent = getFile(SrcMgr, Decomp.first);
223 F.ParentOffset = Decomp.second;
224 F.StateTransitions.push_back({F.Parent->lookup(Decomp.second), 0});
233 F.StateTransitions.push_back({FirstDiagState, 0});
238 void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
240 assert(Loc.
isValid() &&
"Adding invalid loc point");
241 DiagStatesByLoc.append(*SourceMgr, Loc, State);
247 "Can only map builtin diagnostics");
248 assert((Diags->isBuiltinWarningOrExtension(Diag) ||
250 "Cannot map errors into warnings!");
251 assert((L.
isInvalid() || SourceMgr) &&
"No SourceMgr for valid location");
254 bool WasUpgradedFromWarning =
false;
260 WasUpgradedFromWarning =
true;
267 if ((L.
isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
268 DiagStatesByLoc.getCurDiagState()) {
273 DiagStatesByLoc.getCurDiagState()->setMapping(Diag, Mapping);
280 DiagStates.push_back(*GetCurDiagState());
281 DiagStates.back().setMapping(Diag, Mapping);
282 PushDiagStatePoint(&DiagStates.back(), L);
290 if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
366 Diags->getAllDiagnostics(Flavor, AllDiags);
370 if (Diags->isBuiltinWarningOrExtension(
Diag))
375 assert(CurDiagID == ~0U &&
"Multiple diagnostics in flight at once!");
378 CurDiagID = storedDiag.
getID();
384 DiagFixItHints.clear();
387 assert(Client &&
"DiagnosticConsumer not set!");
400 assert(
getClient() &&
"DiagnosticClient not set!");
413 Diags->EmitDiag(*
this, DiagLevel);
418 Emitted = ProcessDiag();
425 if (!Force && DelayedDiagID)
446 template <std::
size_t StrLen>
448 const char (&Str)[StrLen]) {
449 return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
454 static const char *
ScanFormat(
const char *
I,
const char *
E,
char Target) {
457 for ( ; I !=
E; ++
I) {
458 if (Depth == 0 && *I == Target)
return I;
459 if (Depth != 0 && *I ==
'}') Depth--;
469 for (I++; I != E && !
isDigit(*I) && *I !=
'{'; I++) ;
485 const char *Argument,
unsigned ArgumentLen,
487 const char *ArgumentEnd = Argument+ArgumentLen;
491 const char *NextVal =
ScanFormat(Argument, ArgumentEnd,
'|');
492 assert(NextVal != ArgumentEnd &&
"Value for integer select modifier was"
493 " larger than the number of options in the diagnostic string!");
494 Argument = NextVal+1;
499 const char *EndPtr =
ScanFormat(Argument, ArgumentEnd,
'|');
511 OutStr.push_back(
's');
520 assert(ValNo != 0 &&
"ValNo must be strictly positive!");
522 llvm::raw_svector_ostream Out(OutStr);
526 Out << ValNo << llvm::getOrdinalSuffix(ValNo);
534 while (Start != End && *Start >=
'0' && *Start <=
'9') {
551 assert(*Start ==
',' &&
"Bad plural expression syntax: expected ,");
554 assert(*Start ==
']' &&
"Bad plural expression syntax: expected )");
556 return Low <= Val && Val <= High;
571 assert(*Start ==
'=' &&
"Bad plural expression syntax: expected =");
573 unsigned ValMod = ValNo % Arg;
577 assert((C ==
'[' || (C >=
'0' && C <=
'9')) &&
578 "Bad plural expression syntax: unexpected character");
585 Start = std::find(Start, End,
',');
627 const char *Argument,
unsigned ArgumentLen,
629 const char *ArgumentEnd = Argument + ArgumentLen;
631 assert(Argument < ArgumentEnd &&
"Plural expression didn't match.");
632 const char *ExprEnd = Argument;
633 while (*ExprEnd !=
':') {
634 assert(ExprEnd != ArgumentEnd &&
"Plural missing expression end");
638 Argument = ExprEnd + 1;
639 ExprEnd =
ScanFormat(Argument, ArgumentEnd,
'|');
646 Argument =
ScanFormat(Argument, ArgumentEnd - 1,
'|') + 1;
655 case tok::identifier:
667 if (!StoredDiagMessage.empty()) {
668 OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
685 if (DiagEnd - DiagStr == 2 &&
686 StringRef(DiagStr, DiagEnd - DiagStr).
equals(
"%0") &&
690 if (llvm::sys::locale::isPrint(c) || c ==
'\t') {
708 for (
unsigned i = 0, e =
getNumArgs(); i < e; ++i)
712 while (DiagStr != DiagEnd) {
713 if (DiagStr[0] !=
'%') {
715 const char *StrEnd = std::find(DiagStr, DiagEnd,
'%');
716 OutStr.append(DiagStr, StrEnd);
720 OutStr.push_back(DiagStr[1]);
733 const char *Modifier =
nullptr, *Argument =
nullptr;
734 unsigned ModifierLen = 0, ArgumentLen = 0;
739 while (DiagStr[0] ==
'-' ||
740 (DiagStr[0] >=
'a' && DiagStr[0] <=
'z'))
745 if (DiagStr[0] ==
'{') {
750 assert(DiagStr != DiagEnd &&
"Mismatched {}'s in diagnostic string!");
751 ArgumentLen = DiagStr-Argument;
756 assert(
isDigit(*DiagStr) &&
"Invalid format for argument in diagnostic");
757 unsigned ArgNo = *DiagStr++ -
'0';
760 unsigned ArgNo2 = ArgNo;
763 if (
ModifierIs(Modifier, ModifierLen,
"diff")) {
764 assert(*DiagStr ==
',' &&
isDigit(*(DiagStr + 1)) &&
765 "Invalid format for diff modifier");
767 ArgNo2 = *DiagStr++ -
'0';
778 const char *ArgumentEnd = Argument + ArgumentLen;
779 const char *Pipe =
ScanFormat(Argument, ArgumentEnd,
'|');
780 assert(
ScanFormat(Pipe + 1, ArgumentEnd,
'|') == ArgumentEnd &&
781 "Found too many '|'s in a %diff modifier!");
782 const char *FirstDollar =
ScanFormat(Argument, Pipe,
'$');
783 const char *SecondDollar =
ScanFormat(FirstDollar + 1, Pipe,
'$');
784 const char ArgStr1[] = {
'%',
static_cast<char>(
'0' + ArgNo) };
785 const char ArgStr2[] = {
'%',
static_cast<char>(
'0' + ArgNo2) };
799 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
800 OutStr.append(S.begin(), S.end());
805 assert(ModifierLen == 0 &&
"No modifiers for strings yet");
811 OutStr.append(S, S + strlen(S));
818 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
821 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
823 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
826 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
829 assert(ModifierLen == 0 &&
"Unknown integer modifier");
830 llvm::raw_svector_ostream(OutStr) << Val;
837 if (
ModifierIs(Modifier, ModifierLen,
"select")) {
839 }
else if (
ModifierIs(Modifier, ModifierLen,
"s")) {
841 }
else if (
ModifierIs(Modifier, ModifierLen,
"plural")) {
844 }
else if (
ModifierIs(Modifier, ModifierLen,
"ordinal")) {
847 assert(ModifierLen == 0 &&
"Unknown integer modifier");
848 llvm::raw_svector_ostream(OutStr) << Val;
855 assert(ModifierLen == 0 &&
"No modifiers for token kinds yet");
857 llvm::raw_svector_ostream Out(OutStr);
860 Out <<
'\'' <<
S <<
'\'';
869 Out << '<' << S << '>
';
874 // ---- NAMES and TYPES ----
875 case DiagnosticsEngine::ak_identifierinfo: {
876 const IdentifierInfo *II = getArgIdentifier(ArgNo);
877 assert(ModifierLen == 0 && "No modifiers for strings yet");
879 // Don't crash
if get passed a null pointer by accident.
881 const char *S =
"(null)";
882 OutStr.append(S, S + strlen(S));
886 llvm::raw_svector_ostream(OutStr) <<
'\'' << II->getName() <<
'\'';
896 StringRef(Modifier, ModifierLen),
897 StringRef(Argument, ArgumentLen),
899 OutStr, QualTypeVals);
911 const char *ArgumentEnd = Argument + ArgumentLen;
912 const char *Pipe =
ScanFormat(Argument, ArgumentEnd,
'|');
916 if (
getDiags()->PrintTemplateTree && Tree.empty()) {
920 StringRef(Modifier, ModifierLen),
921 StringRef(Argument, ArgumentLen),
933 const char *FirstDollar =
ScanFormat(Argument, ArgumentEnd,
'$');
934 const char *SecondDollar =
ScanFormat(FirstDollar + 1, ArgumentEnd,
'$');
943 StringRef(Modifier, ModifierLen),
944 StringRef(Argument, ArgumentLen),
946 OutStr, QualTypeVals);
957 StringRef(Modifier, ModifierLen),
958 StringRef(Argument, ArgumentLen),
960 OutStr, QualTypeVals);
976 FormattedArgs.push_back(std::make_pair(Kind,
getRawArg(ArgNo)));
984 OutStr.append(Tree.begin(), Tree.end());
989 : ID(ID), Level(Level), Loc(), Message(Message) { }
993 : ID(Info.getID()), Level(Level)
996 "Valid source location without setting a source manager for diagnostic");
1001 this->Message.assign(Message.begin(), Message.end());
1010 : ID(ID), Level(Level), Loc(Loc), Message(Message),
1011 Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
1021 void IgnoringDiagConsumer::anchor() { }
1041 for (
unsigned I = 0;
I != NumCached; ++
I)
1042 FreeList[
I] = Cached +
I;
1043 NumFreeListEntries = NumCached;
1049 assert((NumFreeListEntries == NumCached ||
1050 llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
1051 "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.
static LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
DiagnosticConsumer * getClient()
void pushMappings(SourceLocation Loc)
Copies the current DiagMappings and pushes the new copy onto the top of the stack.
unsigned getNumArgs() const
unsigned NumErrors
Number of errors reported.
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.
StringRef getMessage() const
const std::string & getArgStdStr(unsigned Idx) const
Return the provided argument string specified by Idx.
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.
const FullSourceLoc & getLocation() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
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 setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled)
Set the warning-as-error flag for the given diagnostic group.
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.
fixit_iterator fixit_end() 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.
const DiagnosticsEngine * getDiags() const
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled)
Set the error-as-fatal flag for the given diagnostic group.
int getArgSInt(unsigned Idx) const
Return the specified signed integer argument.
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.
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
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.
fixit_iterator fixit_begin() const
Present this diagnostic as an error.
const char * getArgCStr(unsigned Idx) const
Return the specified C string argument.
const IntrusiveRefCntPtr< DiagnosticIDs > & getDiagnosticIDs() const
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type...
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...
detail::InMemoryDirectory::const_iterator I
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.
virtual ~DiagnosticConsumer()
bool equals(const til::SExpr *E1, const til::SExpr *E2)
range_iterator range_begin() const
unsigned TemplateDiffUsed
intptr_t getRawArg(unsigned Idx) const
Return the specified non-string argument in an opaque form.
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 AddString(StringRef S) const
void Clear()
Clear out the current diagnostic.
diag::Severity getSeverity() const
unsigned Map[FirstTargetAddressSpace]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
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...
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
static void HandleIntegerSModifier(unsigned ValNo, SmallVectorImpl< char > &OutStr)
HandleIntegerSModifier - Handle the integer 's' modifier.
OpenMPLinearClauseKind Modifier
Modifier of 'linear' clause.
static LLVM_READONLY bool isPunctuation(unsigned char c)
Return true if this character is an ASCII punctuation character.
void setUpgradedFromWarning(bool Value)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
unsigned NumWarnings
Number of warnings reported.
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.
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const
Return the kind of the specified index.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
range_iterator range_end() const
bool hasSourceManager() 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
detail::InMemoryDirectory::const_iterator E
ArrayRef< CharSourceRange > getRanges() const
Return an array reference for this diagnostic's ranges.
SourceManager & getSourceManager() const
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.
Level
The level of the diagnostic, after it has been through mapping.
DiagnosticsEngine::Level getLevel() const
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.
unsigned getArgUInt(unsigned Idx) const
Return the specified unsigned integer argument.
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.
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots...
Present this diagnostic as a warning.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
This class handles loading and caching of source files into memory.
ArrayRef< FixItHint > getFixItHints() const
enum TokenKind : unsigned