clang: lib/Lex/TokenLexer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

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"

31#include

32#include

33#include

34

35using namespace clang;

36

37

38

41

42

43 destroy();

44

45 Macro = MI;

46 ActualArgs = Actuals;

47 CurTokenIdx = 0;

48

49 ExpandLocStart = Tok.getLocation();

50 ExpandLocEnd = ELEnd;

51 AtStartOfLine = Tok.isAtStartOfLine();

52 HasLeadingSpace = Tok.hasLeadingSpace();

53 NextTokGetsSpace = false;

54 Tokens = &*Macro->tokens_begin();

55 OwnsTokens = false;

56 DisableMacroExpansion = false;

57 IsReinject = false;

58 NumTokens = Macro->tokens_end()-Macro->tokens_begin();

60

62 MacroStartSLocOffset = SM.getNextLocalOffset();

63

64 if (NumTokens > 0) {

65 assert(Tokens[0].getLocation().isValid());

66 assert((Tokens[0].getLocation().isFileID() || Tokens[0].is(tok::comment)) &&

67 "Macro defined in macro?");

68 assert(ExpandLocStart.isValid());

69

70

71

72

73

74 MacroDefStart = SM.getExpansionLoc(Tokens[0].getLocation());

75 MacroDefLength = Macro->getDefinitionLength(SM);

76 MacroExpansionStart = SM.createExpansionLoc(MacroDefStart,

77 ExpandLocStart,

78 ExpandLocEnd,

79 MacroDefLength);

80 }

81

82

83

84 if (Macro->isFunctionLike() && Macro->getNumParams())

85 ExpandFunctionArguments();

86

87

88

89

90 Macro->DisableMacro();

91}

92

93

94

96 bool disableMacroExpansion, bool ownsTokens,

97 bool isReinject) {

98 assert(!isReinject || disableMacroExpansion);

99

100

101 destroy();

102

103 Macro = nullptr;

104 ActualArgs = nullptr;

105 Tokens = TokArray;

106 OwnsTokens = ownsTokens;

107 DisableMacroExpansion = disableMacroExpansion;

108 IsReinject = isReinject;

109 NumTokens = NumToks;

110 CurTokenIdx = 0;

112 AtStartOfLine = false;

113 HasLeadingSpace = false;

114 NextTokGetsSpace = false;

116

117

118

119 if (NumToks != 0) {

122 }

123}

124

125void TokenLexer::destroy() {

126

127

128 if (OwnsTokens) {

129 delete [] Tokens;

130 Tokens = nullptr;

131 OwnsTokens = false;

132 }

133

134

135 if (ActualArgs) ActualArgs->destroy(PP);

136}

137

138bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(

141

142 if (!Macro->isVariadic() || MacroArgNo != Macro->getNumParams()-1)

143 return false;

144

145

146

147

148 if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)

149 return false;

150

151

152

153

154

155

156 if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode

157 && Macro->getNumParams() < 2)

158 return false;

159

160

161 if (ResultToks.empty() || !ResultToks.back().is(tok::comma))

162 return false;

163

164

165 if (HasPasteOperator)

166 PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);

167

168

169 ResultToks.pop_back();

170

171 if (!ResultToks.empty()) {

172

173

174

175

176 if (ResultToks.back().is(tok::hashhash))

177 ResultToks.pop_back();

178

179

181 }

182

183

184 NextTokGetsSpace = false;

185 return true;

186}

187

188void TokenLexer::stringifyVAOPTContents(

192 const unsigned int NumVAOptTokens = ResultToks.size() - NumToksPriorToVAOpt;

193 Token *const VAOPTTokens =

194 NumVAOptTokens ? &ResultToks[NumToksPriorToVAOpt] : nullptr;

195

196 SmallVector<Token, 64> ConcatenatedVAOPTResultToks;

197

198

199

200

201 for (unsigned int CurTokenIdx = 0; CurTokenIdx != NumVAOptTokens;

202 ++CurTokenIdx) {

203 if (VAOPTTokens[CurTokenIdx].is(tok::hashhash)) {

204 assert(CurTokenIdx != 0 &&

205 "Can not have __VAOPT__ contents begin with a ##");

206 Token &LHS = VAOPTTokens[CurTokenIdx - 1];

207 pasteTokens(LHS, llvm::ArrayRef(VAOPTTokens, NumVAOptTokens),

208 CurTokenIdx);

209

210 ConcatenatedVAOPTResultToks.back() = LHS;

211 if (CurTokenIdx == NumVAOptTokens)

212 break;

213 }

214 ConcatenatedVAOPTResultToks.push_back(VAOPTTokens[CurTokenIdx]);

215 }

216

217 ConcatenatedVAOPTResultToks.push_back(VCtx.getEOFTok());

218

219

220

221

222

223 const SourceLocation ExpansionLocStartWithinMacro =

224 getExpansionLocForMacroDefLoc(VCtx.getVAOptLoc());

225 const SourceLocation ExpansionLocEndWithinMacro =

226 getExpansionLocForMacroDefLoc(VAOPTClosingParenLoc);

227

229 &ConcatenatedVAOPTResultToks[0], PP, VCtx.hasCharifyBefore() ,

230 ExpansionLocStartWithinMacro, ExpansionLocEndWithinMacro);

231

234

236

237 ResultToks.resize(NumToksPriorToVAOpt + 1);

238 ResultToks.back() = StringifiedVAOPT;

239}

240

241

242

243void TokenLexer::ExpandFunctionArguments() {

244 SmallVector<Token, 128> ResultToks;

245

246

247

248

249 bool MadeChange = false;

250

251 std::optional CalledWithVariadicArguments;

252

253 VAOptExpansionContext VCtx(PP);

254

255 for (unsigned I = 0, E = NumTokens; I != E; ++I) {

256 const Token &CurTok = Tokens[I];

257

258

259

260

261

262

263 if (I != 0 && !Tokens[I-1].is(tok::hashhash) && CurTok.hasLeadingSpace())

264 NextTokGetsSpace = true;

265

267 MadeChange = true;

268 assert(Tokens[I + 1].is(tok::l_paren) &&

269 "__VA_OPT__ must be followed by '('");

270

271 ++I;

273 ResultToks.size());

274

275 continue;

276 }

277

278

279

281

282

283

284

285

286

287

288

289

290

291 if (Tokens[I].is(tok::l_paren))

293

294

295

296

298

299 if (!CalledWithVariadicArguments) {

300 CalledWithVariadicArguments =

301 ActualArgs->invokedWithVariadicArgument(Macro, PP);

302 }

303 if (!*CalledWithVariadicArguments) {

304

305 continue;

306 }

307

308

309 } else {

310

311

312

313

314

315

316

318

319

320

321

322

323 stringifyVAOPTContents(ResultToks, VCtx,

324 Tokens[I].getLocation());

325

326 } else if (

328

329

330

331

332

333 if (ResultToks.size() && ResultToks.back().is(tok::hashhash)) {

334 ResultToks.pop_back();

335 } else if ((I + 1 != E) && Tokens[I + 1].is(tok::hashhash)) {

336 ++I;

337 }

338 } else {

339

340

341

342

347 tok::hashhash) &&

348 "no token paste before __VA_OPT__");

349 ResultToks.erase(ResultToks.begin() +

351 }

352

353

355 Tokens[I + 1].is(tok::hashhash)) {

356 ++I;

357 }

358 }

360

361

362 continue;

363 }

364 }

365

366

367

368

369

370 if (CurTok.isOneOf(tok::hash, tok::hashat)) {

371 int ArgNo = Macro->getParameterNum(Tokens[I+1].getIdentifierInfo());

372 assert((ArgNo != -1 || VCtx.isVAOptToken(Tokens[I + 1])) &&

373 "Token following # is not an argument or __VA_OPT__!");

374

375 if (ArgNo == -1) {

376

378 CurTok.is(tok::hashat));

379 continue;

380 }

381

382 SourceLocation ExpansionLocStart =

383 getExpansionLocForMacroDefLoc(CurTok.getLocation());

384 SourceLocation ExpansionLocEnd =

385 getExpansionLocForMacroDefLoc(Tokens[I+1].getLocation());

386

387 bool Charify = CurTok.is(tok::hashat);

388 const Token *UnexpArg = ActualArgs->getUnexpArgument(ArgNo);

390 UnexpArg, PP, Charify, ExpansionLocStart, ExpansionLocEnd);

392

393

394

395 if (NextTokGetsSpace)

397

398 ResultToks.push_back(Res);

399 MadeChange = true;

400 ++I;

401 NextTokGetsSpace = false;

402 continue;

403 }

404

405

406 bool NonEmptyPasteBefore =

407 !ResultToks.empty() && ResultToks.back().is(tok::hashhash);

408 bool PasteBefore = I != 0 && Tokens[I-1].is(tok::hashhash);

409 bool PasteAfter = I+1 != E && Tokens[I+1].is(tok::hashhash);

410 bool RParenAfter = I+1 != E && Tokens[I+1].is(tok::r_paren);

411

412 assert((!NonEmptyPasteBefore || PasteBefore || VCtx.isInVAOpt()) &&

413 "unexpected ## in ResultToks");

414

415

416

418 int ArgNo = II ? Macro->getParameterNum(II) : -1;

419 if (ArgNo == -1) {

420

421 ResultToks.push_back(CurTok);

422

423 if (NextTokGetsSpace) {

425 NextTokGetsSpace = false;

426 } else if (PasteBefore && !NonEmptyPasteBefore)

428

429 continue;

430 }

431

432

433

434 MadeChange = true;

435

436

437

438

439

440 if (!PasteBefore && ActualArgs->isVarargsElidedUse() &&

441 MaybeRemoveCommaBeforeVaArgs(ResultToks,

442 false,

443 Macro, ArgNo, PP))

444 continue;

445

446

447

448

449 if (!PasteBefore && !PasteAfter) {

450 const Token *ResultArgToks;

451

452

453

454 const Token *ArgTok = ActualArgs->getUnexpArgument(ArgNo);

455 if (ActualArgs->ArgNeedsPreexpansion(ArgTok, PP))

456 ResultArgToks = &ActualArgs->getPreExpArgument(ArgNo, PP)[0];

457 else

458 ResultArgToks = ArgTok;

459

460

461 if (ResultArgToks->isNot(tok::eof)) {

462 size_t FirstResult = ResultToks.size();

464 ResultToks.append(ResultArgToks, ResultArgToks+NumToks);

465

466

467

468

469

470 if (PP.getLangOpts().MSVCCompat && NumToks == 1 &&

471 ResultToks.back().is(tok::comma))

473

474

475

476 for (Token &Tok : llvm::drop_begin(ResultToks, FirstResult))

477 if (Tok.is(tok::hashhash))

479

480 if(ExpandLocStart.isValid()) {

481 updateLocForMacroArgTokens(CurTok.getLocation(),

482 ResultToks.begin()+FirstResult,

483 ResultToks.end());

484 }

485

486

487

488

490 NextTokGetsSpace);

492 NextTokGetsSpace = false;

493 } else {

494

495

496

497 if (NonEmptyPasteBefore) {

498

499

500 assert(VCtx.isInVAOpt() && "should only happen inside a __VA_OPT__");

502 } else if (RParenAfter)

504 }

505 continue;

506 }

507

508

509

510 const Token *ArgToks = ActualArgs->getUnexpArgument(ArgNo);

512 if (NumToks) {

513 bool VaArgsPseudoPaste = false;

514

515

516

517

518 if (NonEmptyPasteBefore && ResultToks.size() >= 2 &&

519 ResultToks[ResultToks.size()-2].is(tok::comma) &&

520 (unsigned)ArgNo == Macro->getNumParams()-1 &&

521 Macro->isVariadic()) {

522 VaArgsPseudoPaste = true;

523

524 PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma);

525 }

526

527 ResultToks.append(ArgToks, ArgToks+NumToks);

528

529

530

531 for (Token &Tok : llvm::make_range(ResultToks.end() - NumToks,

532 ResultToks.end())) {

533 if (Tok.is(tok::hashhash))

535 }

536

537 if (ExpandLocStart.isValid()) {

538 updateLocForMacroArgTokens(CurTok.getLocation(),

539 ResultToks.end()-NumToks, ResultToks.end());

540 }

541

542

543

544

545

546 if (!VaArgsPseudoPaste) {

547 ResultToks[ResultToks.size() - NumToks].setFlagValue(Token::StartOfLine,

548 false);

549 ResultToks[ResultToks.size() - NumToks].setFlagValue(

551 }

552

553 NextTokGetsSpace = false;

554 continue;

555 }

556

557

558

559

560

561 if (PasteAfter) {

562

563

564 ++I;

565 continue;

566 }

567

568 if (RParenAfter && !NonEmptyPasteBefore)

570

571

572

573

574 assert(PasteBefore);

575 if (NonEmptyPasteBefore) {

576 assert(ResultToks.back().is(tok::hashhash));

577

578

579

580

583 ResultToks.pop_back();

584 else

586 }

587

588

589

590

591

592 if (ActualArgs->isVarargsElidedUse())

593 MaybeRemoveCommaBeforeVaArgs(ResultToks,

594 true,

595 Macro, ArgNo, PP);

596 }

597

598

599 if (MadeChange) {

600 assert(!OwnsTokens && "This would leak if we already own the token list");

601

602 NumTokens = ResultToks.size();

603

604

605 Tokens = PP.cacheMacroExpandedTokens(this, ResultToks);

606

607

608 OwnsTokens = false;

609 }

610}

611

612

614 const Token &SecondTok) {

615 return FirstTok.is(tok::identifier) &&

618}

619

620

622

623 if (isAtEnd()) {

624

625

626 if (Macro) Macro->EnableMacro();

627

628 Tok.startToken();

631 if (CurTokenIdx == 0)

633 return PP.HandleEndOfTokenLexer(Tok);

634 }

635

637

638

639

640 bool isFirstToken = CurTokenIdx == 0;

641

642

643 Tok = Tokens[CurTokenIdx++];

644 if (IsReinject)

646

647 bool TokenIsFromPaste = false;

648

649

650

651 if (!isAtEnd() && Macro &&

652 (Tokens[CurTokenIdx].is(tok::hashhash) ||

653

654

655

656 (PP.getLangOpts().MSVCCompat &&

658

659

660 if (pasteTokens(Tok))

661 return true;

662

663 TokenIsFromPaste = true;

664 }

665

666

667

668

669

670

671 if (ExpandLocStart.isValid() &&

672

673 SM.isBeforeInSLocAddrSpace(Tok.getLocation(), MacroStartSLocOffset)) {

675 if (Tok.is(tok::comment)) {

676 instLoc = SM.createExpansionLoc(Tok.getLocation(),

677 ExpandLocStart,

678 ExpandLocEnd,

679 Tok.getLength());

680 } else {

681 instLoc = getExpansionLocForMacroDefLoc(Tok.getLocation());

682 }

683

684 Tok.setLocation(instLoc);

685 }

686

687

688

689 if (isFirstToken) {

692 } else {

693

694

697 }

698 AtStartOfLine = false;

699 HasLeadingSpace = false;

700

701

702 if (Tok.isAnnotation() && Tok.getIdentifierInfo() != nullptr) {

703

704

707

708

709

710

711 if (II->isPoisoned() && TokenIsFromPaste) {

712 PP.HandlePoisonedIdentifier(Tok);

713 }

714

716 return PP.HandleIdentifier(Tok);

717 }

718

719

720 return true;

721}

722

723bool TokenLexer::pasteTokens(Token &Tok) {

724 return pasteTokens(Tok, llvm::ArrayRef(Tokens, NumTokens), CurTokenIdx);

725}

726

727

728

729

730

732 unsigned int &CurIdx) {

733 assert(CurIdx > 0 && "## can not be the first token within tokens");

734 assert((TokenStream[CurIdx].is(tok::hashhash) ||

737 "Token at this Index must be ## or part of the MSVC 'L "

738 "#macro-arg' pasting pair");

739

740

741

742

743 if (PP.getLangOpts().MicrosoftExt && (CurIdx >= 2) &&

744 TokenStream[CurIdx - 2].is(tok::hashhash))

746

748 const char *ResultTokStrPtr = nullptr;

751 bool HasUCNs = false;

752

753 auto IsAtEnd = [&TokenStream, &CurIdx] {

754 return TokenStream.size() == CurIdx;

755 };

756

757 do {

758

759 PasteOpLoc = TokenStream[CurIdx].getLocation();

760 if (TokenStream[CurIdx].is(tok::hashhash))

761 ++CurIdx;

762 assert(!IsAtEnd() && "No token on the RHS of a paste operator!");

763

764

765 const Token &RHS = TokenStream[CurIdx];

766

767

768

770

771

772 const char *BufPtr = &Buffer[0];

774 unsigned LHSLen = PP.getSpelling(LHSTok, BufPtr, &Invalid);

775 if (BufPtr != &Buffer[0])

776 memcpy(&Buffer[0], BufPtr, LHSLen);

778 return true;

779

780 BufPtr = Buffer.data() + LHSLen;

781 unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid);

783 return true;

784 if (RHSLen && BufPtr != &Buffer[LHSLen])

785

786 memcpy(&Buffer[LHSLen], BufPtr, RHSLen);

787

788

789 Buffer.resize(LHSLen+RHSLen);

790

791

792

793 Token ResultTokTmp;

795

796

797

798 ResultTokTmp.setKind(tok::string_literal);

799 PP.CreateString(Buffer, ResultTokTmp);

800 SourceLocation ResultTokLoc = ResultTokTmp.getLocation();

802

803

805

807

808

809 PP.IncrementPasteCounter(true);

811 Result.setKind(tok::raw_identifier);

812 Result.setRawIdentifierData(ResultTokStrPtr);

813 Result.setLocation(ResultTokLoc);

814 Result.setLength(LHSLen+RHSLen);

815 } else {

816 PP.IncrementPasteCounter(false);

817

818 assert(ResultTokLoc.isFileID() &&

819 "Should be a raw location into scratch buffer");

820 SourceManager &SourceMgr = PP.getSourceManager();

821 FileID LocFileID = SourceMgr.getFileID(ResultTokLoc);

822

824 const char *ScratchBufStart

827 return false;

828

829

830

832 PP.getLangOpts(), ScratchBufStart,

833 ResultTokStrPtr, ResultTokStrPtr+LHSLen+RHSLen);

834

835

836

837

838

840

841

842

844

845

846

847

849

850

851 SourceManager &SM = PP.getSourceManager();

852 SourceLocation Loc =

853 SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2);

854

855

856

857 if (PP.getLangOpts().MicrosoftExt && LHSTok.is(tok::slash) &&

858 RHS.is(tok::slash)) {

859 HandleMicrosoftCommentPaste(LHSTok, Loc);

860 return true;

861 }

862

863

864 if (!PP.getLangOpts().AsmPreprocessor) {

865

866

867

868 PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::ext_pp_bad_paste_ms

869 : diag::err_pp_bad_paste)

870 << Buffer;

871 }

872

873

874 break;

875 }

876

877

878

879 if (Result.is(tok::hashhash))

880 Result.setKind(tok::unknown);

881 }

882

883

886

887

888 ++CurIdx;

889

890

891 HasUCNs = LHSTok.hasUCN() || RHS.hasUCN() || HasUCNs;

893 } while (!IsAtEnd() && TokenStream[CurIdx].is(tok::hashhash));

894

895 SourceLocation EndLoc = TokenStream[CurIdx - 1].getLocation();

896

897

898

899

900

901

902 SourceManager &SM = PP.getSourceManager();

904 StartLoc = getExpansionLocForMacroDefLoc(StartLoc);

906 EndLoc = getExpansionLocForMacroDefLoc(EndLoc);

907 FileID MacroFID = SM.getFileID(MacroExpansionStart);

908 while (SM.getFileID(StartLoc) != MacroFID)

909 StartLoc = SM.getImmediateExpansionRange(StartLoc).getBegin();

910 while (SM.getFileID(EndLoc) != MacroFID)

911 EndLoc = SM.getImmediateExpansionRange(EndLoc).getEnd();

912

915

916

917

918

919 if (LHSTok.is(tok::raw_identifier)) {

920

921

922

923

924 if (HasUCNs)

926

927

928

929 PP.LookUpIdentifierInfo(LHSTok);

930 }

931 return false;

932}

933

934

935

936

938

939 if (isAtEnd())

940 return std::nullopt;

941 return Tokens[CurTokenIdx];

942}

943

944

945

947 return Tokens[NumTokens-1].is(tok::eod) && !isAtEnd();

948}

949

950

951

952

953

954

956 PP.Diag(OpLoc, diag::ext_comment_paste_microsoft);

957

958

959

960

961

962

963 assert(Macro && "Token streams can't paste comments");

964 Macro->EnableMacro();

965

967}

968

969

970

971

972

974TokenLexer::getExpansionLocForMacroDefLoc(SourceLocation loc) const {

975 assert(ExpandLocStart.isValid() && MacroExpansionStart.isValid() &&

976 "Not appropriate for token streams");

978

980 assert(SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength) &&

981 "Expected loc to come from the macro definition");

982

984 SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength, &relativeOffset);

986}

987

988

989

990

991

992

993

994

995

996

999 Token *&begin_tokens,

1000 Token * end_tokens) {

1001 assert(begin_tokens + 1 < end_tokens);

1005

1007

1008

1009

1013 return Distance <= MaxDistance;

1014 };

1015

1016

1017

1018

1020

1021

1022 Partition = All.take_while([&](const Token &T) {

1023 return T.getLocation().isFileID() && NearLast(T.getLocation());

1024 });

1025 } else {

1026

1027

1028 FileID BeginFID = SM.getFileID(BeginLoc);

1030 SM.getComposedLoc(BeginFID, SM.getFileIDSize(BeginFID));

1031 Partition = All.take_while([&](const Token &T) {

1032

1033

1034

1035

1036

1037

1038

1039

1040 return T.getLocation() >= BeginLoc && T.getLocation() <= Limit

1041 && NearLast(T.getLocation());

1042 });

1043 }

1044 assert(!Partition.empty());

1045

1046

1047

1049 Partition.back().getEndLoc().getRawEncoding() -

1050 Partition.front().getLocation().getRawEncoding();

1051

1053 SM.createMacroArgExpansionLoc(BeginLoc, ExpandLoc, FullLength);

1054

1055#ifdef EXPENSIVE_CHECKS

1056 assert(llvm::all_of(Partition.drop_front(),

1057 [&SM, ID = SM.getFileID(Partition.front().getLocation())](

1059 return ID == SM.getFileID(T.getLocation());

1060 }) &&

1061 "Must have the same FIleID!");

1062#endif

1063

1064

1065 for (Token& T : Partition) {

1067 T.getLocation().getRawEncoding() - BeginLoc.getRawEncoding();

1069 }

1070 begin_tokens = &Partition.back() + 1;

1071}

1072

1073

1074

1075

1076

1077

1078void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,

1079 Token *begin_tokens,

1080 Token *end_tokens) {

1081 SourceManager &SM = PP.getSourceManager();

1082

1083 SourceLocation ExpandLoc =

1084 getExpansionLocForMacroDefLoc(ArgIdSpellLoc);

1085

1086 while (begin_tokens < end_tokens) {

1087

1088 if (end_tokens - begin_tokens == 1) {

1089 Token &Tok = *begin_tokens;

1091 ExpandLoc,

1093 return;

1094 }

1095

1097 }

1098}

1099

1100void TokenLexer::PropagateLineStartLeadingSpaceInfo(Token &Result) {

1101 AtStartOfLine = Result.isAtStartOfLine();

1102 HasLeadingSpace = Result.hasLeadingSpace();

1103}

Defines the Diagnostic-related interfaces.

bool is(tok::TokenKind Kind) const

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.

Definition TokenLexer.cpp:613

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,...

Definition TokenLexer.cpp:997

__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.

Definition TokenLexer.cpp:946

bool Lex(Token &Tok)

Lex and return a token from this macro stream.

Definition TokenLexer.cpp:621

std::optional< Token > peekNextPPToken() const

If TokenLexer::isAtEnd returns true(the next token lexed will pop thismacro off the expansion stack),...

Definition TokenLexer.cpp:937

void Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, MacroArgs *Actuals)

Initialize this TokenLexer to expand from the specified macro with the specified argument information...

Definition TokenLexer.cpp:39

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