27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/SmallVector.h"
30#include "llvm/ADT/iterator_range.h"
49 ExpandLocStart =
Tok.getLocation();
51 AtStartOfLine =
Tok.isAtStartOfLine();
52 HasLeadingSpace =
Tok.hasLeadingSpace();
53 NextTokGetsSpace =
false;
54 Tokens = &*Macro->tokens_begin();
56 DisableMacroExpansion =
false;
58 NumTokens = Macro->tokens_end()-Macro->tokens_begin();
60 LexingCXXModuleDirective =
false;
63 MacroStartSLocOffset =
SM.getNextLocalOffset();
66 assert(Tokens[0].getLocation().isValid());
67 assert((Tokens[0].getLocation().isFileID() || Tokens[0].
is(tok::comment)) &&
68 "Macro defined in macro?");
69 assert(ExpandLocStart.isValid());
75 MacroDefStart =
SM.getExpansionLoc(Tokens[0].getLocation());
76 MacroDefLength = Macro->getDefinitionLength(
SM);
77 MacroExpansionStart =
SM.createExpansionLoc(MacroDefStart,
85 if (Macro->isFunctionLike() && Macro->getNumParams())
86 ExpandFunctionArguments();
91 Macro->DisableMacro();
97 bool disableMacroExpansion,
bool ownsTokens,
99 assert(!isReinject || disableMacroExpansion);
105 ActualArgs =
nullptr;
107 OwnsTokens = ownsTokens;
108 DisableMacroExpansion = disableMacroExpansion;
109 IsReinject = isReinject;
113 AtStartOfLine =
false;
114 HasLeadingSpace =
false;
115 NextTokGetsSpace =
false;
117 LexingCXXModuleDirective =
false;
127void TokenLexer::destroy() {
137 if (ActualArgs) ActualArgs->
destroy(PP);
140bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
144 if (!Macro->isVariadic() || MacroArgNo != Macro->getNumParams()-1)
150 if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)
158 if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode
159 && Macro->getNumParams() < 2)
163 if (ResultToks.empty() || !ResultToks.back().is(tok::comma))
167 if (HasPasteOperator)
168 PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
171 ResultToks.pop_back();
173 if (!ResultToks.empty()) {
178 if (ResultToks.back().is(tok::hashhash))
179 ResultToks.pop_back();
186 NextTokGetsSpace =
false;
190void TokenLexer::stringifyVAOPTContents(
194 const unsigned int NumVAOptTokens = ResultToks.size() - NumToksPriorToVAOpt;
195 Token *
const VAOPTTokens =
196 NumVAOptTokens ? &ResultToks[NumToksPriorToVAOpt] :
nullptr;
198 SmallVector<Token, 64> ConcatenatedVAOPTResultToks;
203 for (
unsigned int CurTokenIdx = 0; CurTokenIdx != NumVAOptTokens;
205 if (VAOPTTokens[CurTokenIdx].
is(tok::hashhash)) {
206 assert(CurTokenIdx != 0 &&
207 "Can not have __VAOPT__ contents begin with a ##");
208 Token &LHS = VAOPTTokens[CurTokenIdx - 1];
209 pasteTokens(LHS, llvm::ArrayRef(VAOPTTokens, NumVAOptTokens),
212 ConcatenatedVAOPTResultToks.back() = LHS;
213 if (CurTokenIdx == NumVAOptTokens)
216 ConcatenatedVAOPTResultToks.push_back(VAOPTTokens[CurTokenIdx]);
219 ConcatenatedVAOPTResultToks.push_back(VCtx.
getEOFTok());
225 const SourceLocation ExpansionLocStartWithinMacro =
227 const SourceLocation ExpansionLocEndWithinMacro =
228 getExpansionLocForMacroDefLoc(VAOPTClosingParenLoc);
232 ExpansionLocStartWithinMacro, ExpansionLocEndWithinMacro);
239 ResultToks.resize(NumToksPriorToVAOpt + 1);
240 ResultToks.back() = StringifiedVAOPT;
245void TokenLexer::ExpandFunctionArguments() {
246 SmallVector<Token, 128> ResultToks;
251 bool MadeChange =
false;
253 std::optional<bool> CalledWithVariadicArguments;
255 VAOptExpansionContext VCtx(PP);
257 for (
unsigned I = 0, E = NumTokens; I != E; ++I) {
258 const Token &CurTok = Tokens[I];
266 NextTokGetsSpace =
true;
270 assert(Tokens[I + 1].
is(tok::l_paren) &&
271 "__VA_OPT__ must be followed by '('");
293 if (Tokens[I].
is(tok::l_paren))
301 if (!CalledWithVariadicArguments) {
302 CalledWithVariadicArguments =
303 ActualArgs->invokedWithVariadicArgument(Macro, PP);
305 if (!*CalledWithVariadicArguments) {
325 stringifyVAOPTContents(ResultToks, VCtx,
326 Tokens[I].getLocation());
335 if (ResultToks.size() && ResultToks.back().is(tok::hashhash)) {
336 ResultToks.pop_back();
337 }
else if ((I + 1 != E) && Tokens[I + 1].
is(tok::hashhash)) {
350 "no token paste before __VA_OPT__");
351 ResultToks.erase(ResultToks.begin() +
357 Tokens[I + 1].is(tok::hashhash)) {
372 if (CurTok.
isOneOf(tok::hash, tok::hashat)) {
373 int ArgNo = Macro->getParameterNum(Tokens[I+1].getIdentifierInfo());
374 assert((ArgNo != -1 || VCtx.
isVAOptToken(Tokens[I + 1])) &&
375 "Token following # is not an argument or __VA_OPT__!");
380 CurTok.
is(tok::hashat));
384 SourceLocation ExpansionLocStart =
385 getExpansionLocForMacroDefLoc(CurTok.
getLocation());
386 SourceLocation ExpansionLocEnd =
387 getExpansionLocForMacroDefLoc(Tokens[I+1].getLocation());
389 bool Charify = CurTok.
is(tok::hashat);
390 const Token *UnexpArg = ActualArgs->getUnexpArgument(ArgNo);
392 UnexpArg, PP, Charify, ExpansionLocStart, ExpansionLocEnd);
397 if (NextTokGetsSpace)
400 ResultToks.push_back(Res);
403 NextTokGetsSpace =
false;
408 bool NonEmptyPasteBefore =
409 !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
410 bool PasteBefore = I != 0 && Tokens[I-1].is(tok::hashhash);
411 bool PasteAfter = I+1 != E && Tokens[I+1].is(tok::hashhash);
412 bool RParenAfter = I+1 != E && Tokens[I+1].is(tok::r_paren);
414 assert((!NonEmptyPasteBefore || PasteBefore || VCtx.
isInVAOpt()) &&
415 "unexpected ## in ResultToks");
420 int ArgNo = II ? Macro->getParameterNum(II) : -1;
423 ResultToks.push_back(CurTok);
425 if (NextTokGetsSpace) {
427 NextTokGetsSpace =
false;
428 }
else if (PasteBefore && !NonEmptyPasteBefore)
442 if (!PasteBefore && ActualArgs->isVarargsElidedUse() &&
443 MaybeRemoveCommaBeforeVaArgs(ResultToks,
451 if (!PasteBefore && !PasteAfter) {
452 const Token *ResultArgToks;
456 const Token *ArgTok = ActualArgs->getUnexpArgument(ArgNo);
457 if (ActualArgs->ArgNeedsPreexpansion(ArgTok, PP))
458 ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, PP)[0];
460 ResultArgToks = ArgTok;
463 if (ResultArgToks->
isNot(tok::eof)) {
464 size_t FirstResult = ResultToks.size();
466 ResultToks.append(ResultArgToks, ResultArgToks+NumToks);
472 if (PP.getLangOpts().MSVCCompat && NumToks == 1 &&
473 ResultToks.back().is(tok::comma))
478 for (Token &
Tok : llvm::drop_begin(ResultToks, FirstResult))
479 if (
Tok.
is(tok::hashhash))
482 if(ExpandLocStart.isValid()) {
484 ResultToks.begin()+FirstResult,
494 NextTokGetsSpace =
false;
499 if (NonEmptyPasteBefore) {
502 assert(VCtx.
isInVAOpt() &&
"should only happen inside a __VA_OPT__");
504 }
else if (RParenAfter)
512 const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo);
515 bool VaArgsPseudoPaste =
false;
520 if (NonEmptyPasteBefore && ResultToks.size() >= 2 &&
521 ResultToks[ResultToks.size()-2].is(tok::comma) &&
522 (
unsigned)ArgNo == Macro->getNumParams()-1 &&
523 Macro->isVariadic()) {
524 VaArgsPseudoPaste =
true;
526 PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma);
529 ResultToks.append(ArgToks, ArgToks+NumToks);
533 for (Token &
Tok : llvm::make_range(ResultToks.end() - NumToks,
535 if (
Tok.
is(tok::hashhash))
539 if (ExpandLocStart.isValid()) {
541 ResultToks.end()-NumToks, ResultToks.end());
548 if (!VaArgsPseudoPaste) {
551 ResultToks[ResultToks.size() - NumToks].setFlagValue(
555 NextTokGetsSpace =
false;
570 if (RParenAfter && !NonEmptyPasteBefore)
577 if (NonEmptyPasteBefore) {
578 assert(ResultToks.back().is(tok::hashhash));
585 ResultToks.pop_back();
594 if (ActualArgs->isVarargsElidedUse())
595 MaybeRemoveCommaBeforeVaArgs(ResultToks,
602 assert(!OwnsTokens &&
"This would leak if we already own the token list");
604 NumTokens = ResultToks.size();
607 Tokens = PP.cacheMacroExpandedTokens(
this, ResultToks);
616 const Token &SecondTok) {
617 return FirstTok.
is(tok::identifier) &&
628 if (Macro) Macro->EnableMacro();
638 AtStartOfLine =
true;
645 if (CurTokenIdx == 0)
647 return PP.HandleEndOfTokenLexer(
Tok);
654 bool isFirstToken = CurTokenIdx == 0;
657 Tok = Tokens[CurTokenIdx++];
661 bool TokenIsFromPaste =
false;
665 if (!isAtEnd() && Macro &&
666 (Tokens[CurTokenIdx].
is(tok::hashhash) ||
670 (PP.getLangOpts().MSVCCompat &&
674 if (pasteTokens(
Tok))
677 TokenIsFromPaste =
true;
685 if (ExpandLocStart.isValid() &&
687 SM.isBeforeInSLocAddrSpace(
Tok.getLocation(), MacroStartSLocOffset)) {
689 if (
Tok.is(tok::comment)) {
690 instLoc =
SM.createExpansionLoc(
Tok.getLocation(),
695 instLoc = getExpansionLocForMacroDefLoc(
Tok.getLocation());
698 Tok.setLocation(instLoc);
712 AtStartOfLine =
false;
713 HasLeadingSpace =
false;
716 if (!
Tok.isAnnotation() &&
Tok.getIdentifierInfo() !=
nullptr &&
717 (!PP.getLangOpts().CPlusPlusModules ||
718 !
Tok.isModuleContextualKeyword())) {
728 PP.HandlePoisonedIdentifier(
Tok);
732 return PP.HandleIdentifier(
Tok);
739bool TokenLexer::pasteTokens(
Token &
Tok) {
748 unsigned int &CurIdx) {
749 assert(CurIdx > 0 &&
"## can not be the first token within tokens");
750 assert((TokenStream[CurIdx].
is(tok::hashhash) ||
753 "Token at this Index must be ## or part of the MSVC 'L "
754 "#macro-arg' pasting pair");
759 if (PP.
getLangOpts().MicrosoftExt && (CurIdx >= 2) &&
760 TokenStream[CurIdx - 2].is(tok::hashhash))
764 const char *ResultTokStrPtr =
nullptr;
767 bool HasUCNs =
false;
769 auto IsAtEnd = [&TokenStream, &CurIdx] {
770 return TokenStream.size() == CurIdx;
775 PasteOpLoc = TokenStream[CurIdx].getLocation();
776 if (TokenStream[CurIdx].
is(tok::hashhash))
778 assert(!IsAtEnd() &&
"No token on the RHS of a paste operator!");
781 const Token &RHS = TokenStream[CurIdx];
788 const char *BufPtr = &Buffer[0];
790 unsigned LHSLen = PP.getSpelling(LHSTok, BufPtr, &
Invalid);
791 if (BufPtr != &Buffer[0])
792 memcpy(&Buffer[0], BufPtr, LHSLen);
796 BufPtr = Buffer.data() + LHSLen;
797 unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &
Invalid);
800 if (RHSLen && BufPtr != &Buffer[LHSLen])
802 memcpy(&Buffer[LHSLen], BufPtr, RHSLen);
805 Buffer.resize(LHSLen+RHSLen);
814 ResultTokTmp.
setKind(tok::string_literal);
815 PP.CreateString(Buffer, ResultTokTmp);
816 SourceLocation ResultTokLoc = ResultTokTmp.
getLocation();
825 PP.IncrementPasteCounter(
true);
827 Result.setKind(tok::raw_identifier);
828 Result.setRawIdentifierData(ResultTokStrPtr);
829 Result.setLocation(ResultTokLoc);
830 Result.setLength(LHSLen+RHSLen);
832 PP.IncrementPasteCounter(
false);
835 "Should be a raw location into scratch buffer");
836 SourceManager &SourceMgr = PP.getSourceManager();
837 FileID LocFileID = SourceMgr.
getFileID(ResultTokLoc);
840 const char *ScratchBufStart
848 PP.getLangOpts(), ScratchBufStart,
849 ResultTokStrPtr, ResultTokStrPtr+LHSLen+RHSLen);
867 SourceManager &
SM = PP.getSourceManager();
869 SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2);
873 if (PP.getLangOpts().MicrosoftExt && LHSTok.
is(tok::slash) &&
874 RHS.
is(tok::slash)) {
875 HandleMicrosoftCommentPaste(LHSTok, Loc);
880 if (!PP.getLangOpts().AsmPreprocessor) {
884 PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::ext_pp_bad_paste_ms
885 : diag::err_pp_bad_paste)
895 if (
Result.is(tok::hashhash))
896 Result.setKind(tok::unknown);
909 }
while (!IsAtEnd() && TokenStream[CurIdx].
is(tok::hashhash));
911 SourceLocation EndLoc = TokenStream[CurIdx - 1].getLocation();
918 SourceManager &
SM = PP.getSourceManager();
920 StartLoc = getExpansionLocForMacroDefLoc(StartLoc);
922 EndLoc = getExpansionLocForMacroDefLoc(EndLoc);
923 FileID MacroFID =
SM.getFileID(MacroExpansionStart);
924 while (
SM.getFileID(StartLoc) != MacroFID)
925 StartLoc =
SM.getImmediateExpansionRange(StartLoc).getBegin();
926 while (
SM.getFileID(EndLoc) != MacroFID)
927 EndLoc =
SM.getImmediateExpansionRange(EndLoc).getEnd();
935 if (LHSTok.
is(tok::raw_identifier)) {
945 PP.LookUpIdentifierInfo(LHSTok);
957 return Tokens[CurTokenIdx];
963 return Tokens[NumTokens-1].is(tok::eod) && !isAtEnd();
969 LexingCXXModuleDirective = Val;
975 return LexingCXXModuleDirective;
984 PP.
Diag(OpLoc, diag::ext_comment_paste_microsoft);
991 assert(
Macro &&
"Token streams can't paste comments");
992 Macro->EnableMacro();
1002TokenLexer::getExpansionLocForMacroDefLoc(
SourceLocation loc)
const {
1003 assert(ExpandLocStart.
isValid() && MacroExpansionStart.
isValid() &&
1004 "Not appropriate for token streams");
1008 assert(
SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength) &&
1009 "Expected loc to come from the macro definition");
1012 SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength, &relativeOffset);
1027 Token *&begin_tokens,
1028 Token * end_tokens) {
1029 assert(begin_tokens + 1 < end_tokens);
1041 return Distance <= MaxDistance;
1050 Partition =
All.take_while([&](
const Token &
T) {
1051 return T.getLocation().isFileID() && NearLast(
T.getLocation());
1056 FileID BeginFID =
SM.getFileID(BeginLoc);
1058 SM.getComposedLoc(BeginFID,
SM.getFileIDSize(BeginFID));
1059 Partition =
All.take_while([&](
const Token &
T) {
1068 return T.getLocation() >= BeginLoc &&
T.getLocation() <= Limit
1069 && NearLast(
T.getLocation());
1072 assert(!Partition.empty());
1077 Partition.back().getEndLoc().getRawEncoding() -
1078 Partition.front().getLocation().getRawEncoding();
1081 SM.createMacroArgExpansionLoc(BeginLoc, ExpandLoc, FullLength);
1083#ifdef EXPENSIVE_CHECKS
1084 assert(llvm::all_of(Partition.drop_front(),
1085 [&
SM, ID =
SM.getFileID(Partition.front().getLocation())](
1087 return ID == SM.getFileID(T.getLocation());
1089 "Must have the same FIleID!");
1093 for (
Token&
T : Partition) {
1098 begin_tokens = &Partition.back() + 1;
1106void TokenLexer::updateLocForMacroArgTokens(
SourceLocation ArgIdSpellLoc,
1107 Token *begin_tokens,
1108 Token *end_tokens) {
1109 SourceManager &
SM = PP.getSourceManager();
1111 SourceLocation ExpandLoc =
1112 getExpansionLocForMacroDefLoc(ArgIdSpellLoc);
1114 while (begin_tokens < end_tokens) {
1116 if (end_tokens - begin_tokens == 1) {
1117 Token &
Tok = *begin_tokens;
1128void TokenLexer::PropagateLineStartLeadingSpaceInfo(
Token &
Result) {
1129 AtStartOfLine =
Result.isAtStartOfLine();
1130 HasLeadingSpace =
Result.hasLeadingSpace();
Defines the Diagnostic-related interfaces.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
static bool isInvalid(LocType Loc, bool *Invalid)
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
static bool isWideStringLiteralFromMacro(const Token &FirstTok, const Token &SecondTok)
Checks if two tokens form wide string literal.
static void updateConsecutiveMacroArgTokens(SourceManager &SM, SourceLocation ExpandLoc, Token *&begin_tokens, Token *end_tokens)
Finds the tokens that are consecutive (from the same FileID) creates a single SLocEntry,...
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
One of these records is kept for each identifier that is lexed.
bool isHandleIdentifierCase() const
Return true if the Preprocessor::HandleIdentifier must be called on a token of this identifier.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
bool isPoisoned() const
Return true if this token has been poisoned.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
static unsigned getArgLength(const Token *ArgPtr)
getArgLength - Given a pointer to an expanded or unexpanded argument, return the number of tokens,...
static Token StringifyArgument(const Token *ArgToks, Preprocessor &PP, bool Charify, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd)
StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of tokens into the literal string...
void destroy(Preprocessor &PP)
destroy - Destroy and deallocate the memory for this object.
Encapsulates the data about a macro definition (e.g.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
const LangOptions & getLangOpts() const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
void HandleMicrosoftCommentPaste(Token &Tok)
When the macro expander pastes together a comment (/##/) in Microsoft mode, this method handles updat...
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isParsingPreprocessorDirective() const
isParsingPreprocessorDirective - Return true if we are in the middle of a preprocessor directive.
bool isLexingCXXModuleDirective() const
isLexingCXXModuleDirective - Return true if we are lexing a C++ module or import directive.
bool Lex(Token &Tok)
Lex and return a token from this macro stream.
std::optional< Token > peekNextPPToken() const
If TokenLexer::isAtEnd returns true(the next token lexed will pop thismacro off the expansion stack),...
void Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, MacroArgs *Actuals)
Initialize this TokenLexer to expand from the specified macro with the specified argument information...
void setLexingCXXModuleDirective(bool Val=true)
setLexingCXXModuleDirective - This is set to true if this TokenLexer is created when handling a C++ m...
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
bool hasUCN() const
Returns true if this token contains a universal character name.
void clearFlag(TokenFlags Flag)
Unset the specified flag.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool isOneOf(Ts... Ks) const
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
void setLocation(SourceLocation L)
bool isNot(tok::TokenKind K) const
bool stringifiedInMacro() const
Returns true if this token is formed by macro by stringizing or charizing operator.
void startToken()
Reset all flags to cleared.
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
void setFlag(TokenFlags Flag)
Set the specified flag.
A class for tracking whether we're inside a VA_OPT during a traversal of the tokens of a macro during...
void hasPlaceholderAfterHashhashAtStart()
bool isInVAOpt() const
Returns true if we have seen the VA_OPT and '(' but before having seen the matching ')'.
bool isVAOptToken(const Token &T) const
void sawHashOrHashAtBefore(const bool HasLeadingSpace, const bool IsHashAt)
SourceLocation getVAOptLoc() const
unsigned int getNumberOfTokensPriorToVAOpt() const
bool getLeadingSpaceForStringifiedToken() const
bool hasStringifyOrCharifyBefore() const
bool hasCharifyBefore() const
void sawOpeningParen(SourceLocation LParenLoc)
Call this function each time an lparen is seen.
void hasPlaceholderBeforeRParen()
const Token & getEOFTok() const
bool sawClosingParen()
Call this function each time an rparen is seen.
bool beginsWithPlaceholder() const
bool endsWithPlaceholder() const
void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc, const unsigned int NumPriorTokens)
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T