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

1

2

3

4

5

6

7

8

9

10

11

12

13

37#include "llvm/ADT/ArrayRef.h"

38#include "llvm/ADT/STLExtras.h"

39#include "llvm/ADT/ScopeExit.h"

40#include "llvm/ADT/SmallVector.h"

41#include "llvm/ADT/StringExtras.h"

42#include "llvm/ADT/StringRef.h"

43#include "llvm/ADT/StringSwitch.h"

44#include "llvm/Support/ErrorHandling.h"

45#include "llvm/Support/Path.h"

46#include "llvm/Support/SaveAndRestore.h"

47#include

48#include

49#include

50#include

51#include

52#include

53

54using namespace clang;

55

56

57

58

59

61 static_assert(std::is_trivially_destructible_v, "");

63}

64

68}

69

71Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) {

73}

74

77 bool isPublic) {

79}

80

81

82

85

88 while (Tmp.isNot(tok::eod)) {

89 assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens");

91 }

93 return Res;

94}

95

96

99 MD_KeywordDef,

100 MD_ReservedMacro

102

103

104

110

112

113

114

115

116

117 static constexpr StringRef ReservedMacro[] = {

118 "_ATFILE_SOURCE",

119 "_BSD_SOURCE",

120 "_CRT_NONSTDC_NO_WARNINGS",

121 "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",

122 "_CRT_SECURE_NO_WARNINGS",

123 "_FILE_OFFSET_BITS",

124 "_FORTIFY_SOURCE",

125 "_GLIBCXX_ASSERTIONS",

126 "_GLIBCXX_CONCEPT_CHECKS",

127 "_GLIBCXX_DEBUG",

128 "_GLIBCXX_DEBUG_PEDANTIC",

129 "_GLIBCXX_PARALLEL",

130 "_GLIBCXX_PARALLEL_ASSERTIONS",

131 "_GLIBCXX_SANITIZE_VECTOR",

132 "_GLIBCXX_USE_CXX11_ABI",

133 "_GLIBCXX_USE_DEPRECATED",

134 "_GNU_SOURCE",

135 "_ISOC11_SOURCE",

136 "_ISOC95_SOURCE",

137 "_ISOC99_SOURCE",

138 "_LARGEFILE64_SOURCE",

139 "_POSIX_C_SOURCE",

140 "_REENTRANT",

141 "_SVID_SOURCE",

142 "_THREAD_SAFE",

143 "_XOPEN_SOURCE",

144 "_XOPEN_SOURCE_EXTENDED",

145 "__STDCPP_WANT_MATH_SPEC_FUNCS__",

146 "__STDC_FORMAT_MACROS",

147 };

148 return std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),

149 MacroName);

150}

151

154 const StringRef MacroName) {

155

156

158 return true;

159

161 return false;

162

163

164 if (MacroName.starts_with("__STDC"))

165 return true;

166

167 if (MacroName == "__cplusplus")

168 return true;

169

170 if (MacroName.starts_with("__cpp"))

171 return true;

172

173 return false;

174}

175

183 if (Lang.CPlusPlus11 && (Text == "override" || Text == "final"))

186}

187

190

194}

195

196

197

198

199

200

202

203

204 if (::llvm::sys::path::begin(Include)->equals_insensitive("boost"))

205 return true;

206

207

208

209 static const size_t MaxStdHeaderNameLen = 18u;

210 if (Include.size() > MaxStdHeaderNameLen)

211 return false;

212

213

215 for (char &Ch : LowerInclude) {

216

217 if (static_cast<unsigned char>(Ch) > 0x7f)

218 return false;

219

220 if (Ch >= 'A' && Ch <= 'Z')

221 Ch += 'a' - 'A';

222

223 else if (::llvm::sys::path::is_separator(Ch))

224 Ch = '/';

225 }

226

227

228 return llvm::StringSwitch(LowerInclude)

229

230 .Cases("assert.h", "complex.h", "ctype.h", "errno.h", "fenv.h", true)

231 .Cases("float.h", "inttypes.h", "iso646.h", "limits.h", "locale.h", true)

232 .Cases("math.h", "setjmp.h", "signal.h", "stdalign.h", "stdarg.h", true)

233 .Cases("stdatomic.h", "stdbool.h", "stdckdint.h", "stddef.h", true)

234 .Cases("stdint.h", "stdio.h", "stdlib.h", "stdnoreturn.h", true)

235 .Cases("string.h", "tgmath.h", "threads.h", "time.h", "uchar.h", true)

236 .Cases("wchar.h", "wctype.h", true)

237

238

239 .Cases("cassert", "ccomplex", "cctype", "cerrno", "cfenv", true)

240 .Cases("cfloat", "cinttypes", "ciso646", "climits", "clocale", true)

241 .Cases("cmath", "csetjmp", "csignal", "cstdalign", "cstdarg", true)

242 .Cases("cstdbool", "cstddef", "cstdint", "cstdio", "cstdlib", true)

243 .Cases("cstring", "ctgmath", "ctime", "cuchar", "cwchar", true)

244 .Case("cwctype", true)

245

246

247 .Cases("algorithm", "fstream", "list", "regex", "thread", true)

248 .Cases("array", "functional", "locale", "scoped_allocator", "tuple", true)

249 .Cases("atomic", "future", "map", "set", "type_traits", true)

250 .Cases("bitset", "initializer_list", "memory", "shared_mutex", "typeindex", true)

251 .Cases("chrono", "iomanip", "mutex", "sstream", "typeinfo", true)

252 .Cases("codecvt", "ios", "new", "stack", "unordered_map", true)

253 .Cases("complex", "iosfwd", "numeric", "stdexcept", "unordered_set", true)

254 .Cases("condition_variable", "iostream", "ostream", "streambuf", "utility", true)

255 .Cases("deque", "istream", "queue", "string", "valarray", true)

256 .Cases("exception", "iterator", "random", "strstream", "vector", true)

257 .Cases("forward_list", "limits", "ratio", "system_error", true)

258

259

260 .Cases("aio.h", "arpa/inet.h", "cpio.h", "dirent.h", "dlfcn.h", true)

261 .Cases("fcntl.h", "fmtmsg.h", "fnmatch.h", "ftw.h", "glob.h", true)

262 .Cases("grp.h", "iconv.h", "langinfo.h", "libgen.h", "monetary.h", true)

263 .Cases("mqueue.h", "ndbm.h", "net/if.h", "netdb.h", "netinet/in.h", true)

264 .Cases("netinet/tcp.h", "nl_types.h", "poll.h", "pthread.h", "pwd.h", true)

265 .Cases("regex.h", "sched.h", "search.h", "semaphore.h", "spawn.h", true)

266 .Cases("strings.h", "stropts.h", "sys/ipc.h", "sys/mman.h", "sys/msg.h", true)

267 .Cases("sys/resource.h", "sys/select.h", "sys/sem.h", "sys/shm.h", "sys/socket.h", true)

268 .Cases("sys/stat.h", "sys/statvfs.h", "sys/time.h", "sys/times.h", "sys/types.h", true)

269 .Cases("sys/uio.h", "sys/un.h", "sys/utsname.h", "sys/wait.h", "syslog.h", true)

270 .Cases("tar.h", "termios.h", "trace.h", "ulimit.h", true)

271 .Cases("unistd.h", "utime.h", "utmpx.h", "wordexp.h", true)

272 .Default(false);

273}

274

275

276

277

278

279

280

281

282

283static std::optional

284findSimilarStr(StringRef LHS, const std::vector &Candidates) {

285

286

287 for (StringRef C : Candidates) {

288 if (LHS.equals_insensitive(C)) {

289 return C;

290 }

291 }

292

293

294

295

296 size_t Length = LHS.size();

297 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;

298

299 std::optional<std::pair<StringRef, size_t>> SimilarStr;

300 for (StringRef C : Candidates) {

301 size_t CurDist = LHS.edit_distance(C, true);

302 if (CurDist <= MaxDist) {

303 if (!SimilarStr) {

304

305 SimilarStr = {C, CurDist};

306 } else if (CurDist < SimilarStr->second) {

307

308 SimilarStr = {C, CurDist};

309 }

310 }

311 }

312

313 if (SimilarStr) {

314 return SimilarStr->first;

315 } else {

316 return std::nullopt;

317 }

318}

319

321 bool *ShadowFlag) {

322

323 if (MacroNameTok.is(tok::eod))

324 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);

325

327 if (!II)

328 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);

329

331

332

334 ? diag::ext_pp_operator_used_as_macro_name

335 : diag::err_pp_operator_used_as_macro_name)

336 << II << MacroNameTok.getKind();

337

338

339 }

340

342

343 return Diag(MacroNameTok, diag::err_defined_macro_name);

344 }

345

346

347

349 if (ShadowFlag)

350 *ShadowFlag = false;

352 (SourceMgr.getBufferName(MacroNameLoc) != "")) {

354 if (isDefineUndef == MU_Define) {

356 }

357 else if (isDefineUndef == MU_Undef)

360

361

362

363 if (ShadowFlag)

364 *ShadowFlag = true;

365 }

367 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);

368 }

369

370

371 return false;

372}

373

374

375

376

377

378

379

380

381

382

383void Preprocessor::ReadMacroName(Token &MacroNameTok, MacroUse isDefineUndef,

384 bool *ShadowFlag) {

385

387

388 if (MacroNameTok.is(tok::code_completion)) {

389 if (CodeComplete)

393 }

394

395 if (CheckMacroName(MacroNameTok, isDefineUndef, ShadowFlag))

396 return;

397

398

399

400 if (MacroNameTok.isNot(tok::eod)) {

401 MacroNameTok.setKind(tok::eod);

403 }

404}

405

406

407

408

409

410

411

413 bool EnableMacros) {

415

416

417

418 if (EnableMacros)

419 Lex(Tmp);

420 else

422

423

424

425 while (Tmp.is(tok::comment))

427

428 if (Tmp.is(tok::eod))

430

431

432

433

434

436 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&

437 !CurTokenLexer)

439 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;

441}

442

443void Preprocessor::SuggestTypoedDirective(const Token &Tok,

445

446

447 if (getLangOpts().AsmPreprocessor) return;

448

449 std::vector Candidates = {

450 "if", "ifdef", "ifndef", "elif", "else", "endif"

451 };

452 if (LangOpts.C23 || LangOpts.CPlusPlus23)

453 Candidates.insert(Candidates.end(), {"elifdef", "elifndef"});

454

456

461 StringRef SuggValue = *Sugg;

462

464 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;

465 }

466}

467

468

469

470

471

472

473

474

475

476void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,

478 bool FoundNonSkipPortion,

479 bool FoundElse,

481

482

483

484

485

486

487

488

489 assert(!SkippingExcludedConditionalBlock &&

490 "calling SkipExcludedConditionalBlock recursively");

492

493 ++NumSkipped;

494 assert(!CurTokenLexer && "Conditional PP block cannot appear in a macro!");

495 assert(CurPPLexer && "Conditional PP block must be in a file!");

496 assert(CurLexer && "Conditional PP block but no current lexer set!");

497

498 if (PreambleConditionalStack.reachedEOFWhileSkipping())

499 PreambleConditionalStack.clearSkipInfo();

500 else

502 FoundNonSkipPortion, FoundElse);

503

504

505

509

510

511

512 struct SkippingRangeStateTy {

514

515 const char *BeginPtr = nullptr;

516 unsigned *SkipRangePtr = nullptr;

517

518 SkippingRangeStateTy(Preprocessor &PP) : PP(PP) {}

519

520 void beginLexPass() {

521 if (BeginPtr)

522 return;

523

524

525

526 BeginPtr = PP.CurLexer->getBufferLocation();

527 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];

528 if (*SkipRangePtr) {

529 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,

530 true);

531 }

532 }

533

534 void endLexPass(const char *Hashptr) {

535 if (!BeginPtr) {

536

537 assert(PP.CurLexer->isDependencyDirectivesLexer());

538 return;

539 }

540

541

542 if (!*SkipRangePtr) {

543 *SkipRangePtr = Hashptr - BeginPtr;

544 }

545 assert(*SkipRangePtr == unsigned(Hashptr - BeginPtr));

546 BeginPtr = nullptr;

547 SkipRangePtr = nullptr;

548 }

549 } SkippingRangeState(*this);

550

551 while (true) {

552 if (CurLexer->isDependencyDirectivesLexer()) {

553 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);

554 } else {

555 SkippingRangeState.beginLexPass();

556 while (true) {

557 CurLexer->Lex(Tok);

558

559 if (Tok.is(tok::code_completion)) {

561 if (CodeComplete)

563 continue;

564 }

565

566

567 if (Tok.is(tok::eof)) {

568

569

570

571 if (PreambleConditionalStack.isRecording())

572 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,

573 FoundNonSkipPortion,

574 FoundElse, ElseLoc);

575 break;

576 }

577

578

580 continue;

581

582 break;

583 }

584 }

585 if (Tok.is(tok::eof))

586 break;

587

588

589

590

592 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);

593

594 assert(Tok.is(tok::hash));

595 const char *Hashptr = CurLexer->getBufferLocation() - Tok.getLength();

596 assert(CurLexer->getSourceLocation(Hashptr) == Tok.getLocation());

597

598

600

601

602

603 if (Tok.isNot(tok::raw_identifier)) {

605

606 if (CurLexer) CurLexer->resetExtendedTokenMode();

607 continue;

608 }

609

610

611

612

613

614

616

617 char FirstChar = RI[0];

618 if (FirstChar >= 'a' && FirstChar <= 'z' &&

619 FirstChar != 'i' && FirstChar != 'e') {

621

622 if (CurLexer) CurLexer->resetExtendedTokenMode();

623 continue;

624 }

625

626

627

628

629 char DirectiveBuf[20];

633 } else {

634 std::string DirectiveStr = getSpelling(Tok);

635 size_t IdLen = DirectiveStr.size();

636 if (IdLen >= 20) {

638

639 if (CurLexer) CurLexer->resetExtendedTokenMode();

640 continue;

641 }

642 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);

643 Directive = StringRef(DirectiveBuf, IdLen);

644 }

645

646 if (Directive.starts_with("if")) {

648 if (Sub.empty() ||

649 Sub == "def" ||

650 Sub == "ndef") {

651

652

655 false,

656 false);

657 } else {

658 SuggestTypoedDirective(Tok, Directive);

659 }

660 } else if (Directive[0] == 'e') {

662 if (Sub == "ndif") {

664 CondInfo.WasSkipping = true;

666 (void)InCond;

667 assert(!InCond && "Can't be skipping if not in a conditional!");

668

669

671 SkippingRangeState.endLexPass(Hashptr);

672

673

677 if (Callbacks)

679 break;

680 } else {

682 }

683 } else if (Sub == "lse") {

684

685

686

688

690 SkippingRangeState.endLexPass(Hashptr);

691

692

694 Diag(Tok, diag::pp_err_else_after_else);

695

696

698

699

700

703

704

708 if (Callbacks)

710 break;

711 } else {

713 }

714 } else if (Sub == "lif") {

716

718 SkippingRangeState.endLexPass(Hashptr);

719

720

722 Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif;

723

724

725

727

728

729

730

732 } else {

733

734

735 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");

738 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);

739

740 if (!CurPPLexer)

741 return;

742 const bool CondValue = DER.Conditional;

744 if (Callbacks) {

745 Callbacks->Elif(

749 }

750

751 if (CondValue) {

753 break;

754 }

755 }

756 } else if (Sub == "lifdef" ||

757 Sub == "lifndef") {

758 bool IsElifDef = Sub == "lifdef";

760 Token DirectiveToken = Tok;

761

763 SkippingRangeState.endLexPass(Hashptr);

764

765

766

767 unsigned DiagID;

768 if (LangOpts.CPlusPlus)

769 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive

770 : diag::ext_cxx23_pp_directive;

771 else

772 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive

773 : diag::ext_c23_pp_directive;

775

776

778 Diag(Tok, diag::pp_err_elif_after_else)

780

781

782

784

785

786

787

789 } else {

790

791

792 assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");

794 Token MacroNameTok;

795 ReadMacroName(MacroNameTok);

797

798

799

800 if (MacroNameTok.is(tok::eod)) {

801

802

803 continue;

804 }

805

807

809

812 MacroInfo *MI = MD.getMacroInfo();

813

814 if (Callbacks) {

815 if (IsElifDef) {

816 Callbacks->Elifdef(DirectiveToken.getLocation(), MacroNameTok,

817 MD);

818 } else {

819 Callbacks->Elifndef(DirectiveToken.getLocation(), MacroNameTok,

820 MD);

821 }

822 }

823

824 if (static_cast<bool>(MI) == IsElifDef) {

826 break;

827 }

828 }

829 } else {

830 SuggestTypoedDirective(Tok, Directive);

831 }

832 } else {

833 SuggestTypoedDirective(Tok, Directive);

834 }

835

837

838 if (CurLexer) CurLexer->resetExtendedTokenMode();

839 }

840

841

842

843

845

846

847

849 Callbacks->SourceRangeSkipped(

851 ? endLoc

854}

855

857 bool AllowTextual) {

859

860

863

867 }

868 }

869

870

871

873 ? nullptr

875}

876

881 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);

882

883

884

885

886

889 auto ID = SM.getFileID(SM.getExpansionLoc(Loc));

890 auto FE = SM.getFileEntryRefForID(ID);

891 if (!FE)

892 break;

893

894

895

896 HeaderInfo.hasModuleMap(FE->getName(), nullptr,

898

899 bool InPrivateHeader = false;

901 if (!Header.isAccessibleFrom(IncM)) {

902

903

904

905

906 InPrivateHeader = true;

907 continue;

908 }

909

910

912 continue;

913

914

915

917 continue;

918

919

920

921

923 return std::nullopt;

924

925

926

927

928 return *FE;

929 }

930

931

932

933 if (InPrivateHeader)

934 return std::nullopt;

935

936

937

938

940 return *FE;

941

942 Loc = SM.getIncludeLoc(ID);

943 }

944

945 return std::nullopt;

946}

947

954 bool *IsFrameworkFound, bool SkipCache, bool OpenFile, bool CacheFailures) {

957

959 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);

960

961

962

964 bool BuildSystemModule = false;

965 if (!FromDir && !FromFile) {

968

969

970

971

972

973

974

975

976

977

978

979

980

981 if (!FileEnt) {

982 if (FID == SourceMgr.getMainFileID() && MainFileDir) {

983 auto IncludeDir =

987 : MainFileDir;

988 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));

993 Includers.push_back(std::make_pair(*FileEnt, *CWD));

994 }

995 } else {

996 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));

997 }

998

999

1000

1001

1002 if (LangOpts.MSVCCompat && !isAngled) {

1003 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {

1004 if (IsFileLexer(ISEntry))

1005 if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))

1006 Includers.push_back(std::make_pair(*FileEnt, FileEnt->getDir()));

1007 }

1008 }

1009 }

1010

1011 CurDir = CurDirLookup;

1012

1013 if (FromFile) {

1014

1015

1019 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,

1020 Includers, SearchPath, RelativePath, RequestingModule,

1021 SuggestedModule, nullptr,

1022 nullptr, SkipCache)) {

1023

1024 TmpFromDir = TmpCurDir;

1025 ++TmpFromDir;

1026 if (&FE->getFileEntry() == FromFile) {

1027

1028 FromDir = TmpFromDir;

1029 CurDir = TmpCurDir;

1030 break;

1031 }

1032 }

1033 }

1034

1035

1037 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,

1038 RelativePath, RequestingModule, SuggestedModule, IsMapped,

1039 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);

1040 if (FE)

1041 return FE;

1042

1044

1045

1046

1047 if (IsFileLexer()) {

1048 if ((CurFileEnt = CurPPLexer->getFileEntry())) {

1050 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,

1051 SuggestedModule)) {

1052 return FE;

1053 }

1054 }

1055 }

1056

1057 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {

1058 if (IsFileLexer(ISEntry)) {

1059 if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {

1061 Filename, *CurFileEnt, SearchPath, RelativePath,

1062 RequestingModule, SuggestedModule)) {

1063 return FE;

1064 }

1065 }

1066 }

1067 }

1068

1069

1070 return std::nullopt;

1071}

1072

1075 const FileEntry *LookupFromFile) {

1077 if (llvm::sys::path::is_absolute(Filename)) {

1078

1080 Filename, OpenFile, true, false);

1081 return llvm::expectedToOptional(std::move(ShouldBeEntry));

1082 }

1083

1085 StringRef StartingFrom, StringRef FileName,

1086 bool RemoveInitialFileComponentFromLookupPath) {

1087 llvm::sys::path::native(StartingFrom, LookupPath);

1088 if (RemoveInitialFileComponentFromLookupPath)

1089 llvm::sys::path::remove_filename(LookupPath);

1090 if (!LookupPath.empty() &&

1091 !llvm::sys::path::is_separator(LookupPath.back())) {

1092 LookupPath.push_back(llvm::sys::path::get_separator().front());

1093 }

1095 };

1096

1097

1099

1100 if (!isAngled) {

1101 if (LookupFromFile) {

1102

1104 if (!FullFileDir.empty()) {

1105 SeparateComponents(LookupPath, FullFileDir, Filename, true);

1107 LookupPath, OpenFile, true, false);

1108 if (ShouldBeEntry)

1109 return llvm::expectedToOptional(std::move(ShouldBeEntry));

1110 llvm::consumeError(ShouldBeEntry.takeError());

1111 }

1112 }

1113

1114

1115 LookupPath.clear();

1117 if (MaybeWorkingDirEntry) {

1119 StringRef WorkingDir = WorkingDirEntry.getName();

1120 if (!WorkingDir.empty()) {

1121 SeparateComponents(LookupPath, WorkingDir, Filename, false);

1123 LookupPath, OpenFile, true, false);

1124 if (ShouldBeEntry)

1125 return llvm::expectedToOptional(std::move(ShouldBeEntry));

1126 llvm::consumeError(ShouldBeEntry.takeError());

1127 }

1128 }

1129 }

1130

1131 for (const auto &Entry : PPOpts->EmbedEntries) {

1132 LookupPath.clear();

1133 SeparateComponents(LookupPath, Entry, Filename, false);

1135 LookupPath, OpenFile, true, false);

1136 if (ShouldBeEntry)

1137 return llvm::expectedToOptional(std::move(ShouldBeEntry));

1138 llvm::consumeError(ShouldBeEntry.takeError());

1139 }

1140 return std::nullopt;

1141}

1142

1143

1144

1145

1146

1148public:

1150 : PP(pp), save(pp->DisableMacroExpansion) {

1151 if (pp->MacroExpansionInDirectivesOverride)

1152 pp->DisableMacroExpansion = false;

1153 }

1154

1156 PP->DisableMacroExpansion = save;

1157 }

1158

1159private:

1161 bool save;

1162};

1163

1164

1165

1166

1167

1168

1169

1173 if (II->getPPKeywordID() == tok::pp_define) {

1174 return HandleDefineDirective(Result,

1175 false);

1176 }

1177 if (SkippingUntilPCHThroughHeader &&

1178 II->getPPKeywordID() == tok::pp_include) {

1179 return HandleIncludeDirective(HashLoc, Result);

1180 }

1181 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {

1183 auto *II = Result.getIdentifierInfo();

1184 if (II && II->getName() == "hdrstop")

1186 }

1187 }

1189}

1190

1191

1192

1193

1194

1196

1197

1198

1199

1200

1202 if (CurLexer) CurLexer->SetKeepWhitespaceMode(false);

1203

1204 bool ImmediatelyAfterTopLevelIfndef =

1207

1208 ++NumDirectives;

1209

1210

1211

1212

1214

1215

1217

1218

1219

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230 if (InMacroArgs) {

1232 switch (II->getPPKeywordID()) {

1233 case tok::pp_include:

1234 case tok::pp_import:

1235 case tok::pp_include_next:

1236 case tok::pp___include_macros:

1237 case tok::pp_pragma:

1238 case tok::pp_embed:

1239 Diag(Result, diag::err_embedded_directive) << II->getName();

1240 Diag(*ArgMacro, diag::note_macro_expansion_here)

1243 return;

1244 default:

1245 break;

1246 }

1247 }

1248 Diag(Result, diag::ext_embedded_directive);

1249 }

1250

1251

1252

1254

1255 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)

1257

1258 switch (Result.getKind()) {

1259 case tok::eod:

1260

1261

1262

1264 return;

1265 case tok::code_completion:

1267 if (CodeComplete)

1270 return;

1271 case tok::numeric_constant:

1272

1273

1274

1277 break;

1278 return HandleDigitDirective(Result);

1279 default:

1281 if (!II) break;

1282

1283

1285 default: break;

1286

1287 case tok::pp_if:

1288 return HandleIfDirective(Result, SavedHash, ReadAnyTokensBeforeDirective);

1289 case tok::pp_ifdef:

1290 return HandleIfdefDirective(Result, SavedHash, false,

1291 true );

1292 case tok::pp_ifndef:

1293 return HandleIfdefDirective(Result, SavedHash, true,

1294 ReadAnyTokensBeforeDirective);

1295 case tok::pp_elif:

1296 case tok::pp_elifdef:

1297 case tok::pp_elifndef:

1299

1300 case tok::pp_else:

1301 return HandleElseDirective(Result, SavedHash);

1302 case tok::pp_endif:

1303 return HandleEndifDirective(Result);

1304

1305

1306 case tok::pp_include:

1307

1309 case tok::pp___include_macros:

1310

1311 return HandleIncludeMacrosDirective(SavedHash.getLocation(), Result);

1312

1313

1314 case tok::pp_define:

1315 return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef);

1316 case tok::pp_undef:

1317 return HandleUndefDirective();

1318

1319

1320 case tok::pp_line:

1321 return HandleLineDirective();

1322

1323

1324 case tok::pp_error:

1325 return HandleUserDiagnosticDirective(Result, false);

1326

1327

1328 case tok::pp_pragma:

1330

1331

1332 case tok::pp_import:

1334 case tok::pp_include_next:

1335 return HandleIncludeNextDirective(SavedHash.getLocation(), Result);

1336

1337 case tok::pp_warning:

1338 if (LangOpts.CPlusPlus)

1340 ? diag::warn_cxx23_compat_warning_directive

1341 : diag::ext_pp_warning_directive)

1342 << 1;

1343 else

1344 Diag(Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive

1345 : diag::ext_pp_warning_directive)

1346 << 0;

1347

1348 return HandleUserDiagnosticDirective(Result, true);

1349 case tok::pp_ident:

1350 return HandleIdentSCCSDirective(Result);

1351 case tok::pp_sccs:

1352 return HandleIdentSCCSDirective(Result);

1353 case tok::pp_embed:

1357 : static_cast<FileEntry *>(nullptr));

1358 case tok::pp_assert:

1359

1360 break;

1361 case tok::pp_unassert:

1362

1363 break;

1364

1365 case tok::pp___public_macro:

1367 return HandleMacroPublicDirective(Result);

1368 break;

1369

1370 case tok::pp___private_macro:

1372 return HandleMacroPrivateDirective();

1373 break;

1374 }

1375 break;

1376 }

1377

1378

1379

1380

1381

1383 auto Toks = std::make_unique<Token[]>(2);

1384

1385 Toks[0] = SavedHash;

1387

1388

1389

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

1391 Toks[1].setKind(tok::unknown);

1392

1393

1394

1395

1396 EnterTokenStream(std::move(Toks), 2, false, false);

1397 return;

1398 }

1399

1400

1401

1402 Diag(Result, diag::err_pp_invalid_directive) << 0;

1403

1404

1406

1407

1408}

1409

1410

1411

1414 bool IsGNULineDirective=false) {

1415 if (DigitTok.isNot(tok::numeric_constant)) {

1416 PP.Diag(DigitTok, DiagID);

1417

1418 if (DigitTok.isNot(tok::eod))

1420 return true;

1421 }

1422

1424 IntegerBuffer.resize(DigitTok.getLength());

1425 const char *DigitTokBegin = &IntegerBuffer[0];

1427 unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin, &Invalid);

1429 return true;

1430

1431

1432

1433

1434 Val = 0;

1435 for (unsigned i = 0; i != ActualLength; ++i) {

1436

1437

1438 if (DigitTokBegin[i] == '\'')

1439 continue;

1440

1441 if (isDigit(DigitTokBegin[i])) {

1443 diag::err_pp_line_digit_sequence) << IsGNULineDirective;

1445 return true;

1446 }

1447

1448 unsigned NextVal = Val*10+(DigitTokBegin[i]-'0');

1449 if (NextVal < Val) {

1450 PP.Diag(DigitTok, DiagID);

1452 return true;

1453 }

1454 Val = NextVal;

1455 }

1456

1457 if (DigitTokBegin[0] == '0' && Val)

1458 PP.Diag(DigitTok.getLocation(), diag::warn_pp_line_decimal)

1459 << IsGNULineDirective;

1460

1461 return false;

1462}

1463

1464

1465

1466

1467

1468

1469

1470

1471void Preprocessor::HandleLineDirective() {

1472

1473

1475 Lex(DigitTok);

1476

1477

1478 unsigned LineNo;

1479 if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this))

1480 return;

1481

1482 if (LineNo == 0)

1483 Diag(DigitTok, diag::ext_pp_line_zero);

1484

1485

1486

1487 unsigned LineLimit = 32768U;

1488 if (LangOpts.C99 || LangOpts.CPlusPlus11)

1489 LineLimit = 2147483648U;

1490 if (LineNo >= LineLimit)

1491 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;

1492 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)

1493 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);

1494

1495 int FilenameID = -1;

1497 Lex(StrTok);

1498

1499

1500

1501 if (StrTok.is(tok::eod))

1502 ;

1503 else if (StrTok.isNot(tok::string_literal)) {

1504 Diag(StrTok, diag::err_pp_line_invalid_filename);

1506 return;

1508 Diag(StrTok, diag::err_invalid_string_udl);

1510 return;

1511 } else {

1512

1514 assert(Literal.isOrdinary() && "Didn't allow wide strings in");

1517 return;

1518 }

1520 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

1522 return;

1523 }

1525

1526

1527

1529 }

1530

1531

1532

1533

1534

1535

1538

1540 false, FileKind);

1541

1542 if (Callbacks)

1545}

1546

1547

1548

1552 unsigned FlagVal;

1554 PP.Lex(FlagTok);

1555 if (FlagTok.is(tok::eod)) return false;

1556 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))

1557 return true;

1558

1559 if (FlagVal == 1) {

1560 IsFileEntry = true;

1561

1562 PP.Lex(FlagTok);

1563 if (FlagTok.is(tok::eod)) return false;

1564 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))

1565 return true;

1566 } else if (FlagVal == 2) {

1567 IsFileExit = true;

1568

1570

1571

1573 SM.getDecomposedExpansionLoc(FlagTok.getLocation()).first;

1576 return true;

1577

1578

1579

1582 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {

1583 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);

1585 return true;

1586 }

1587

1588 PP.Lex(FlagTok);

1589 if (FlagTok.is(tok::eod)) return false;

1590 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))

1591 return true;

1592 }

1593

1594

1595 if (FlagVal != 3) {

1596 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);

1598 return true;

1599 }

1600

1602

1603 PP.Lex(FlagTok);

1604 if (FlagTok.is(tok::eod)) return false;

1605 if (GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))

1606 return true;

1607

1608

1609 if (FlagVal != 4) {

1610 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);

1612 return true;

1613 }

1614

1616

1617 PP.Lex(FlagTok);

1618 if (FlagTok.is(tok::eod)) return false;

1619

1620

1621 PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);

1623 return true;

1624}

1625

1626

1627

1628

1629

1630

1631

1632

1633void Preprocessor::HandleDigitDirective(Token &DigitTok) {

1634

1635

1636 unsigned LineNo;

1637 if (GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,

1638 *this, true))

1639 return;

1640

1642 Lex(StrTok);

1643

1644 bool IsFileEntry = false, IsFileExit = false;

1645 int FilenameID = -1;

1647

1648

1649

1650 if (StrTok.is(tok::eod)) {

1651 Diag(StrTok, diag::ext_pp_gnu_line_directive);

1652

1654 } else if (StrTok.isNot(tok::string_literal)) {

1655 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

1657 return;

1659 Diag(StrTok, diag::err_invalid_string_udl);

1661 return;

1662 } else {

1663

1665 assert(Literal.isOrdinary() && "Didn't allow wide strings in");

1668 return;

1669 }

1671 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);

1673 return;

1674 }

1675

1676

1678 return;

1681 Diag(StrTok, diag::ext_pp_gnu_line_directive);

1682

1683

1684

1685 if (!(IsFileExit && Literal.GetString().empty()))

1687 }

1688

1689

1691 IsFileExit, FileKind);

1692

1693

1694

1695

1696 if (Callbacks) {

1698 if (IsFileEntry)

1700 else if (IsFileExit)

1702

1703 Callbacks->FileChanged(CurPPLexer->getSourceLocation(), Reason, FileKind);

1704 }

1705}

1706

1707

1708

1709void Preprocessor::HandleUserDiagnosticDirective(Token &Tok,

1710 bool isWarning) {

1711

1712

1713

1714

1715

1717 CurLexer->ReadToEndOfLine(&Message);

1718

1719

1720

1721 StringRef Msg = Message.str().ltrim(' ');

1722

1723 if (isWarning)

1724 Diag(Tok, diag::pp_hash_warning) << Msg;

1725 else

1726 Diag(Tok, diag::err_pp_hash_error) << Msg;

1727}

1728

1729

1730

1731void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {

1732

1733 Diag(Tok, diag::ext_pp_ident_directive);

1734

1735

1737 Lex(StrTok);

1738

1739

1740 if (StrTok.isNot(tok::string_literal) &&

1741 StrTok.isNot(tok::wide_string_literal)) {

1742 Diag(StrTok, diag::err_pp_malformed_ident);

1743 if (StrTok.isNot(tok::eod))

1745 return;

1746 }

1747

1749 Diag(StrTok, diag::err_invalid_string_udl);

1751 return;

1752 }

1753

1754

1756

1757 if (Callbacks) {

1761 Callbacks->Ident(Tok.getLocation(), Str);

1762 }

1763}

1764

1765

1766void Preprocessor::HandleMacroPublicDirective(Token &Tok) {

1767 Token MacroNameTok;

1768 ReadMacroName(MacroNameTok, MU_Undef);

1769

1770

1771 if (MacroNameTok.is(tok::eod))

1772 return;

1773

1774

1776

1778

1780

1781

1782 if (!MD) {

1783 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;

1784 return;

1785 }

1786

1787

1789 MacroNameTok.getLocation(), true));

1790}

1791

1792

1793void Preprocessor::HandleMacroPrivateDirective() {

1794 Token MacroNameTok;

1795 ReadMacroName(MacroNameTok, MU_Undef);

1796

1797

1798 if (MacroNameTok.is(tok::eod))

1799 return;

1800

1801

1803

1805

1807

1808

1809 if (!MD) {

1810 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;

1811 return;

1812 }

1813

1814

1816 MacroNameTok.getLocation(), false));

1817}

1818

1819

1820

1821

1822

1823

1824

1825

1826

1827

1828

1830 StringRef &Buffer) {

1831

1832 assert(!Buffer.empty() && "Can't have tokens with empty spellings!");

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843 bool isAngled;

1844 if (Buffer[0] == '<') {

1845 if (Buffer.back() != '>') {

1846 Diag(Loc, diag::err_pp_expects_filename);

1847 Buffer = StringRef();

1848 return true;

1849 }

1850 isAngled = true;

1851 } else if (Buffer[0] == '"') {

1852 if (Buffer.back() != '"') {

1853 Diag(Loc, diag::err_pp_expects_filename);

1854 Buffer = StringRef();

1855 return true;

1856 }

1857 isAngled = false;

1858 } else {

1859 Diag(Loc, diag::err_pp_expects_filename);

1860 Buffer = StringRef();

1861 return true;

1862 }

1863

1864

1865 if (Buffer.size() <= 2) {

1866 Diag(Loc, diag::err_pp_empty_filename);

1867 Buffer = StringRef();

1868 return true;

1869 }

1870

1871

1872 Buffer = Buffer.substr(1, Buffer.size()-2);

1873 return isAngled;

1874}

1875

1876

1879 void *AnnotationVal) {

1880

1881

1882 auto Tok = std::make_unique<Token[]>(1);

1888 EnterTokenStream(std::move(Tok), 1, true, false);

1889}

1890

1891

1892

1895 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,

1898 for (size_t I = 0, N = Path.size(); I != N; ++I) {

1899 if (I)

1900 PathString += '.';

1901 PathString += Path[I].first->getName();

1902 }

1903

1904 int IncludeKind = 0;

1906 case tok::pp_include:

1907 IncludeKind = 0;

1908 break;

1909

1910 case tok::pp_import:

1911 IncludeKind = 1;

1912 break;

1913

1914 case tok::pp_include_next:

1915 IncludeKind = 2;

1916 break;

1917

1918 case tok::pp___include_macros:

1919 IncludeKind = 3;

1920 break;

1921

1922 default:

1923 llvm_unreachable("unknown include directive kind");

1924 }

1925

1926 PP.Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)

1927 << IncludeKind << PathString;

1928}

1929

1930

1931

1932

1934 StringRef RealPathName,

1935 llvm::sys::path::Style Separator) {

1936 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);

1937 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);

1938 int Cnt = 0;

1939 bool SuggestReplacement = false;

1940

1941 auto IsSep = [Separator](StringRef Component) {

1942 return Component.size() == 1 &&

1943 llvm::sys::path::is_separator(Component[0], Separator);

1944 };

1945

1946

1947

1948 for (auto &Component : llvm::reverse(Components)) {

1949 if ("." == Component) {

1950 } else if (".." == Component) {

1951 ++Cnt;

1952 } else if (Cnt) {

1953 --Cnt;

1954 } else if (RealPathComponentIter != RealPathComponentEnd) {

1955 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&

1956 Component != *RealPathComponentIter) {

1957

1958

1959

1960 SuggestReplacement =

1961 RealPathComponentIter->equals_insensitive(Component);

1962 if (!SuggestReplacement)

1963 break;

1964 Component = *RealPathComponentIter;

1965 }

1966 ++RealPathComponentIter;

1967 }

1968 }

1969 return SuggestReplacement;

1970}

1971

1978 Module *ShadowingModule = nullptr;

1980 ShadowingModule))

1981 return false;

1982

1984 Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)

1986 } else if (ShadowingModule) {

1989 diag::note_previous_definition);

1990 } else {

1991

1992

1996 }

1997 return true;

1998}

1999

2000std::pair<ConstSearchDirIterator, const FileEntry *>

2001Preprocessor::getIncludeNextStart(const Token &IncludeNextTok) const {

2002

2003

2004

2006 const FileEntry *LookupFromFile = nullptr;

2007

2009

2010

2011

2013 Lookup = nullptr;

2014 Diag(IncludeNextTok, diag::pp_include_next_in_primary);

2015 } else if (CurLexerSubmodule) {

2016

2017

2018 assert(CurPPLexer && "#include_next directive in macro?");

2020 LookupFromFile = *FE;

2021 Lookup = nullptr;

2022 } else if (!Lookup) {

2023

2024

2025

2026

2027 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);

2028 } else {

2029

2030 ++Lookup;

2031 }

2032

2033 return {Lookup, LookupFromFile};

2034}

2035

2036

2037

2038

2039

2040

2041void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,

2042 Token &IncludeTok,

2044 const FileEntry *LookupFromFile) {

2045 Token FilenameTok;

2047 return;

2048

2049 if (FilenameTok.isNot(tok::header_name)) {

2050 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);

2051 if (FilenameTok.isNot(tok::eod))

2053 return;

2054 }

2055

2056

2057

2058

2059

2062

2063 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,

2064 EndLoc, LookupFrom, LookupFromFile);

2065 switch (Action.Kind) {

2066 case ImportAction::None:

2067 case ImportAction::SkippedModuleImport:

2068 break;

2069 case ImportAction::ModuleBegin:

2071 tok::annot_module_begin, Action.ModuleForHeader);

2072 break;

2073 case ImportAction::HeaderUnitImport:

2075 Action.ModuleForHeader);

2076 break;

2077 case ImportAction::ModuleImport:

2079 tok::annot_module_include, Action.ModuleForHeader);

2080 break;

2081 case ImportAction::Failure:

2083 "This should be an early exit only to a fatal error");

2085 IncludeTok.setKind(tok::eof);

2086 CurLexer->cutOffLexing();

2087 return;

2088 }

2089}

2090

2094 const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,

2096 const FileEntry *LookupFromFile, StringRef &LookupFilename,

2099 auto DiagnoseHeaderInclusion = [&](FileEntryRef FE) {

2100 if (LangOpts.AsmPreprocessor)

2101 return;

2102

2104 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);

2105 bool RequestingModuleIsModuleInterface =

2107

2109 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,

2111 };

2112

2114 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,

2115 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,

2116 &SuggestedModule, &IsMapped, &IsFrameworkFound);

2118 DiagnoseHeaderInclusion(*File);

2119 return File;

2120 }

2121

2122

2123 if (Callbacks && Callbacks->FileNotFound(Filename))

2124 return std::nullopt;

2125

2126 if (SuppressIncludeNotFoundError)

2127 return std::nullopt;

2128

2129

2130

2131

2132 if (isAngled) {

2134 FilenameLoc, LookupFilename, false, LookupFrom, LookupFromFile, CurDir,

2135 Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,

2136 &SuggestedModule, &IsMapped,

2137 nullptr);

2139 DiagnoseHeaderInclusion(*File);

2140 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)

2143 "\"" + Filename.str() + "\"");

2144 return File;

2145 }

2146 }

2147

2148

2149

2150 StringRef OriginalFilename = Filename;

2151 if (LangOpts.SpellChecking) {

2152

2153

2154 auto CorrectTypoFilename = [](llvm::StringRef Filename) {

2158 }

2160 };

2161 StringRef TypoCorrectionName = CorrectTypoFilename(Filename);

2162 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);

2163

2165 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,

2166 LookupFromFile, CurDir, Callbacks ? &SearchPath : nullptr,

2167 Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,

2168 nullptr);

2170 DiagnoseHeaderInclusion(*File);

2171 auto Hint =

2173 FilenameRange, "<" + TypoCorrectionName.str() + ">")

2175 FilenameRange, "\"" + TypoCorrectionName.str() + "\"");

2176 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)

2177 << OriginalFilename << TypoCorrectionName << Hint;

2178

2179

2180 Filename = TypoCorrectionName;

2181 LookupFilename = TypoCorrectionLookupName;

2182 return File;

2183 }

2184 }

2185

2186

2187 assert(File && "expected missing file");

2188 Diag(FilenameTok, diag::err_pp_file_not_found)

2189 << OriginalFilename << FilenameRange;

2190 if (IsFrameworkFound) {

2191 size_t SlashPos = OriginalFilename.find('/');

2192 assert(SlashPos != StringRef::npos &&

2193 "Include with framework name should have '/' in the filename");

2194 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);

2197 assert(CacheEntry.Directory && "Found framework should be in cache");

2198 Diag(FilenameTok, diag::note_pp_framework_without_header)

2199 << OriginalFilename.substr(SlashPos + 1) << FrameworkName

2201 }

2202

2203 return std::nullopt;

2204}

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2215

2216

2217

2218Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(

2221 const FileEntry *LookupFromFile) {

2225

2228 StringRef OriginalFilename = Filename;

2229 bool isAngled =

2231

2232

2233

2235 return {ImportAction::None};

2236

2237 bool IsImportDecl = HashLoc.isInvalid();

2239

2240

2241 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {

2242 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;

2243 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);

2244

2245

2246 PragmaARCCFCodeAuditedInfo = {nullptr, SourceLocation()};

2247 }

2248

2249

2250 if (PragmaAssumeNonNullLoc.isValid()) {

2251 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;

2252 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);

2253

2254

2256 }

2257

2259

2260

2261

2263 if (!NewName.empty())

2265 }

2266

2267

2268 bool IsMapped = false;

2269 bool IsFrameworkFound = false;

2273

2274

2277 StringRef LookupFilename = Filename;

2278

2279

2280

2282 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;

2283 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {

2284 NormalizedPath = Filename.str();

2285 llvm::sys::path::native(NormalizedPath);

2286 LookupFilename = NormalizedPath;

2287 BackslashStyle = llvm::sys::path::Style::windows;

2288 }

2289

2291 &CurDir, Filename, FilenameLoc, FilenameRange, FilenameTok,

2292 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,

2293 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);

2294

2297 SkippingUntilPCHThroughHeader = false;

2298 return {ImportAction::None};

2299 }

2300

2301

2302

2303

2304

2305

2306

2307

2308

2309

2310

2311

2312

2313

2314

2315

2316 enum { Enter, Import, Skip, IncludeLimitReached } Action = Enter;

2317

2318 if (PPOpts->SingleFileParseMode)

2319 Action = IncludeLimitReached;

2320

2321

2322

2323

2324 if (Action == Enter && HasReachedMaxIncludeDepth && File &&

2326 Action = IncludeLimitReached;

2327

2328

2329

2330

2332

2333 bool MaybeTranslateInclude = Action == Enter && File && ModuleToImport &&

2335

2336

2337 bool UsableHeaderUnit = false;

2338 if (getLangOpts().CPlusPlusModules && ModuleToImport &&

2340 if (TrackGMFState.inGMF() || IsImportDecl)

2341 UsableHeaderUnit = true;

2342 else if (!IsImportDecl) {

2343

2344 ModuleToImport = nullptr;

2345 }

2346 }

2347

2348 bool UsableClangHeaderModule =

2350 ModuleToImport && !ModuleToImport->isHeaderUnit();

2351

2352

2353

2354

2355 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {

2356

2357

2358

2359

2363 diag::note_implicit_top_level_module_import_here)

2365 return {ImportAction::None};

2366 }

2367

2368

2369

2370

2372 for (Module *Mod = ModuleToImport; Mod; Mod = Mod->Parent)

2375 std::reverse(Path.begin(), Path.end());

2376

2377

2378 if (!IsImportDecl)

2380

2381

2382

2383

2384

2387 true);

2388 assert((Imported == nullptr || Imported == ModuleToImport) &&

2389 "the imported module is different than the suggested one");

2390

2391 if (Imported) {

2395 static_cast<Module *>(Imported)->getTopLevelModule());

2396

2397

2398

2399

2400 ModuleToImport = nullptr;

2402

2403

2404 } else {

2405

2407

2409 assert(CurLexer && "#include but no current lexer set!");

2410 Result.startToken();

2411 CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);

2412 CurLexer->cutOffLexing();

2413 }

2414 return {ImportAction::None};

2415 }

2416 }

2417

2418

2419

2420

2424 FileCharacter = std::max(HeaderInfo.getFileDirFlavor(*File), FileCharacter);

2425

2426

2427

2428

2429

2430

2431 bool EnterOnce =

2432 IsImportDecl ||

2434

2435 bool IsFirstIncludeOfFile = false;

2436

2437

2438

2439 if (Action == Enter && File &&

2442 IsFirstIncludeOfFile)) {

2443

2444

2445

2446

2447

2448

2449

2450

2451

2452

2453 if (UsableHeaderUnit && getLangOpts().CompilingPCH)

2454 Action = TrackGMFState.inGMF() ? Import : Skip;

2455 else

2456 Action = (ModuleToImport && getLangOpts().CompilingPCH) ? Import : Skip;

2457 }

2458

2459

2460

2461

2462

2463

2464 if (Action == Enter && File && PreambleConditionalStack.isRecording() &&

2467 diag::err_pp_including_mainfile_in_preamble);

2468 return {ImportAction::None};

2469 }

2470

2471 if (Callbacks && !IsImportDecl) {

2472

2473

2474 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,

2475 FilenameRange, File, SearchPath, RelativePath,

2476 SuggestedModule.getModule(), Action == Import,

2477 FileCharacter);

2479 Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);

2480 }

2481

2483 return {ImportAction::None};

2484

2485

2486

2487 if (IsImportDecl && !ModuleToImport) {

2488 Diag(FilenameTok, diag::err_header_import_not_header_unit)

2489 << OriginalFilename << File->getName();

2490 return {ImportAction::None};

2491 }

2492

2493

2494

2495 const bool CheckIncludePathPortability =

2496 !IsMapped && File->getFileEntry().tryGetRealPathName().empty();

2497

2498 if (CheckIncludePathPortability) {

2499 StringRef Name = LookupFilename;

2500 StringRef NameWithoriginalSlashes = Filename;

2501#if defined(_WIN32)

2502

2503

2504 bool NameWasUNC = Name.consume_front("\\\\?\\");

2505 NameWithoriginalSlashes.consume_front("\\\\?\\");

2506#endif

2507 StringRef RealPathName = File->getFileEntry().tryGetRealPathName();

2509 llvm::sys::path::end(Name));

2510#if defined(_WIN32)

2511

2512

2513

2514

2515

2516

2517

2518

2519

2520

2522 if (llvm::sys::path::is_absolute(Name) &&

2523 llvm::sys::path::is_absolute(RealPathName) &&

2526 assert(Components.size() >= 3 && "should have drive, backslash, name");

2527 assert(Components[0].size() == 2 && "should start with drive");

2528 assert(Components[0][1] == ':' && "should have colon");

2529 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();

2530 RealPathName = FixedDriveRealPath;

2531 }

2532#endif

2533

2534 if (trySimplifyPath(Components, RealPathName, BackslashStyle)) {

2536 Path.reserve(Name.size()+2);

2537 Path.push_back(isAngled ? '<' : '"');

2538

2539 const auto IsSep = [BackslashStyle](char c) {

2540 return llvm::sys::path::is_separator(c, BackslashStyle);

2541 };

2542

2543 for (auto Component : Components) {

2544

2545

2546

2547

2548

2549

2550

2551

2552

2553

2554

2555 if (!(Component.size() == 1 && IsSep(Component[0])))

2556 Path.append(Component);

2557 else if (Path.size() != 1)

2558 continue;

2559

2560

2561 if (Path.size() > NameWithoriginalSlashes.size()) {

2562 Path.push_back(isAngled ? '>' : '"');

2563 continue;

2564 }

2565 assert(IsSep(NameWithoriginalSlashes[Path.size()-1]));

2566 do

2567 Path.push_back(NameWithoriginalSlashes[Path.size()-1]);

2568 while (Path.size() <= NameWithoriginalSlashes.size() &&

2569 IsSep(NameWithoriginalSlashes[Path.size()-1]));

2570 }

2571

2572#if defined(_WIN32)

2573

2574 if (NameWasUNC)

2575 Path = (Path.substr(0, 1) + "\\\\?\\" + Path.substr(1)).str();

2576#endif

2577

2578

2579

2580 auto DiagId =

2582 ? diag::pp_nonportable_path

2583 : diag::pp_nonportable_system_path;

2584 Diag(FilenameTok, DiagId) << Path <<

2586 }

2587 }

2588

2589 switch (Action) {

2591

2592 if (ModuleToImport)

2593 return {ImportAction::SkippedModuleImport, ModuleToImport};

2594 return {ImportAction::None};

2595

2596 case IncludeLimitReached:

2597

2598

2599 return {ImportAction::None};

2600

2602

2603 assert(ModuleToImport && "no module to import");

2604

2606

2608 tok::pp___include_macros)

2609 return {ImportAction::None};

2610

2611 return {ImportAction::ModuleImport, ModuleToImport};

2612 }

2613

2614 case Enter:

2615 break;

2616 }

2617

2618

2619 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {

2620 Diag(FilenameTok, diag::err_pp_include_too_deep);

2621 HasReachedMaxIncludeDepth = true;

2622 return {ImportAction::None};

2623 }

2624

2626 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)

2628

2629

2631

2632

2638 return ImportAction::Failure;

2639 }

2640

2641

2643 IsFirstIncludeOfFile))

2644 return {ImportAction::None};

2645

2646

2647

2648 if (ModuleToImport && !ModuleToImport->isHeaderUnit()) {

2650

2651

2653 diag::err_module_build_shadowed_submodule)

2656 diag::note_previous_definition);

2657 return {ImportAction::None};

2658 }

2659

2660

2661

2662

2663

2664

2665

2666

2669 return {ImportAction::None};

2670

2671 assert(!CurLexerSubmodule && "should not have marked this as a module yet");

2672 CurLexerSubmodule = ModuleToImport;

2673

2674

2675

2676 EnterSubmodule(ModuleToImport, EndLoc, false);

2677

2678

2679

2680

2681

2682 return {ImportAction::ModuleBegin, ModuleToImport};

2683 }

2684

2685 assert(!IsImportDecl && "failed to diagnose missing module for import decl");

2686 return {ImportAction::None};

2687}

2688

2689

2690

2691void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,

2692 Token &IncludeNextTok) {

2693 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);

2694

2696 const FileEntry *LookupFromFile;

2697 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);

2698

2699 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,

2700 LookupFromFile);

2701}

2702

2703

2704void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {

2705

2706

2707

2708

2709

2710 Diag(Tok, diag::err_pp_import_directive_ms );

2711

2712

2713

2715}

2716

2717

2718

2719void Preprocessor::HandleImportDirective(SourceLocation HashLoc,

2720 Token &ImportTok) {

2721 if (!LangOpts.ObjC) {

2722 if (LangOpts.MSVCCompat)

2723 return HandleMicrosoftImportDirective(ImportTok);

2724 Diag(ImportTok, diag::ext_pp_import_directive);

2725 }

2726 return HandleIncludeDirective(HashLoc, ImportTok);

2727}

2728

2729

2730

2731

2732

2733void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,

2734 Token &IncludeMacrosTok) {

2735

2736

2740 diag::pp_include_macros_out_of_predefines);

2742 return;

2743 }

2744

2745

2746

2747 HandleIncludeDirective(HashLoc, IncludeMacrosTok);

2748

2750 do {

2751 Lex(TmpTok);

2752 assert(TmpTok.isNot(tok::eof) && "Didn't find end of -imacros!");

2753 } while (TmpTok.isNot(tok::hashhash));

2754}

2755

2756

2757

2758

2759

2760

2761

2762

2763

2764bool Preprocessor::ReadMacroParameterList(MacroInfo *MI, Token &Tok) {

2766

2767 while (true) {

2769 switch (Tok.getKind()) {

2770 case tok::r_paren:

2771

2772 if (Parameters.empty())

2773 return false;

2774

2775 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);

2776 return true;

2777 case tok::ellipsis:

2778 if (!LangOpts.C99)

2779 Diag(Tok, LangOpts.CPlusPlus11 ?

2780 diag::warn_cxx98_compat_variadic_macro :

2781 diag::ext_variadic_macro);

2782

2783

2784 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {

2785 Diag(Tok, diag::ext_pp_opencl_variadic_macros);

2786 }

2787

2788

2790 if (Tok.isNot(tok::r_paren)) {

2791 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);

2792 return true;

2793 }

2794

2795 Parameters.push_back(Ident__VA_ARGS__);

2798 return false;

2799 case tok::eod:

2800 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);

2801 return true;

2802 default:

2803

2804

2806 if (!II) {

2807

2808 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);

2809 return true;

2810 }

2811

2812

2813

2814 if (llvm::is_contained(Parameters, II)) {

2815 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;

2816 return true;

2817 }

2818

2819

2821

2822

2824

2825 switch (Tok.getKind()) {

2826 default:

2827 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);

2828 return true;

2829 case tok::r_paren:

2831 return false;

2832 case tok::comma:

2833 break;

2834 case tok::ellipsis:

2835

2836 Diag(Tok, diag::ext_named_variadic_macro);

2837

2838

2840 if (Tok.isNot(tok::r_paren)) {

2841 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);

2842 return true;

2843 }

2844

2847 return false;

2848 }

2849 }

2850 }

2851}

2852

2857

2858

2860 return true;

2861

2862

2863

2864

2865

2866

2870 return false;

2871 StringRef ValueText = II->getName();

2872 StringRef TrimmedValue = ValueText;

2873 if (!ValueText.starts_with("__")) {

2874 if (ValueText.starts_with("_"))

2875 TrimmedValue = TrimmedValue.drop_front(1);

2876 else

2877 return false;

2878 } else {

2879 TrimmedValue = TrimmedValue.drop_front(2);

2880 if (TrimmedValue.ends_with("__"))

2881 TrimmedValue = TrimmedValue.drop_back(2);

2882 }

2883 return TrimmedValue == MacroText;

2884 } else {

2885 return false;

2886 }

2887 }

2888

2889

2890 return MacroName.isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,

2891 tok::kw_const) &&

2893}

2894

2895

2896

2897

2898

2899

2900

2901

2902

2903MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(

2904 const Token &MacroNameTok, const bool ImmediatelyAfterHeaderGuard) {

2905

2906 Token LastTok = MacroNameTok;

2907

2909

2912

2913

2914 auto _ = llvm::make_scope_exit([&]() {

2915

2916 if (CurLexer->ParsingPreprocessorDirective)

2918 });

2919

2920

2921

2923

2924

2925

2926

2927 if (Tok.is(tok::eod)) {

2928 if (ImmediatelyAfterHeaderGuard) {

2929

2932 }

2933

2935

2936

2938 } else if (Tok.is(tok::l_paren)) {

2939

2941 if (ReadMacroParameterList(MI, LastTok))

2942 return nullptr;

2943

2944

2945

2946

2947

2948

2951 }

2952

2953

2955 } else if (LangOpts.C99 || LangOpts.CPlusPlus11) {

2956

2957

2958 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);

2959 } else {

2960

2961

2962

2963

2964

2965

2967 if (Tok.is(tok::at))

2969 else if (Tok.is(tok::unknown)) {

2970

2971

2972

2974 }

2976 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);

2977 else

2978 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);

2979 }

2980

2981 if (!Tok.is(tok::eod))

2982 LastTok = Tok;

2983

2985

2986

2988

2989 while (Tok.isNot(tok::eod)) {

2990 LastTok = Tok;

2991 Tokens.push_back(Tok);

2992

2994 }

2995 } else {

2996

2997

2998

2999

3001

3002 while (Tok.isNot(tok::eod)) {

3003 LastTok = Tok;

3004

3005 if (!Tok.isOneOf(tok::hash, tok::hashat, tok::hashhash)) {

3006 Tokens.push_back(Tok);

3007

3008 if (VAOCtx.isVAOptToken(Tok)) {

3009

3010 if (VAOCtx.isInVAOpt()) {

3011 Diag(Tok, diag::err_pp_vaopt_nested_use);

3012 return nullptr;

3013 }

3014

3016 if (Tok.isNot(tok::l_paren)) {

3017 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);

3018 return nullptr;

3019 }

3020 Tokens.push_back(Tok);

3021 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.getLocation());

3023 if (Tok.is(tok::hashhash)) {

3024 Diag(Tok, diag::err_vaopt_paste_at_start);

3025 return nullptr;

3026 }

3027 continue;

3028 } else if (VAOCtx.isInVAOpt()) {

3029 if (Tok.is(tok::r_paren)) {

3030 if (VAOCtx.sawClosingParen()) {

3031 assert(Tokens.size() >= 3 &&

3032 "Must have seen at least __VA_OPT__( "

3033 "and a subsequent tok::r_paren");

3034 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {

3035 Diag(Tok, diag::err_vaopt_paste_at_end);

3036 return nullptr;

3037 }

3038 }

3039 } else if (Tok.is(tok::l_paren)) {

3040 VAOCtx.sawOpeningParen(Tok.getLocation());

3041 }

3042 }

3043

3045 continue;

3046 }

3047

3048

3049

3050

3052 Tok.setKind(tok::unknown);

3053 Tokens.push_back(Tok);

3054

3055

3057 continue;

3058 }

3059

3060 if (Tok.is(tok::hashhash)) {

3061

3062

3063

3064

3065

3067

3068 if (Tok.is(tok::eod)) {

3069 Tokens.push_back(LastTok);

3070 break;

3071 }

3072

3073 if (!Tokens.empty() && Tok.getIdentifierInfo() == Ident__VA_ARGS__ &&

3074 Tokens[Tokens.size() - 1].is(tok::comma))

3076

3077

3078 Tokens.push_back(LastTok);

3079 continue;

3080 }

3081

3082

3083

3085

3086

3087 if (!VAOCtx.isVAOptToken(Tok) &&

3090

3091

3092

3093

3094

3096 LastTok.setKind(tok::unknown);

3097 Tokens.push_back(LastTok);

3098 continue;

3099 } else {

3100 Diag(Tok, diag::err_pp_stringize_not_parameter)

3101 << LastTok.is(tok::hashat);

3102 return nullptr;

3103 }

3104 }

3105

3106

3107 Tokens.push_back(LastTok);

3108

3109

3110

3111

3112 if (!VAOCtx.isVAOptToken(Tok)) {

3113 Tokens.push_back(Tok);

3114 LastTok = Tok;

3115

3116

3118 }

3119 }

3120 if (VAOCtx.isInVAOpt()) {

3121 assert(Tok.is(tok::eod) && "Must be at End Of preprocessing Directive");

3122 Diag(Tok, diag::err_pp_expected_after)

3123 << LastTok.getKind() << tok::r_paren;

3124 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;

3125 return nullptr;

3126 }

3127 }

3129

3131 return MI;

3132}

3133

3135 return II->isStr("__strong") || II->isStr("__weak") ||

3136 II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing");

3137}

3138

3139

3140

3141void Preprocessor::HandleDefineDirective(

3142 Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) {

3143 ++NumDefined;

3144

3145 Token MacroNameTok;

3146 bool MacroShadowsKeyword;

3147 ReadMacroName(MacroNameTok, MU_Define, &MacroShadowsKeyword);

3148

3149

3150 if (MacroNameTok.is(tok::eod))

3151 return;

3152

3154

3155

3157 emitFinalMacroWarning(MacroNameTok, false);

3158

3159

3160

3161 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);

3162

3163 MacroInfo *const MI = ReadOptionalMacroParameterListAndBody(

3164 MacroNameTok, ImmediatelyAfterHeaderGuard);

3165

3166 if (!MI) return;

3167

3168 if (MacroShadowsKeyword &&

3170 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);

3171 }

3172

3173

3175 if (NumTokens != 0) {

3178 return;

3179 }

3182 return;

3183 }

3184 }

3185

3186

3187 if (SkippingUntilPCHThroughHeader) {

3189 if (!OtherMI || !MI->isIdenticalTo(*OtherMI, *this,

3190 LangOpts.MicrosoftExt))

3193

3194 if (!LangOpts.MicrosoftExt)

3195 return;

3196 }

3197

3198

3199

3201

3202

3203

3205 emitFinalMacroWarning(MacroNameTok, false);

3206

3207

3208

3209

3214

3215 if ((getDiagnostics().getSuppressSystemWarnings() ||

3218 LangOpts.MicrosoftExt)) {

3220 }

3222 return;

3223 }

3224

3225

3226

3227

3228 if (getDiagnostics().getSuppressSystemWarnings() ||

3230

3233

3234

3235

3237 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);

3238

3239

3241 !MI->isIdenticalTo(*OtherMI, *this, LangOpts.MicrosoftExt)) {

3245 }

3246 }

3249 }

3250

3253

3254 assert(!MI->isUsed());

3255

3256

3259 !MacroExpansionInDirectivesOverride &&

3264 }

3265

3266

3267 if (Callbacks)

3268 Callbacks->MacroDefined(MacroNameTok, MD);

3269

3270

3271

3272

3273

3278

3281 Tok.setKind(tok::kw__Static_assert);

3285 }

3286}

3287

3288

3289

3290void Preprocessor::HandleUndefDirective() {

3291 ++NumUndefined;

3292

3293 Token MacroNameTok;

3294 ReadMacroName(MacroNameTok, MU_Undef);

3295

3296

3297 if (MacroNameTok.is(tok::eod))

3298 return;

3299

3300

3302

3303

3307

3309 emitFinalMacroWarning(MacroNameTok, true);

3310

3311

3315

3316

3317

3319 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);

3320

3323

3324 Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation());

3325 }

3326

3327

3328

3329 if (Callbacks)

3330 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);

3331

3332 if (Undef)

3334}

3335

3336

3337

3338

3339

3340

3341

3342

3343

3344

3345void Preprocessor::HandleIfdefDirective(Token &Result,

3346 const Token &HashToken,

3347 bool isIfndef,

3348 bool ReadAnyTokensBeforeDirective) {

3349 ++NumIf;

3351

3352 Token MacroNameTok;

3353 ReadMacroName(MacroNameTok);

3354

3355

3356 if (MacroNameTok.is(tok::eod)) {

3357

3358

3359 SkipExcludedConditionalBlock(HashToken.getLocation(),

3361 false, false);

3362 return;

3363 }

3364

3366

3367

3369

3373

3375

3376

3377

3378

3379 if (!ReadAnyTokensBeforeDirective && !MI) {

3380 assert(isIfndef && "#ifdef shouldn't reach here");

3382 } else

3384 }

3385

3386

3387 if (MI)

3389

3390 if (Callbacks) {

3391 if (isIfndef)

3392 Callbacks->Ifndef(DirectiveTok.getLocation(), MacroNameTok, MD);

3393 else

3394 Callbacks->Ifdef(DirectiveTok.getLocation(), MacroNameTok, MD);

3395 }

3396

3397 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&

3399

3400

3401 if (PPOpts->SingleFileParseMode && !MI) {

3402

3403

3405 false, false,

3406 false);

3407 } else if (!MI == isIfndef || RetainExcludedCB) {

3408

3410 false, true,

3411 false);

3412 } else {

3413

3414 SkipExcludedConditionalBlock(HashToken.getLocation(),

3416 false,

3417 false);

3418 }

3419}

3420

3421

3422

3423void Preprocessor::HandleIfDirective(Token &IfToken,

3424 const Token &HashToken,

3425 bool ReadAnyTokensBeforeDirective) {

3426 ++NumIf;

3427

3428

3430 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);

3431 const bool ConditionalTrue = DER.Conditional;

3432

3433

3434 if (!CurPPLexer)

3435 return;

3436

3437

3438

3440 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)

3441

3443 else

3445 }

3446

3447 if (Callbacks)

3448 Callbacks->If(

3451

3452 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&

3454

3455

3456 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {

3457

3458

3460 false, false);

3461 } else if (ConditionalTrue || RetainExcludedCB) {

3462

3464 true, false);

3465 } else {

3466

3468 false,

3469 false);

3470 }

3471}

3472

3473

3474

3475void Preprocessor::HandleEndifDirective(Token &EndifToken) {

3476 ++NumEndif;

3477

3478

3480

3483

3484 Diag(EndifToken, diag::err_pp_endif_without_if);

3485 return;

3486 }

3487

3488

3491

3493 "This code should only be reachable in the non-skipping case!");

3494

3495 if (Callbacks)

3497}

3498

3499

3500

3501void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) {

3502 ++NumElse;

3503

3504

3506

3509 Diag(Result, diag::pp_err_else_without_if);

3510 return;

3511 }

3512

3513

3516

3517

3519

3520 if (Callbacks)

3521 Callbacks->Else(Result.getLocation(), CI.IfLoc);

3522

3523 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&

3525

3526 if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {

3527

3528

3530 false, true);

3531 return;

3532 }

3533

3534

3535 SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc,

3536 true,

3537 true, Result.getLocation());

3538}

3539

3540

3541void Preprocessor::HandleElifFamilyDirective(Token &ElifToken,

3542 const Token &HashToken,

3547 ++NumElse;

3548

3549

3550 switch (DirKind) {

3553 unsigned DiagID;

3554 if (LangOpts.CPlusPlus)

3555 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive

3556 : diag::ext_cxx23_pp_directive;

3557 else

3558 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive

3559 : diag::ext_c23_pp_directive;

3560 Diag(ElifToken, DiagID) << DirKind;

3561 break;

3562 default:

3563 break;

3564 }

3565

3566

3567

3568

3570

3573 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;

3574 return;

3575 }

3576

3577

3580

3581

3583 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;

3584

3585 if (Callbacks) {

3586 switch (Kind) {

3587 case tok::pp_elif:

3588 Callbacks->Elif(ElifToken.getLocation(), ConditionRange,

3590 break;

3591 case tok::pp_elifdef:

3592 Callbacks->Elifdef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);

3593 break;

3594 case tok::pp_elifndef:

3595 Callbacks->Elifndef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);

3596 break;

3597 default:

3598 assert(false && "unexpected directive kind");

3599 break;

3600 }

3601 }

3602

3603 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&

3605

3606 if ((PPOpts->SingleFileParseMode && !CI.FoundNonSkip) || RetainExcludedCB) {

3607

3608

3610 false, false);

3611 return;

3612 }

3613

3614

3615 SkipExcludedConditionalBlock(

3618}

3619

3620std::optional

3624 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;

3625

3626 auto DiagMismatchedBracesAndSkipToEOD =

3628 std::pair<tok::TokenKind, SourceLocation> Matches) {

3629 Diag(CurTok, diag::err_expected) << Expected;

3630 Diag(Matches.second, diag::note_matching) << Matches.first;

3631 if (CurTok.isNot(tok::eod))

3633 };

3634

3635 auto ExpectOrDiagAndSkipToEOD = [&](tok::TokenKind Kind) {

3636 if (CurTok.isNot(Kind)) {

3637 Diag(CurTok, diag::err_expected) << Kind;

3638 if (CurTok.isNot(tok::eod))

3640 return false;

3641 }

3642 return true;

3643 };

3644

3645

3646

3647

3648

3649

3650

3651

3652

3653

3654

3655 auto LexPPParameterName = [&]() -> std::optionalstd::string {

3656

3657

3658 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))

3659 return std::nullopt;

3660

3662

3663

3664

3666 if (CurTok.is(tok::coloncolon)) {

3667

3669 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))

3670 return std::nullopt;

3671

3673

3674

3676 return (llvm::Twine(Prefix->getName()) + "::" + Suffix->getName()).str();

3677 }

3678 return Prefix->getName().str();

3679 };

3680

3681

3682

3683

3684

3685 auto NormalizeParameterName = [](StringRef Name) {

3686 if (Name.size() > 4 && Name.starts_with("__") && Name.ends_with("__"))

3687 return Name.substr(2, Name.size() - 4);

3688 return Name;

3689 };

3690

3691 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {

3692

3693

3694 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))

3695 return std::nullopt;

3696

3697

3698

3700 bool EvaluatedDefined;

3701 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(

3702 ParameterIfNDef, CurTok, EvaluatedDefined, false);

3703

3704 if (!LimitEvalResult.Value) {

3705

3706

3707 assert(CurTok.is(tok::eod) && "expect to be at the end of directive");

3708 return std::nullopt;

3709 }

3710

3711 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))

3712 return std::nullopt;

3713

3714

3716

3717

3718

3719 if (EvaluatedDefined) {

3720 Diag(CurTok, diag::err_defined_in_pp_embed);

3721 return std::nullopt;

3722 }

3723

3724 if (LimitEvalResult.Value) {

3725 const llvm::APSInt &Result = *LimitEvalResult.Value;

3726 if (Result.isNegative()) {

3727 Diag(CurTok, diag::err_requires_positive_value)

3729 return std::nullopt;

3730 }

3731 return Result.getLimitedValue();

3732 }

3733 return std::nullopt;

3734 };

3735

3736 auto GetMatchingCloseBracket = [](tok::TokenKind Kind) {

3737 switch (Kind) {

3738 case tok::l_paren:

3739 return tok::r_paren;

3740 case tok::l_brace:

3741 return tok::r_brace;

3742 case tok::l_square:

3743 return tok::r_square;

3744 default:

3745 llvm_unreachable("should not get here");

3746 }

3747 };

3748

3749 auto LexParenthesizedBalancedTokenSoup =

3751 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;

3752

3753

3754 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))

3755 return false;

3757

3758 bool WaitingForInnerCloseParen = false;

3759 while (CurTok.isNot(tok::eod) &&

3760 (WaitingForInnerCloseParen || CurTok.isNot(tok::r_paren))) {

3761 switch (CurTok.getKind()) {

3762 default:

3763 break;

3764 case tok::l_paren:

3765 WaitingForInnerCloseParen = true;

3766 [[fallthrough]];

3767 case tok::l_brace:

3768 case tok::l_square:

3770 break;

3771 case tok::r_paren:

3772 WaitingForInnerCloseParen = false;

3773 [[fallthrough]];

3774 case tok::r_brace:

3775 case tok::r_square: {

3777 GetMatchingCloseBracket(BracketStack.back().first);

3778 if (BracketStack.empty() || CurTok.getKind() != Matching) {

3779 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());

3780 return false;

3781 }

3782 BracketStack.pop_back();

3783 } break;

3784 }

3785 Tokens.push_back(CurTok);

3787 }

3788

3789

3790 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))

3791 return false;

3792

3794 return true;

3795 };

3796

3798 while (!CurTok.isOneOf(EndTokenKind, tok::eod)) {

3800 std::optionalstd::string ParamName = LexPPParameterName();

3801 if (!ParamName)

3802 return std::nullopt;

3803 StringRef Parameter = NormalizeParameterName(*ParamName);

3804

3805

3806

3807

3808

3810 if (Result.MaybeLimitParam)

3811 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;

3812

3813 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();

3814 if (!Limit)

3815 return std::nullopt;

3816 Result.MaybeLimitParam =

3818 } else if (Parameter == "clang::offset") {

3819 if (Result.MaybeOffsetParam)

3820 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;

3821

3822 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();

3823 if (!Offset)

3824 return std::nullopt;

3826 *Offset, {ParamStartLoc, CurTok.getLocation()}};

3827 } else if (Parameter == "prefix") {

3828 if (Result.MaybePrefixParam)

3829 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;

3830

3832 if (!LexParenthesizedBalancedTokenSoup(Soup))

3833 return std::nullopt;

3835 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};

3836 } else if (Parameter == "suffix") {

3837 if (Result.MaybeSuffixParam)

3838 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;

3839

3841 if (!LexParenthesizedBalancedTokenSoup(Soup))

3842 return std::nullopt;

3844 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};

3845 } else if (Parameter == "if_empty") {

3846 if (Result.MaybeIfEmptyParam)

3847 Diag(CurTok, diag::err_pp_embed_dup_params) << Parameter;

3848

3850 if (!LexParenthesizedBalancedTokenSoup(Soup))

3851 return std::nullopt;

3853 std::move(Soup), {ParamStartLoc, CurTok.getLocation()}};

3854 } else {

3855 ++Result.UnrecognizedParams;

3856

3857

3858

3859 if (CurTok.is(tok::l_paren)) {

3861 if (!LexParenthesizedBalancedTokenSoup(Soup))

3862 return std::nullopt;

3863 }

3864 if (!ForHasEmbed) {

3865 Diag(CurTok, diag::err_pp_unknown_parameter) << 1 << Parameter;

3866 return std::nullopt;

3867 }

3868 }

3869 }

3871}

3872

3873void Preprocessor::HandleEmbedDirectiveImpl(

3875 StringRef BinaryContents) {

3876 if (BinaryContents.empty()) {

3877

3878

3879

3880

3881

3884 size_t TokCount = Toks.size();

3885 auto NewToks = std::make_unique<Token[]>(TokCount);

3886 llvm::copy(Toks, NewToks.get());

3887 EnterTokenStream(std::move(NewToks), TokCount, true, true);

3888 }

3889 return;

3890 }

3891

3894 size_t TotalNumToks = 1 + NumPrefixToks + NumSuffixToks;

3895 size_t CurIdx = 0;

3896 auto Toks = std::make_unique<Token[]>(TotalNumToks);

3897

3898

3901 CurIdx += NumPrefixToks;

3902 }

3903

3905 Data->BinaryData = BinaryContents;

3906

3907 Toks[CurIdx].startToken();

3908 Toks[CurIdx].setKind(tok::annot_embed);

3909 Toks[CurIdx].setAnnotationRange(HashLoc);

3910 Toks[CurIdx++].setAnnotationValue(Data);

3911

3912

3915 CurIdx += NumSuffixToks;

3916 }

3917

3918 assert(CurIdx == TotalNumToks && "Calculated the incorrect number of tokens");

3919 EnterTokenStream(std::move(Toks), TotalNumToks, true, true);

3920}

3921

3922void Preprocessor::HandleEmbedDirective(SourceLocation HashLoc, Token &EmbedTok,

3923 const FileEntry *LookupFromFile) {

3924

3925 if (LangOpts.C23)

3926 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);

3927 else

3928 Diag(EmbedTok, diag::ext_pp_embed_directive)

3929 << (LangOpts.CPlusPlus ? 1 : 0);

3930

3931

3932 Token FilenameTok;

3934 return;

3935

3936 if (FilenameTok.isNot(tok::header_name)) {

3937 Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);

3938 if (FilenameTok.isNot(tok::eod))

3940 return;

3941 }

3942

3943

3944

3945

3946

3947

3948

3949

3951 std::optional Params =

3953

3954 assert((Params || CurTok.is(tok::eod)) &&

3955 "expected success or to be at the end of the directive");

3956 if (!Params)

3957 return;

3958

3959

3962 StringRef OriginalFilename = Filename;

3963 bool isAngled =

3965

3966

3969 this->LookupEmbedFile(Filename, isAngled, true, LookupFromFile);

3970 if (!MaybeFileRef) {

3971

3972 if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) {

3973 return;

3974 }

3975 Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;

3976 return;

3977 }

3978 std::optionalllvm::MemoryBufferRef MaybeFile =

3980 if (!MaybeFile) {

3981

3982 Diag(FilenameTok, diag::err_cannot_open_file)

3983 << Filename << "a buffer to the contents could not be created";

3984 return;

3985 }

3986 StringRef BinaryContents = MaybeFile->getBuffer();

3987

3988

3989

3990

3991 if (Params->MaybeOffsetParam) {

3992

3993

3994

3995

3996 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);

3997 }

3998

3999 if (Params->MaybeLimitParam) {

4000

4001

4002

4003 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);

4004 }

4005

4006 if (Callbacks)

4007 Callbacks->EmbedDirective(HashLoc, Filename, isAngled, MaybeFileRef,

4008 *Params);

4009 HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents);

4010}

static bool isInMainFile(const clang::Diagnostic &D)

Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.

Defines the clang::FileManager interface and associated types.

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::Module class, which describes a module in the source code.

Defines the PPCallbacks interface.

static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP)

ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line marker directive.

static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, const LangOptions &LOptions)

static std::optional< StringRef > findSimilarStr(StringRef LHS, const std::vector< StringRef > &Candidates)

Find a similar string in Candidates.

static bool isLanguageDefinedBuiltin(const SourceManager &SourceMgr, const MacroInfo *MI, const StringRef MacroName)

static bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName, llvm::sys::path::Style Separator)

static void diagnoseAutoModuleImport(Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, ArrayRef< std::pair< IdentifierInfo *, SourceLocation > > Path, SourceLocation PathEnd)

Produce a diagnostic informing the user that a #include or similar was implicitly treated as a module...

static bool warnByDefaultOnWrongCase(StringRef Include)

MacroDiag

Enumerates possible cases of #define/#undef a reserved identifier.

static bool isFeatureTestMacro(StringRef MacroName)

static bool GetLineValue(Token &DigitTok, unsigned &Val, unsigned DiagID, Preprocessor &PP, bool IsGNULineDirective=false)

GetLineValue - Convert a numeric token into an unsigned value, emitting Diagnostic DiagID if it is in...

PPElifDiag

Enumerates possible select values for the pp_err_elif_after_else and pp_err_elif_without_if diagnosti...

static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II)

static bool isObjCProtectedMacro(const IdentifierInfo *II)

static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II)

Defines the clang::Preprocessor interface.

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.

static bool isInvalid(LocType Loc, bool *Invalid)

Defines the SourceManager interface.

Defines the clang::TokenKind enum and support functions.

__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)

__device__ __2f16 float c

ResetMacroExpansionHelper(Preprocessor *pp)

~ResetMacroExpansionHelper()

Represents a character-granular source range.

static CharSourceRange getCharRange(SourceRange R)

SourceLocation getEnd() const

virtual void CodeCompleteMacroName(bool IsDefinition)

Callback invoked when performing code completion in a context where the name of a macro is expected.

virtual void CodeCompleteInConditionalExclusion()

Callback invoked when performing code completion within a block of code that was excluded due to prep...

virtual void CodeCompleteDirective(bool InConditional)

Callback invoked when performing code completion for a preprocessor directive.

A directive for a defined macro or a macro imported from a module.

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 isIgnored(unsigned DiagID, SourceLocation Loc) const

Determine whether the diagnostic is known to be ignored.

A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...

StringRef getName() const

A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...

const FileEntry & getFileEntry() const

DirectoryEntryRef getDir() const

Cached information about one file (either on disk or in the virtual file system).

StringRef tryGetRealPathName() const

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

Implements support for file system lookup, file system caching, and directory search management.

llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)

Lookup, cache, and verify the specified directory (real or virtual).

OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)

Get a DirectoryEntryRef if it exists, without doing anything on error.

LLVM_DEPRECATED("Functions returning DirectoryEntry are deprecated.", "getOptionalDirectoryRef()") llvm LLVM_DEPRECATED("Functions returning FileEntry are deprecated.", "getOptionalFileRef()") llvm llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)

Lookup, cache, and verify the specified directory (real or virtual).

Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)

Create a code modification hint that inserts the given code string at a specific location.

One of these records is kept for each identifier that is lexed.

tok::PPKeywordKind getPPKeywordID() const

Return the preprocessor keyword ID for this identifier.

bool isCPlusPlusOperatorKeyword() const

bool hadMacroDefinition() const

Returns true if this identifier was #defined to some value at any moment.

bool hasMacroDefinition() const

Return true if this identifier is #defined to some other value.

const char * getNameStart() const

Return the beginning of the actual null-terminated string for this identifier.

bool isKeyword(const LangOptions &LangOpts) const

Return true if this token is a keyword in the specified language.

ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const

Determine whether this is a name reserved for the implementation (C99 7.1.3, C++ [lib....

bool isStr(const char(&Str)[StrLen]) const

Return true if this is the identifier for the specified string.

StringRef getName() const

Return the actual identifier string.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

bool IsHeaderFile

Indicates whether the front-end is explicitly told that the input is a header file (i....

std::string CurrentModule

The name of the current module, of which the main source file is a part.

Encapsulates changes to the "macros namespace" (the location where the macro name became active,...

const MacroInfo * getMacroInfo() const

Encapsulates the data about a macro definition (e.g.

bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const

Return true if the specified macro definition is equal to this macro in spelling, arguments,...

bool isUsed() const

Return false if this macro is defined in the main file and has not yet been used.

bool isC99Varargs() const

bool isAllowRedefinitionsWithoutWarning() const

Return true if this macro can be redefined without warning.

void setHasCommaPasting()

unsigned getNumTokens() const

Return the number of tokens that this macro expands to.

const Token & getReplacementToken(unsigned Tok) const

void setDefinitionEndLoc(SourceLocation EndLoc)

Set the location of the last token in the macro.

bool isBuiltinMacro() const

Return true if this macro requires processing before expansion.

void setTokens(ArrayRef< Token > Tokens, llvm::BumpPtrAllocator &PPAllocator)

void setParameterList(ArrayRef< IdentifierInfo * > List, llvm::BumpPtrAllocator &PPAllocator)

Set the specified list of identifiers as the parameter list for this macro.

SourceLocation getDefinitionLoc() const

Return the location that the macro was defined at.

void setIsFunctionLike()

Function/Object-likeness.

bool isObjectLike() const

void setIsWarnIfUnused(bool val)

Set the value of the IsWarnIfUnused flag.

int getParameterNum(const IdentifierInfo *Arg) const

Return the parameter number of the specified identifier, or -1 if the identifier is not a formal para...

bool isWarnIfUnused() const

Return true if we should emit a warning if the macro is unused.

void setIsC99Varargs()

Varargs querying methods. This can only be set for function-like macros.

Describes the result of attempting to load a module.

bool isMissingExpected() const

Determines whether the module, which failed to load, was actually a submodule that we expected to see...

bool isConfigMismatch() const

Determines whether the module failed to load due to a configuration mismatch with an explicitly-named...

virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective)=0

Attempt to load the given module.

void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, FileEntryRef File)

Reports errors if a module must not include a specific file.

KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)

Retrieve the module that owns the given header file, if any.

bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName, Module *Module) const

OptionalDirectoryEntryRef getBuiltinDir() const

Get the directory that contains Clang-supplied include files.

@ ExcludedHeader

This header is explicitly excluded from the module.

@ TextualHeader

This header is part of the module (for layering purposes) but should be textually included.

Describes a module or submodule.

StringRef getTopLevelModuleName() const

Retrieve the name of the top-level module.

bool isForBuilding(const LangOptions &LangOpts) const

Determine whether this module can be built in this compilation.

@ Hidden

All of the names in this module are hidden.

SourceLocation DefinitionLoc

The location of the module definition.

Module * Parent

The parent of this module.

unsigned IsSystem

Whether this is a "system" module (which assumes that all headers in it are system headers).

std::string Name

The name of this module.

bool isAvailable() const

Determine whether this module is available for use within the current translation unit.

bool isHeaderUnit() const

Is this module a header unit.

Module * ShadowingModule

A module with the same name that shadows this module.

std::string getFullModuleName(bool AllowStringLiterals=false) const

Retrieve the full name of this module, including the path from its top-level module.

Module * getTopLevelModule()

Retrieve the top-level module for this (sub)module, which may be this module.

bool getHasReadAnyTokensVal() const

getHasReadAnyTokensVal - This is used for the #ifndef handshake at the top of the file when reading p...

void ExitTopLevelConditional()

Called when the lexer exits the top-level conditional.

void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc)

void SetReadToken(bool Value)

SetReadToken - Set whether the value of 'ReadAnyTokens'.

bool getImmediatelyAfterTopLevelIfndef() const

getImmediatelyAfterTopLevelIfndef - returns true if the last directive was an #ifndef at the beginnin...

void EnterTopLevelConditional()

Invoked when a top level conditional (except #ifndef) is found.

void resetImmediatelyAfterTopLevelIfndef()

void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc)

Called when entering a top-level #ifndef directive (or the "\#if !defined" equivalent) without any pr...

Preprocessor standard embed parameter "if_empty" if_empty( balanced-token-seq )

Preprocessor standard embed parameter "limit" limit( constant-expression )

Preprocessor extension embed parameter "clang::offset" clang::offset( constant-expression )

Preprocessor standard embed parameter "prefix" prefix( balanced-token-seq )

Preprocessor standard embed parameter "suffix" suffix( balanced-token-seq )

void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse)

pushConditionalLevel - When we enter a #if directive, this keeps track of what we are currently in fo...

unsigned getConditionalStackDepth() const

bool LexingRawMode

True if in raw mode.

bool ParsingPreprocessorDirective

True when parsing #XXX; turns '\n' into a tok::eod token.

MultipleIncludeOpt MIOpt

A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.

bool popConditionalLevel(PPConditionalInfo &CI)

popConditionalLevel - Remove an entry off the top of the conditional stack, returning information abo...

OptionalFileEntryRef getFileEntry() const

getFileEntry - Return the FileEntry corresponding to this FileID.

PPConditionalInfo & peekConditionalLevel()

Return the top of the conditional stack.

virtual SourceLocation getSourceLocation()=0

Return the source location for the next observable location.

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

MacroDirective * getLocalMacroDirective(const IdentifierInfo *II) const

Given an identifier, return its latest non-imported MacroDirective if it is #define'd and not #undef'...

void markClangModuleAsAffecting(Module *M)

Mark the given clang module as affecting the current clang module or translation unit.

OptionalFileEntryRef LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, const FileEntry *LookupFromFile=nullptr)

Given a "Filename" or reference, look up the indicated embed resource.

const MacroInfo * getMacroInfo(const IdentifierInfo *II) const

bool isRecordingPreamble() const

void HandleSkippedDirectiveWhileUsingPCH(Token &Result, SourceLocation HashLoc)

Process directives while skipping until the through header or #pragma hdrstop is found.

bool isInPrimaryFile() const

Return true if we're in the top-level file, not in a #include.

void markMacroAsUsed(MacroInfo *MI)

A macro is used, update information about macros that need unused warnings.

void EnterSubmodule(Module *M, SourceLocation ImportLoc, bool ForPragma)

void setCodeCompletionReached()

Note that we hit the code-completion point.

StringRef getNamedModuleName() const

Get the named module name we're preprocessing.

void makeModuleVisible(Module *M, SourceLocation Loc)

void Lex(Token &Result)

Lex the next token for this preprocessor.

bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)

Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...

void LexNonComment(Token &Result)

Lex a token.

SourceRange DiscardUntilEndOfDirective()

Read and discard all tokens remaining on the current line until the tok::eod token is found.

SourceLocation CheckEndOfDirective(const char *DirType, bool EnableMacros=false)

Ensure that the next token is a tok::eod token.

IdentifierInfo * getIdentifierInfo(StringRef Name) const

Return information about the specified preprocessor identifier token.

SourceManager & getSourceManager() const

MacroDefinition getMacroDefinition(const IdentifierInfo *II)

bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag=nullptr)

bool isMacroDefined(StringRef Id)

static bool checkModuleIsAvailable(const LangOptions &LangOpts, const TargetInfo &TargetInfo, const Module &M, DiagnosticsEngine &Diags)

Check that the given module is available, producing a diagnostic if not.

SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const

Given a location that specifies the start of a token, return a new location that specifies a characte...

Module * getCurrentModule()

Retrieves the module that we're currently building, if any.

bool hadModuleLoaderFatalFailure() const

const TargetInfo & getTargetInfo() const

FileManager & getFileManager() const

bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)

Lex a token, forming a header-name token if possible.

bool isPCHThroughHeader(const FileEntry *FE)

Returns true if the FileEntry is the PCH through header.

friend class VariadicMacroScopeGuard

MacroInfo * AllocateMacroInfo(SourceLocation L)

Allocate a new MacroInfo object with the provided SourceLocation.

void LexUnexpandedToken(Token &Result)

Just like Lex, but disables macro expansion of identifier tokens.

bool alreadyIncluded(FileEntryRef File) const

Return true if this header has already been included.

FileID getPredefinesFileID() const

Returns the FileID for the preprocessor predefines.

void LexUnexpandedNonComment(Token &Result)

Like LexNonComment, but this disables macro expansion of identifier tokens.

StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const

Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...

bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)

Turn the specified lexer token into a fully checked and spelled filename, e.g.

PreprocessorLexer * getCurrentFileLexer() const

Return the current file lexer being lexed from.

HeaderSearch & getHeaderSearchInfo() const

void emitMacroExpansionWarnings(const Token &Identifier, bool IsIfnDef=false) const

void HandleDirective(Token &Result)

Callback invoked when the lexer sees a # token at the start of a line.

void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal)

Enter an annotation token into the token stream.

OptionalFileEntryRef LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, ConstSearchDirIterator FromDir, const FileEntry *FromFile, ConstSearchDirIterator *CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false, bool OpenFile=true, bool CacheFailures=true)

Given a "foo" or reference, look up the indicated file.

const LangOptions & getLangOpts() const

bool isInNamedModule() const

If we are preprocessing a named module.

OptionalFileEntryRef getHeaderToIncludeForDiagnostics(SourceLocation IncLoc, SourceLocation MLoc)

We want to produce a diagnostic at location IncLoc concerning an unreachable effect at location MLoc ...

DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)

void HandlePragmaHdrstop(Token &Tok)

DiagnosticsEngine & getDiagnostics() const

std::optional< LexEmbedParametersResult > LexEmbedParameters(Token &Current, bool ForHasEmbed)

Lex the parameters for an #embed directive, returns nullopt on error.

Module * getModuleForLocation(SourceLocation Loc, bool AllowTextual)

Find the module that owns the source or header file that Loc points to.

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const

Forwarding function for diagnostics.

bool usingPCHWithThroughHeader()

True if using a PCH with a through header.

void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)

Add a directive to the macro directive history for this identifier.

Represents an unpacked "presumed" location which can be presented to the user.

bool isInvalid() const

Return true if this object is invalid or uninitialized.

SourceLocation getIncludeLoc() const

Return the presumed include location of this location.

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.

This class handles loading and caching of source files into memory.

FileID getFileID(SourceLocation SpellingLoc) const

Return the FileID for a SourceLocation.

bool isWrittenInBuiltinFile(SourceLocation Loc) const

Returns whether Loc is located in a file.

bool isInMainFile(SourceLocation Loc) const

Returns whether the PresumedLoc for a given SourceLocation is in the main file.

void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)

Add a line note to the line table for the FileID and offset specified by Loc.

bool isWrittenInCommandLineFile(SourceLocation Loc) const

Returns whether Loc is located in a file.

OptionalFileEntryRef getFileEntryRefForID(FileID FID) const

Returns the FileEntryRef for the provided FileID.

StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const

Return the filename or buffer identifier of the buffer the location is in.

FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)

Create a new FileID that represents the specified file being #included from the specified IncludePosi...

bool isMainFile(const FileEntry &SourceFile)

Returns true when the given FileEntry corresponds to the main file.

FileID getMainFileID() const

Returns the FileID of the main source file.

CharSourceRange getExpansionRange(SourceLocation Loc) const

Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...

unsigned getLineTableFilenameID(StringRef Str)

Return the uniqued ID for the specified filename.

bool isInSystemHeader(SourceLocation Loc) const

Returns if a SourceLocation is in a system header.

SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const

Return the file characteristic of the specified source location, indicating whether this is a normal ...

SourceLocation getExpansionLoc(SourceLocation Loc) const

Given a SourceLocation object Loc, return the expansion location referenced by the ID.

std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)

Retrieve the memory buffer associated with the given file.

A trivial tuple used to represent a source range.

void setBegin(SourceLocation b)

SourceLocation getEnd() const

SourceLocation getBegin() const

void setEnd(SourceLocation e)

StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...

Exposes information about the current target.

Token - This structure provides full information about a lexed token.

IdentifierInfo * getIdentifierInfo() const

SourceLocation getEndLoc() const

void setAnnotationEndLoc(SourceLocation L)

void clearFlag(TokenFlags Flag)

Unset the specified flag.

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)) {....

tok::TokenKind getKind() const

bool isAtStartOfLine() const

isAtStartOfLine - Return true if this token is at the start of a line.

bool hasLeadingSpace() const

Return true if this token has whitespace before it.

void setLocation(SourceLocation L)

bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const

bool isNot(tok::TokenKind K) const

void setAnnotationValue(void *val)

bool hasUDSuffix() const

Return true if this token is a string or character literal which has a ud-suffix.

void startToken()

Reset all flags to cleared.

bool needsCleaning() const

Return true if this token has trigraphs or escaped newlines in it.

void setIdentifierInfo(IdentifierInfo *II)

StringRef getRawIdentifier() const

getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...

A directive for an undefined macro.

A class for tracking whether we're inside a VA_OPT during a traversal of the tokens of a variadic mac...

An RAII class that tracks when the Preprocessor starts and stops lexing the definition of a (ISO C/C+...

void enterScope()

Client code should call this function just before the Preprocessor is about to Lex tokens from the de...

Directive - Abstract class representing a parsed verify directive.

A directive for setting the module visibility of a macro.

Defines the clang::TargetInfo interface.

CharacteristicKind

Indicates whether a file or directory holds normal user code, system code, or system code which is im...

uint32_t Literal

Literals are represented as positive integers.

bool Sub(InterpState &S, CodePtr OpPC)

TokenKind

Provides a simple uniform namespace for tokens from all C languages.

PPKeywordKind

Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.

The JSON file list parser is used to communicate input to InstallAPI.

bool isReservedInAllContexts(ReservedIdentifierStatus Status)

Determine whether an identifier is reserved in all contexts.

LLVM_READONLY char toLowercase(char c)

Converts the given ASCII character to its lowercase equivalent.

MacroUse

Context in which macro name is used.

LLVM_READONLY bool isAlphanumeric(unsigned char c)

Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].

@ Parameter

The parameter type of a method or function.

@ Result

The result type of a method or function.

LLVM_READONLY bool isDigit(unsigned char c)

Return true if this character is an ASCII digit: [0-9].

LLVM_READONLY bool isLowercase(unsigned char c)

Return true if this character is a lowercase ASCII letter: [a-z].

@ PIK_HashPragma

The pragma was introduced via #pragma.

Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...

This structure is used to record entries in our framework cache.

OptionalDirectoryEntryRef Directory

The directory entry which should be used for the cached framework.

std::optional< PPEmbedParameterIfEmpty > MaybeIfEmptyParam

size_t SuffixTokenCount() const

std::optional< PPEmbedParameterSuffix > MaybeSuffixParam

std::optional< PPEmbedParameterPrefix > MaybePrefixParam

size_t PrefixTokenCount() const

Information about the conditional stack (#if directives) currently active.

bool FoundNonSkip

True if we have emitted tokens already, and now we're in an #else block or something.

SourceLocation IfLoc

Location where the conditional started.

bool WasSkipping

True if this was contained in a skipping directive, e.g., in a "\#if 0" block.

bool FoundElse

True if we've seen a #else in this block.