@@ -313,6 +313,9 @@ class Preprocessor {
313
313
// / The import path for named module that we're currently processing.
314
314
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > NamedModuleImportPath;
315
315
316
+ // / Whether the import is an `@import` or a standard c++ modules import.
317
+ bool IsAtImport = false ;
318
+
316
319
// / Whether the last token we lexed was an '@'.
317
320
bool LastTokenWasAt = false ;
318
321
@@ -456,6 +459,144 @@ class Preprocessor {
456
459
457
460
TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer;
458
461
462
+ // / Track the status of the c++20 module decl.
463
+ // /
464
+ // / module-declaration:
465
+ // / 'export'[opt] 'module' module-name module-partition[opt]
466
+ // / attribute-specifier-seq[opt] ';'
467
+ // /
468
+ // / module-name:
469
+ // / module-name-qualifier[opt] identifier
470
+ // /
471
+ // / module-partition:
472
+ // / ':' module-name-qualifier[opt] identifier
473
+ // /
474
+ // / module-name-qualifier:
475
+ // / identifier '.'
476
+ // / module-name-qualifier identifier '.'
477
+ // /
478
+ // / Transition state:
479
+ // /
480
+ // / NotAModuleDecl --- export ---> FoundExport
481
+ // / NotAModuleDecl --- module ---> ImplementationCandidate
482
+ // / FoundExport --- module ---> InterfaceCandidate
483
+ // / ImplementationCandidate --- Identifier ---> ImplementationCandidate
484
+ // / ImplementationCandidate --- period ---> ImplementationCandidate
485
+ // / ImplementationCandidate --- colon ---> ImplementationCandidate
486
+ // / InterfaceCandidate --- Identifier ---> InterfaceCandidate
487
+ // / InterfaceCandidate --- period ---> InterfaceCandidate
488
+ // / InterfaceCandidate --- colon ---> InterfaceCandidate
489
+ // / ImplementationCandidate --- Semi ---> NamedModuleImplementation
490
+ // / NamedModuleInterface --- Semi ---> NamedModuleInterface
491
+ // / NamedModuleImplementation --- Anything ---> NamedModuleImplementation
492
+ // / NamedModuleInterface --- Anything ---> NamedModuleInterface
493
+ // /
494
+ // / FIXME: We haven't handle attribute-specifier-seq here. It may not be bad
495
+ // / soon since we don't support any module attributes yet.
496
+ class ModuleDeclSeq {
497
+ enum ModuleDeclState : int {
498
+ NotAModuleDecl,
499
+ FoundExport,
500
+ InterfaceCandidate,
501
+ ImplementationCandidate,
502
+ NamedModuleInterface,
503
+ NamedModuleImplementation,
504
+ };
505
+
506
+ public:
507
+ ModuleDeclSeq () : State(NotAModuleDecl) {}
508
+
509
+ void handleExport () {
510
+ if (State == NotAModuleDecl)
511
+ State = FoundExport;
512
+ else if (!isNamedModule ())
513
+ reset ();
514
+ }
515
+
516
+ void handleModule () {
517
+ if (State == FoundExport)
518
+ State = InterfaceCandidate;
519
+ else if (State == NotAModuleDecl)
520
+ State = ImplementationCandidate;
521
+ else if (!isNamedModule ())
522
+ reset ();
523
+ }
524
+
525
+ void handleIdentifier (IdentifierInfo *Identifier) {
526
+ if (isModuleCandidate () && Identifier)
527
+ Name += Identifier->getName ().str ();
528
+ else if (!isNamedModule ())
529
+ reset ();
530
+ }
531
+
532
+ void handleColon () {
533
+ if (isModuleCandidate ())
534
+ Name += " :" ;
535
+ else if (!isNamedModule ())
536
+ reset ();
537
+ }
538
+
539
+ void handlePeriod () {
540
+ if (isModuleCandidate ())
541
+ Name += " ." ;
542
+ else if (!isNamedModule ())
543
+ reset ();
544
+ }
545
+
546
+ void handleSemi () {
547
+ if (!Name.empty () && isModuleCandidate ()) {
548
+ if (State == InterfaceCandidate)
549
+ State = NamedModuleInterface;
550
+ else if (State == ImplementationCandidate)
551
+ State = NamedModuleImplementation;
552
+ else
553
+ llvm_unreachable (" Unimaged ModuleDeclState." );
554
+ } else if (!isNamedModule ())
555
+ reset ();
556
+ }
557
+
558
+ void handleMisc () {
559
+ if (!isNamedModule ())
560
+ reset ();
561
+ }
562
+
563
+ bool isModuleCandidate () const {
564
+ return State == InterfaceCandidate || State == ImplementationCandidate;
565
+ }
566
+
567
+ bool isNamedModule () const {
568
+ return State == NamedModuleInterface ||
569
+ State == NamedModuleImplementation;
570
+ }
571
+
572
+ bool isNamedInterface () const { return State == NamedModuleInterface; }
573
+
574
+ bool isImplementationUnit () const {
575
+ return State == NamedModuleImplementation && !getName ().contains (' :' );
576
+ }
577
+
578
+ StringRef getName () const {
579
+ assert (isNamedModule () && " Can't get name from a non named module" );
580
+ return Name;
581
+ }
582
+
583
+ StringRef getPrimaryName () const {
584
+ assert (isNamedModule () && " Can't get name from a non named module" );
585
+ return getName ().split (' :' ).first ;
586
+ }
587
+
588
+ void reset () {
589
+ Name.clear ();
590
+ State = NotAModuleDecl;
591
+ }
592
+
593
+ private:
594
+ ModuleDeclState State;
595
+ std::string Name;
596
+ };
597
+
598
+ ModuleDeclSeq ModuleDeclState;
599
+
459
600
// / Whether the module import expects an identifier next. Otherwise,
460
601
// / it expects a '.' or ';'.
461
602
bool ModuleImportExpectsIdentifier = false ;
@@ -2225,6 +2366,36 @@ class Preprocessor {
2225
2366
// / Retrieves the module whose implementation we're current compiling, if any.
2226
2367
Module *getCurrentModuleImplementation ();
2227
2368
2369
+ // / If we are preprocessing a named module.
2370
+ bool isInNamedModule () const { return ModuleDeclState.isNamedModule (); }
2371
+
2372
+ // / If we are proprocessing a named interface unit.
2373
+ // / Note that a module implementation partition is not considered as an
2374
+ // / named interface unit here although it is importable
2375
+ // / to ease the parsing.
2376
+ bool isInNamedInterfaceUnit () const {
2377
+ return ModuleDeclState.isNamedInterface ();
2378
+ }
2379
+
2380
+ // / Get the named module name we're preprocessing.
2381
+ // / Requires we're preprocessing a named module.
2382
+ StringRef getNamedModuleName () const { return ModuleDeclState.getName (); }
2383
+
2384
+ // / If we are implementing an implementation module unit.
2385
+ // / Note that the module implementation partition is not considered as an
2386
+ // / implementation unit.
2387
+ bool isInImplementationUnit () const {
2388
+ return ModuleDeclState.isImplementationUnit ();
2389
+ }
2390
+
2391
+ // / If we're importing a standard C++20 Named Modules.
2392
+ bool isInImportingCXXNamedModules () const {
2393
+ // NamedModuleImportPath will be non-empty only if we're importing
2394
+ // Standard C++ named modules.
2395
+ return !NamedModuleImportPath.empty () && getLangOpts ().CPlusPlusModules &&
2396
+ !IsAtImport;
2397
+ }
2398
+
2228
2399
// / Allocate a new MacroInfo object with the provided SourceLocation.
2229
2400
MacroInfo *AllocateMacroInfo (SourceLocation L);
2230
2401
0 commit comments