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

1

2

3

4

5

6

7

8

9

10

11

12

13

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

23#include

24

25using namespace clang;

27

28namespace {

29struct MMToken {

30 enum TokenKind {

31 Comma,

32 ConfigMacros,

33 Conflict,

34 EndOfFile,

35 HeaderKeyword,

36 Identifier,

37 Exclaim,

38 ExcludeKeyword,

39 ExplicitKeyword,

40 ExportKeyword,

41 ExportAsKeyword,

42 ExternKeyword,

43 FrameworkKeyword,

44 LinkKeyword,

45 ModuleKeyword,

46 Period,

47 PrivateKeyword,

48 UmbrellaKeyword,

49 UseKeyword,

50 RequiresKeyword,

51 Star,

52 StringLiteral,

53 IntegerLiteral,

54 TextualKeyword,

55 LBrace,

56 RBrace,

57 LSquare,

58 RSquare

59 } Kind;

60

61 SourceLocation::UIntTy Location;

62 unsigned StringLength;

63 union {

64

65 const char *StringData;

66

67

69 };

70

71 void clear() {

72 Kind = EndOfFile;

73 Location = 0;

74 StringLength = 0;

75 StringData = nullptr;

76 }

77

78 bool is(TokenKind K) const { return Kind == K; }

79

80 SourceLocation getLocation() const {

81 return SourceLocation::getFromRawEncoding(Location);

82 }

83

85 return Kind == IntegerLiteral ? IntegerValue : 0;

86 }

87

88 StringRef getString() const {

89 return Kind == IntegerLiteral ? StringRef()

90 : StringRef(StringData, StringLength);

91 }

92};

93

94struct ModuleMapFileParser {

95

96 Lexer &L;

97 DiagnosticsEngine &Diags;

98

99

100 ModuleMapFile MMF{};

101

102 bool HadError = false;

103

104

105 MMToken Tok{};

106

107 bool parseTopLevelDecls();

108 std::optional parseModuleDecl(bool TopLevel);

109 std::optional parseExternModuleDecl();

110 std::optional parseConfigMacrosDecl();

111 std::optional parseConflictDecl();

112 std::optional parseExportDecl();

113 std::optional parseExportAsDecl();

114 std::optional parseUseDecl();

115 std::optional parseRequiresDecl();

116 std::optional parseHeaderDecl(MMToken::TokenKind LeadingToken,

117 SourceLocation LeadingLoc);

118 std::optional parseExcludeDecl(clang::SourceLocation LeadingLoc);

119 std::optional

120 parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);

121 std::optional parseLinkDecl();

122

123 SourceLocation consumeToken();

124 void skipUntil(MMToken::TokenKind K);

125 bool parseModuleId(ModuleId &Id);

126 bool parseOptionalAttributes(ModuleAttributes &Attrs);

127

128 SourceLocation getLocation() const { return Tok.getLocation(); };

129};

130

131std::string formatModuleId(const ModuleId &Id) {

132 std::string result;

133 {

134 llvm::raw_string_ostream OS(result);

135

136 for (unsigned I = 0, N = Id.size(); I != N; ++I) {

137 if (I)

138 OS << ".";

139 OS << Id[I].first;

140 }

141 }

142

143 return result;

144}

145}

146

147std::optional

150 bool IsSystem, unsigned *Offset) {

151 std::optionalllvm::MemoryBufferRef Buffer = SM.getBufferOrNone(ID);

153 LOpts.LangStd = clang::LangStandard::lang_c99;

154 Lexer L(SM.getLocForStartOfFile(ID), LOpts, Buffer->getBufferStart(),

155 Buffer->getBufferStart() + (Offset ? *Offset : 0),

156 Buffer->getBufferEnd());

158

159 ModuleMapFileParser Parser{L, Diags};

160 bool Failed = Parser.parseTopLevelDecls();

161

162 if (Offset) {

163 auto Loc = SM.getDecomposedLoc(Parser.getLocation());

164 assert(Loc.first == ID && "stopped in a different file?");

165 *Offset = Loc.second;

166 }

167

168 if (Failed)

169 return std::nullopt;

171 Parser.MMF.Dir = Dir;

172 Parser.MMF.Start = Start;

173 Parser.MMF.IsSystem = IsSystem;

174 return std::move(Parser.MMF);

175}

176

177bool ModuleMapFileParser::parseTopLevelDecls() {

178 Tok.clear();

179 consumeToken();

180 do {

181 switch (Tok.Kind) {

182 case MMToken::EndOfFile:

183 return HadError;

184 case MMToken::ExternKeyword: {

185 std::optional EMD = parseExternModuleDecl();

186 if (EMD)

187 MMF.Decls.push_back(std::move(*EMD));

188 break;

189 }

190 case MMToken::ExplicitKeyword:

191 case MMToken::ModuleKeyword:

192 case MMToken::FrameworkKeyword: {

193 std::optional MD = parseModuleDecl(true);

194 if (MD)

195 MMF.Decls.push_back(std::move(*MD));

196 break;

197 }

198 case MMToken::Comma:

199 case MMToken::ConfigMacros:

200 case MMToken::Conflict:

201 case MMToken::Exclaim:

202 case MMToken::ExcludeKeyword:

203 case MMToken::ExportKeyword:

204 case MMToken::ExportAsKeyword:

205 case MMToken::HeaderKeyword:

206 case MMToken::Identifier:

207 case MMToken::LBrace:

208 case MMToken::LinkKeyword:

209 case MMToken::LSquare:

210 case MMToken::Period:

211 case MMToken::PrivateKeyword:

212 case MMToken::RBrace:

213 case MMToken::RSquare:

214 case MMToken::RequiresKeyword:

215 case MMToken::Star:

216 case MMToken::StringLiteral:

217 case MMToken::IntegerLiteral:

218 case MMToken::TextualKeyword:

219 case MMToken::UmbrellaKeyword:

220 case MMToken::UseKeyword:

222 HadError = true;

223 consumeToken();

224 break;

225 }

226 } while (true);

227}

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247std::optional ModuleMapFileParser::parseModuleDecl(bool TopLevel) {

248 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||

249 Tok.is(MMToken::FrameworkKeyword));

250

251 ModuleDecl MDecl;

252

253 SourceLocation ExplicitLoc;

256

257

258 if (Tok.is(MMToken::ExplicitKeyword)) {

259 MDecl.Location = ExplicitLoc = consumeToken();

261 }

262

263

264 if (Tok.is(MMToken::FrameworkKeyword)) {

265 SourceLocation FrameworkLoc = consumeToken();

267 MDecl.Location = FrameworkLoc;

269 }

270

271

272 if (Tok.is(MMToken::ModuleKeyword)) {

274 consumeToken();

275 HadError = true;

276 return std::nullopt;

277 }

278 SourceLocation ModuleLoc = consumeToken();

280 MDecl.Location = ModuleLoc;

281

282

283

284 if (Tok.is(MMToken::Star)) {

285 SourceLocation StarLoc = consumeToken();

286 MDecl.Id.push_back({"*", StarLoc});

287 if (TopLevel && !MDecl.Framework) {

288 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);

289 HadError = true;

290 return std::nullopt;

291 }

292 } else {

293

294 if (parseModuleId(MDecl.Id)) {

295 HadError = true;

296 return std::nullopt;

297 }

298 if (!TopLevel) {

299 if (MDecl.Id.size() > 1) {

300 Diags.Report(MDecl.Id.front().second,

301 diag::err_mmap_nested_submodule_id)

302 << SourceRange(MDecl.Id.front().second, MDecl.Id.back().second);

303

304 HadError = true;

305 }

306 } else if (MDecl.Id.size() == 1 && MDecl.Explicit) {

307

308 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);

310 HadError = true;

311 }

312 }

313

314

315 if (parseOptionalAttributes(MDecl.Attrs))

316 return std::nullopt;

317

318

319 if (Tok.is(MMToken::LBrace)) {

321 << MDecl.Id.back().first;

322 HadError = true;

323 return std::nullopt;

324 }

325 SourceLocation LBraceLoc = consumeToken();

326

327 bool Done = false;

328 do {

329 std::optional SubDecl;

330 switch (Tok.Kind) {

331 case MMToken::EndOfFile:

332 case MMToken::RBrace:

333 Done = true;

334 break;

335

336 case MMToken::ConfigMacros:

337

338 if (!TopLevel)

340 SubDecl = parseConfigMacrosDecl();

341 break;

342

343 case MMToken::Conflict:

344 SubDecl = parseConflictDecl();

345 break;

346

347 case MMToken::ExternKeyword:

348 SubDecl = parseExternModuleDecl();

349 break;

350

351 case MMToken::ExplicitKeyword:

352 case MMToken::FrameworkKeyword:

353 case MMToken::ModuleKeyword:

354 SubDecl = parseModuleDecl(false);

355 break;

356

357 case MMToken::ExportKeyword:

358 SubDecl = parseExportDecl();

359 break;

360

361 case MMToken::ExportAsKeyword:

362 if (!TopLevel) {

364 parseExportAsDecl();

365 } else

366 SubDecl = parseExportAsDecl();

367 break;

368

369 case MMToken::UseKeyword:

370 SubDecl = parseUseDecl();

371 break;

372

373 case MMToken::RequiresKeyword:

374 SubDecl = parseRequiresDecl();

375 break;

376

377 case MMToken::TextualKeyword:

378 SubDecl = parseHeaderDecl(MMToken::TextualKeyword, consumeToken());

379 break;

380

381 case MMToken::UmbrellaKeyword: {

382 SourceLocation UmbrellaLoc = consumeToken();

383 if (Tok.is(MMToken::HeaderKeyword))

384 SubDecl = parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);

385 else

386 SubDecl = parseUmbrellaDirDecl(UmbrellaLoc);

387 break;

388 }

389

390 case MMToken::ExcludeKeyword: {

391 SourceLocation ExcludeLoc = consumeToken();

392 if (Tok.is(MMToken::HeaderKeyword))

393 SubDecl = parseHeaderDecl(MMToken::ExcludeKeyword, ExcludeLoc);

394 else

395 SubDecl = parseExcludeDecl(ExcludeLoc);

396 break;

397 }

398

399 case MMToken::PrivateKeyword:

400 SubDecl = parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());

401 break;

402

403 case MMToken::HeaderKeyword:

404 SubDecl = parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());

405 break;

406

407 case MMToken::LinkKeyword:

408 SubDecl = parseLinkDecl();

409 break;

410

411 default:

413 consumeToken();

414 break;

415 }

416 if (SubDecl)

417 MDecl.Decls.push_back(std::move(*SubDecl));

418 } while (!Done);

419

420 if (Tok.is(MMToken::RBrace))

421 consumeToken();

422 else {

424 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);

425 HadError = true;

426 }

427 return std::move(MDecl);

428}

429

430std::optional ModuleMapFileParser::parseExternModuleDecl() {

431 assert(Tok.is(MMToken::ExternKeyword));

432 ExternModuleDecl EMD;

433 EMD.Location = consumeToken();

434

435

436 if (Tok.is(MMToken::ModuleKeyword)) {

438 consumeToken();

439 HadError = true;

440 return std::nullopt;

441 }

442 consumeToken();

443

444

445 if (parseModuleId(EMD.Id)) {

446 HadError = true;

447 return std::nullopt;

448 }

449

450

451 if (Tok.is(MMToken::StringLiteral)) {

453 HadError = true;

454 return std::nullopt;

455 }

456 EMD.Path = Tok.getString();

457 consumeToken();

458

459 return std::move(EMD);

460}

461

462

463

464

465

466

467

468

469std::optional ModuleMapFileParser::parseConfigMacrosDecl() {

470 assert(Tok.is(MMToken::ConfigMacros));

471 ConfigMacrosDecl CMDecl;

472 CMDecl.Location = consumeToken();

473

474

475 ModuleAttributes Attrs;

476 if (parseOptionalAttributes(Attrs))

477 return std::nullopt;

478

480

481

482

483 if (Tok.is(MMToken::Identifier))

484 return std::nullopt;

485

486

487 CMDecl.Macros.push_back(Tok.getString());

488 consumeToken();

489

490 do {

491

492 if (Tok.is(MMToken::Comma))

493 break;

494 consumeToken();

495

496

497

498 if (Tok.is(MMToken::Identifier)) {

500 return std::nullopt;

501 }

502

503

504 CMDecl.Macros.push_back(Tok.getString());

505 consumeToken();

506 } while (true);

507 return std::move(CMDecl);

508}

509

510

511

512

513

514std::optional ModuleMapFileParser::parseConflictDecl() {

515 assert(Tok.is(MMToken::Conflict));

516 ConflictDecl CD;

517 CD.Location = consumeToken();

518

519

520 if (parseModuleId(CD.Id))

521 return std::nullopt;

522

523

524 if (Tok.is(MMToken::Comma)) {

527 return std::nullopt;

528 }

529 consumeToken();

530

531

532 if (Tok.is(MMToken::StringLiteral)) {

534 << formatModuleId(CD.Id);

535 return std::nullopt;

536 }

538 consumeToken();

539 return std::move(CD);

540}

541

542

543

544

545

546

547

548

549

550

551std::optional ModuleMapFileParser::parseExportDecl() {

552 assert(Tok.is(MMToken::ExportKeyword));

553 ExportDecl ED;

554 ED.Location = consumeToken();

555

556

557 ED.Wildcard = false;

558 do {

559

560 if (Tok.is(MMToken::Identifier)) {

561 ED.Id.push_back(

562 std::make_pair(std::string(Tok.getString()), Tok.getLocation()));

563 consumeToken();

564

565 if (Tok.is(MMToken::Period)) {

566 consumeToken();

567 continue;

568 }

569

570 break;

571 }

572

573 if (Tok.is(MMToken::Star)) {

574 ED.Wildcard = true;

575 consumeToken();

576 break;

577 }

578

580 HadError = true;

581 return std::nullopt;

582 } while (true);

583

584 return std::move(ED);

585}

586

587

588

589

590

591std::optional ModuleMapFileParser::parseExportAsDecl() {

592 assert(Tok.is(MMToken::ExportAsKeyword));

593 ExportAsDecl EAD;

594 EAD.Location = consumeToken();

595

596 if (Tok.is(MMToken::Identifier)) {

598 HadError = true;

599 return std::nullopt;

600 }

601

602 if (parseModuleId(EAD.Id))

603 return std::nullopt;

604 if (EAD.Id.size() > 1)

605 Diags.Report(EAD.Id[1].second, diag::err_mmap_qualified_export_as);

606 return std::move(EAD);

607}

608

609

610

611

612

613std::optional ModuleMapFileParser::parseUseDecl() {

614 assert(Tok.is(MMToken::UseKeyword));

615 UseDecl UD;

616 UD.Location = consumeToken();

617 if (parseModuleId(UD.Id))

618 return std::nullopt;

619 return std::move(UD);

620}

621

622

623

624

625

626

627

628

629

630

631

632

633std::optional ModuleMapFileParser::parseRequiresDecl() {

634 assert(Tok.is(MMToken::RequiresKeyword));

635 RequiresDecl RD;

636 RD.Location = consumeToken();

637

638

639 do {

640 bool RequiredState = true;

641 if (Tok.is(MMToken::Exclaim)) {

642 RequiredState = false;

643 consumeToken();

644 }

645

646 if (Tok.is(MMToken::Identifier)) {

648 HadError = true;

649 return std::nullopt;

650 }

651

652

653 RequiresFeature RF;

655 RF.Location = consumeToken();

657

658 RD.Features.push_back(std::move(RF));

659

660 if (Tok.is(MMToken::Comma))

661 break;

662

663

664 consumeToken();

665 } while (true);

666 return std::move(RD);

667}

668

669

670

671

672

673

674

675

676std::optional

677ModuleMapFileParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,

678 clang::SourceLocation LeadingLoc) {

679 HeaderDecl HD;

683

685

686 if (LeadingToken == MMToken::PrivateKeyword) {

688

689 if (Tok.is(MMToken::TextualKeyword)) {

691 LeadingToken = Tok.Kind;

692 consumeToken();

693 }

694 } else if (LeadingToken == MMToken::ExcludeKeyword)

696 else if (LeadingToken == MMToken::TextualKeyword)

698

699 if (LeadingToken != MMToken::HeaderKeyword) {

700 if (Tok.is(MMToken::HeaderKeyword)) {

702 << (LeadingToken == MMToken::PrivateKeyword ? "private"

703 : LeadingToken == MMToken::ExcludeKeyword ? "exclude"

704 : LeadingToken == MMToken::TextualKeyword ? "textual"

705 : "umbrella");

706 return std::nullopt;

707 }

708 consumeToken();

709 }

710

711

712 if (Tok.is(MMToken::StringLiteral)) {

714 HadError = true;

715 return std::nullopt;

716 }

717 HD.Path = Tok.getString();

718 HD.PathLoc = consumeToken();

719 HD.Umbrella = LeadingToken == MMToken::UmbrellaKeyword;

720

721

722

723 if (Tok.is(MMToken::LBrace)) {

724 SourceLocation LBraceLoc = consumeToken();

725

726 while (Tok.is(MMToken::RBrace) && Tok.is(MMToken::EndOfFile)) {

727 enum Attribute { Size, ModTime, Unknown };

728 StringRef Str = Tok.getString();

729 SourceLocation Loc = consumeToken();

730 switch (llvm::StringSwitch(Str)

731 .Case("size", Size)

732 .Case("mtime", ModTime)

736 Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;

737 if (Tok.is(MMToken::IntegerLiteral)) {

739 diag::err_mmap_invalid_header_attribute_value)

740 << Str;

741 skipUntil(MMToken::RBrace);

742 break;

743 }

744 HD.Size = Tok.getInteger();

745 consumeToken();

746 break;

747

748 case ModTime:

750 Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;

751 if (Tok.is(MMToken::IntegerLiteral)) {

753 diag::err_mmap_invalid_header_attribute_value)

754 << Str;

755 skipUntil(MMToken::RBrace);

756 break;

757 }

759 consumeToken();

760 break;

761

763 Diags.Report(Loc, diag::err_mmap_expected_header_attribute);

764 skipUntil(MMToken::RBrace);

765 break;

766 }

767 }

768

769 if (Tok.is(MMToken::RBrace))

770 consumeToken();

771 else {

773 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);

774 HadError = true;

775 }

776 }

777 return std::move(HD);

778}

779

780

781

782

783

784std::optional

785ModuleMapFileParser::parseExcludeDecl(clang::SourceLocation LeadingLoc) {

786

787 if (Tok.is(MMToken::Identifier)) {

789 HadError = true;

790 return std::nullopt;

791 }

792

793 ExcludeDecl ED;

796 consumeToken();

797 return std::move(ED);

798}

799

800

801

802

803

804std::optional

805ModuleMapFileParser::parseUmbrellaDirDecl(clang::SourceLocation UmbrellaLoc) {

806 UmbrellaDirDecl UDD;

808

809 if (Tok.is(MMToken::StringLiteral)) {

811 << "umbrella";

812 HadError = true;

813 return std::nullopt;

814 }

815

816 UDD.Path = Tok.getString();

817 consumeToken();

818 return std::move(UDD);

819}

820

821

822

823

824

825std::optional ModuleMapFileParser::parseLinkDecl() {

826 assert(Tok.is(MMToken::LinkKeyword));

827 LinkDecl LD;

828 LD.Location = consumeToken();

829

830

832 if (Tok.is(MMToken::FrameworkKeyword)) {

833 consumeToken();

835 }

836

837

838 if (Tok.is(MMToken::StringLiteral)) {

841 HadError = true;

842 return std::nullopt;

843 }

844

846 consumeToken();

847 return std::move(LD);

848}

849

850SourceLocation ModuleMapFileParser::consumeToken() {

852

853retry:

854 Tok.clear();

855 Token LToken;

858 switch (LToken.getKind()) {

859 case tok::raw_identifier: {

861 Tok.StringData = RI.data();

862 Tok.StringLength = RI.size();

863 Tok.Kind = llvm::StringSwitchMMToken::TokenKind(RI)

864 .Case("config_macros", MMToken::ConfigMacros)

865 .Case("conflict", MMToken::Conflict)

866 .Case("exclude", MMToken::ExcludeKeyword)

867 .Case("explicit", MMToken::ExplicitKeyword)

868 .Case("export", MMToken::ExportKeyword)

869 .Case("export_as", MMToken::ExportAsKeyword)

870 .Case("extern", MMToken::ExternKeyword)

871 .Case("framework", MMToken::FrameworkKeyword)

872 .Case("header", MMToken::HeaderKeyword)

873 .Case("link", MMToken::LinkKeyword)

874 .Case("module", MMToken::ModuleKeyword)

875 .Case("private", MMToken::PrivateKeyword)

876 .Case("requires", MMToken::RequiresKeyword)

877 .Case("textual", MMToken::TextualKeyword)

878 .Case("umbrella", MMToken::UmbrellaKeyword)

879 .Case("use", MMToken::UseKeyword)

880 .Default(MMToken::Identifier);

881 break;

882 }

883

884 case tok::comma:

885 Tok.Kind = MMToken::Comma;

886 break;

887

888 case tok::eof:

889 Tok.Kind = MMToken::EndOfFile;

890 break;

891

892 case tok::l_brace:

893 Tok.Kind = MMToken::LBrace;

894 break;

895

896 case tok::l_square:

897 Tok.Kind = MMToken::LSquare;

898 break;

899

900 case tok::period:

901 Tok.Kind = MMToken::Period;

902 break;

903

904 case tok::r_brace:

905 Tok.Kind = MMToken::RBrace;

906 break;

907

908 case tok::r_square:

909 Tok.Kind = MMToken::RSquare;

910 break;

911

912 case tok:⭐

913 Tok.Kind = MMToken::Star;

914 break;

915

916 case tok::exclaim:

917 Tok.Kind = MMToken::Exclaim;

918 break;

919

920 case tok::string_literal: {

922 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);

923 HadError = true;

924 goto retry;

925 }

926

927

928 Tok.Kind = MMToken::StringLiteral;

931 break;

932 }

933

934 case tok::numeric_constant: {

935

938 .getAsInteger(0, Value)) {

940 HadError = true;

941 goto retry;

942 }

943

944 Tok.Kind = MMToken::IntegerLiteral;

946 break;

947 }

948

949 case tok::comment:

950 goto retry;

951

952 case tok::hash:

953

954

955

956

957 {

958 auto NextIsIdent = [&](StringRef Str) -> bool {

960 return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&

962 };

963 if (NextIsIdent("pragma") && NextIsIdent("clang") &&

964 NextIsIdent("module") && NextIsIdent("contents")) {

965 Tok.Kind = MMToken::EndOfFile;

966 break;

967 }

968 }

969 [[fallthrough]];

970

971 default:

973 HadError = true;

974 goto retry;

975 }

976

978}

979

980void ModuleMapFileParser::skipUntil(MMToken::TokenKind K) {

981 unsigned braceDepth = 0;

982 unsigned squareDepth = 0;

983 do {

984 switch (Tok.Kind) {

985 case MMToken::EndOfFile:

986 return;

987

988 case MMToken::LBrace:

989 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)

990 return;

991

992 ++braceDepth;

993 break;

994

995 case MMToken::LSquare:

996 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)

997 return;

998

999 ++squareDepth;

1000 break;

1001

1002 case MMToken::RBrace:

1003 if (braceDepth > 0)

1004 --braceDepth;

1005 else if (Tok.is(K))

1006 return;

1007 break;

1008

1009 case MMToken::RSquare:

1010 if (squareDepth > 0)

1011 --squareDepth;

1012 else if (Tok.is(K))

1013 return;

1014 break;

1015

1016 default:

1017 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))

1018 return;

1019 break;

1020 }

1021

1022 consumeToken();

1023 } while (true);

1024}

1025

1026

1027

1028

1029

1030

1031

1032

1033bool ModuleMapFileParser::parseModuleId(ModuleId &Id) {

1034 Id.clear();

1035 do {

1036 if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {

1037 Id.push_back(

1038 std::make_pair(std::string(Tok.getString()), Tok.getLocation()));

1039 consumeToken();

1040 } else {

1042 return true;

1043 }

1044

1045 if (Tok.is(MMToken::Period))

1046 break;

1047

1048 consumeToken();

1049 } while (true);

1050

1051 return false;

1052}

1053

1054

1055

1056

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066bool ModuleMapFileParser::parseOptionalAttributes(ModuleAttributes &Attrs) {

1067 bool Error = false;

1068

1069 while (Tok.is(MMToken::LSquare)) {

1070

1071 SourceLocation LSquareLoc = consumeToken();

1072

1073

1074 if (Tok.is(MMToken::Identifier)) {

1076 skipUntil(MMToken::RSquare);

1077 if (Tok.is(MMToken::RSquare))

1078 consumeToken();

1080 }

1081

1082

1083 enum AttributeKind {

1084

1085 AT_unknown,

1086

1087

1088 AT_system,

1089

1090

1091 AT_extern_c,

1092

1093

1094 AT_exhaustive,

1095

1096

1097 AT_no_undeclared_includes

1098 };

1099

1100

1101 AttributeKind Attribute =

1102 llvm::StringSwitch(Tok.getString())

1103 .Case("exhaustive", AT_exhaustive)

1104 .Case("extern_c", AT_extern_c)

1105 .Case("no_undeclared_includes", AT_no_undeclared_includes)

1106 .Case("system", AT_system)

1107 .Default(AT_unknown);

1108 switch (Attribute) {

1109 case AT_unknown:

1111 << Tok.getString();

1112 break;

1113

1114 case AT_system:

1116 break;

1117

1118 case AT_extern_c:

1120 break;

1121

1122 case AT_exhaustive:

1124 break;

1125

1126 case AT_no_undeclared_includes:

1128 break;

1129 }

1130 consumeToken();

1131

1132

1133 if (Tok.is(MMToken::RSquare)) {

1135 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);

1136 skipUntil(MMToken::RSquare);

1138 }

1139

1140 if (Tok.is(MMToken::RSquare))

1141 consumeToken();

1142 }

1143

1145 HadError = true;

1146

1148}

1149

1150static void dumpModule(const ModuleDecl &MD, llvm::raw_ostream &out, int depth);

1151

1153 llvm::raw_ostream &out, int depth) {

1154 out.indent(depth * 2);

1155 out << "extern module " << formatModuleId(EMD.Id) << " \"" << EMD.Path

1156 << "\"\n";

1157}

1158

1160 for (const auto &Decl : Decls) {

1161 std::visit(llvm::makeVisitor(

1163 out.indent(depth * 2);

1164 out << "requires\n";

1165 },

1167 out.indent(depth * 2);

1169 out << "private ";

1171 out << "textual ";

1173 out << "excluded ";

1175 out << "umbrella ";

1176 out << "header \"" << HD.Path << "\"\n";

1177 },

1179 out.indent(depth * 2);

1180 out << "umbrella\n";

1181 },

1184 out.indent(depth * 2);

1185 out << "exclude " << ED.Module << "\n";

1186 },

1188 out.indent(depth * 2);

1189 out << "export "

1190 << (ED.Wildcard ? "*" : formatModuleId(ED.Id)) << "\n";

1191 },

1193 out.indent(depth * 2);

1194 out << "export as\n";

1195 },

1198 },

1199 [&](const UseDecl &UD) {

1200 out.indent(depth * 2);

1201 out << "use\n";

1202 },

1204 out.indent(depth * 2);

1205 out << "link\n";

1206 },

1208 out.indent(depth * 2);

1209 out << "config_macros ";

1210 if (CMD.Exhaustive)

1211 out << "[exhaustive] ";

1212 for (auto Macro : CMD.Macros) {

1214 }

1215 out << "\n";

1216 },

1218 out.indent(depth * 2);

1219 out << "conflicts\n";

1220 }),

1222 }

1223}

1224

1226 int depth) {

1227 out.indent(depth * 2);

1228 out << "module " << formatModuleId(MD.Id) << "\n";

1230}

1231

1233 for (const auto &Decl : Decls) {

1234 std::visit(

1238 }),

1240 }

1241}

Defines the Diagnostic-related interfaces.

bool is(tok::TokenKind Kind) const

Defines the clang::LangOptions interface.

static void dumpModule(const ModuleDecl &MD, llvm::raw_ostream &out, int depth)

Definition ModuleMapFile.cpp:1225

static void dumpDecls(ArrayRef< Decl > Decls, llvm::raw_ostream &out, int depth)

Definition ModuleMapFile.cpp:1159

static void dumpExternModule(const ExternModuleDecl &EMD, llvm::raw_ostream &out, int depth)

Definition ModuleMapFile.cpp:1152

Defines the clang::Module class, which describes a module in the source code.

Defines the SourceManager interface.

Decl - This represents one declaration (or definition), e.g.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

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

Represents a standard C++ module export declaration.

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

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

LangStandard::Kind LangStd

The used language standard.

Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.

bool LexFromRawLexer(Token &Result)

LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...

SourceLocation getSourceLocation(const char *Loc, unsigned TokLen=1) const

getSourceLocation - Return a source location identifier for the specified offset in the current file.

Parser - This implements a parser for the C family of languages.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

UIntTy getRawEncoding() const

When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.

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

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

unsigned getLength() const

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 hasUDSuffix() const

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

StringRef getRawIdentifier() const

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

const char * getLiteralData() const

getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

std::optional< ModuleMapFile > parseModuleMap(FileID ID, clang::DirectoryEntryRef Dir, SourceManager &SM, DiagnosticsEngine &Diags, bool IsSystem, unsigned *Offset)

Parse a module map file into an in memory representation.

Definition ModuleMapFile.cpp:148

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

SmallVector< std::pair< std::string, SourceLocation >, 2 > ModuleId

Describes the name of a module.

@ Result

The result type of a method or function.

unsigned IsExternC

Whether this is an extern "C" module.

unsigned IsSystem

Whether this is a system module.

unsigned IsExhaustive

Whether this is an exhaustive set of configuration macros.

unsigned NoUndeclaredIncludes

Whether files in this module can only include non-modular headers and headers from used modules.

std::vector< StringRef > Macros

ModuleAttributes Attrs

Points to the first keyword in the decl.

std::vector< Decl > Decls

std::vector< TopLevelDecl > Decls

void dump(llvm::raw_ostream &out) const

Definition ModuleMapFile.cpp:1232

std::vector< RequiresFeature > Features