@@ -2364,20 +2364,19 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
2364
2364
}
2365
2365
2366
2366
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > Path;
2367
- if (ParseModuleName (ModuleLoc, Path, /* IsImport*/ false ))
2367
+ if (ParseModuleName (ModuleLoc, Path, /* IsImport*/ false ))
2368
2368
return nullptr ;
2369
2369
2370
2370
// Parse the optional module-partition.
2371
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > Partition;
2371
2372
if (Tok.is (tok::colon)) {
2372
2373
SourceLocation ColonLoc = ConsumeToken ();
2373
- SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > Partition;
2374
- if (ParseModuleName (ModuleLoc, Partition, /* IsImport*/ false ))
2374
+ if (!getLangOpts ().CPlusPlusModules )
2375
+ Diag (ColonLoc, diag::err_unsupported_module_partition)
2376
+ << SourceRange (ColonLoc, Partition.back ().second );
2377
+ // Recover by ignoring the partition name.
2378
+ else if (ParseModuleName (ModuleLoc, Partition, /* IsImport*/ false ))
2375
2379
return nullptr ;
2376
-
2377
- // FIXME: Support module partition declarations.
2378
- Diag (ColonLoc, diag::err_unsupported_module_partition)
2379
- << SourceRange (ColonLoc, Partition.back ().second );
2380
- // Recover by parsing as a non-partition.
2381
2380
}
2382
2381
2383
2382
// We don't support any module attributes yet; just parse them and diagnose.
@@ -2387,18 +2386,19 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) {
2387
2386
2388
2387
ExpectAndConsumeSemi (diag::err_module_expected_semi);
2389
2388
2390
- return Actions.ActOnModuleDecl (StartLoc, ModuleLoc, MDK, Path, ImportState);
2389
+ return Actions.ActOnModuleDecl (StartLoc, ModuleLoc, MDK, Path, Partition,
2390
+ ImportState);
2391
2391
}
2392
2392
2393
2393
// / Parse a module import declaration. This is essentially the same for
2394
- // / Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC)
2395
- // / and the trailing optional attributes (in C++).
2394
+ // / Objective-C and C++20 except for the leading '@' (in ObjC) and the
2395
+ // / trailing optional attributes (in C++).
2396
2396
// /
2397
2397
// / [ObjC] @import declaration:
2398
2398
// / '@' 'import' module-name ';'
2399
2399
// / [ModTS] module-import-declaration:
2400
2400
// / 'import' module-name attribute-specifier-seq[opt] ';'
2401
- // / [C++2a ] module-import-declaration:
2401
+ // / [C++20 ] module-import-declaration:
2402
2402
// / 'export'[opt] 'import' module-name
2403
2403
// / attribute-specifier-seq[opt] ';'
2404
2404
// / 'export'[opt] 'import' module-partition
@@ -2418,9 +2418,10 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
2418
2418
bool IsObjCAtImport = Tok.isObjCAtKeyword (tok::objc_import);
2419
2419
SourceLocation ImportLoc = ConsumeToken ();
2420
2420
2421
+ // For C++20 modules, we can have "name" or ":Partition name" as valid input.
2421
2422
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > Path;
2423
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2 > Partition;
2422
2424
Module *HeaderUnit = nullptr ;
2423
-
2424
2425
if (Tok.is (tok::header_name)) {
2425
2426
// This is a header import that the preprocessor decided we should skip
2426
2427
// because it was malformed in some way. Parse and ignore it; it's already
@@ -2430,17 +2431,16 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
2430
2431
// This is a header import that the preprocessor mapped to a module import.
2431
2432
HeaderUnit = reinterpret_cast <Module *>(Tok.getAnnotationValue ());
2432
2433
ConsumeAnnotationToken ();
2433
- } else if (getLangOpts (). CPlusPlusModules && Tok.is (tok::colon)) {
2434
+ } else if (Tok.is (tok::colon)) {
2434
2435
SourceLocation ColonLoc = ConsumeToken ();
2435
- if (ParseModuleName (ImportLoc, Path, /* IsImport*/ true ))
2436
+ if (!getLangOpts ().CPlusPlusModules )
2437
+ Diag (ColonLoc, diag::err_unsupported_module_partition)
2438
+ << SourceRange (ColonLoc, Partition.back ().second );
2439
+ // Recover by leaving partition empty.
2440
+ else if (ParseModuleName (ColonLoc, Partition, /* IsImport*/ true ))
2436
2441
return nullptr ;
2437
-
2438
- // FIXME: Support module partition import.
2439
- Diag (ColonLoc, diag::err_unsupported_module_partition)
2440
- << SourceRange (ColonLoc, Path.back ().second );
2441
- return nullptr ;
2442
2442
} else {
2443
- if (ParseModuleName (ImportLoc, Path, /* IsImport*/ true ))
2443
+ if (ParseModuleName (ImportLoc, Path, /* IsImport*/ true ))
2444
2444
return nullptr ;
2445
2445
}
2446
2446
@@ -2457,21 +2457,24 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
2457
2457
2458
2458
// Diagnose mis-imports.
2459
2459
bool SeenError = true ;
2460
+ bool HasPart = !Partition.empty ();
2460
2461
switch (ImportState) {
2461
2462
case Sema::ModuleImportState::ImportAllowed:
2462
2463
SeenError = false ;
2463
2464
break ;
2464
2465
case Sema::ModuleImportState::FirstDecl:
2465
2466
case Sema::ModuleImportState::NotACXX20Module:
2466
- // TODO: These cases will be an error when partitions are implemented.
2467
- SeenError = false ;
2467
+ // We can only import a partition within a module purview.
2468
+ if (HasPart)
2469
+ Diag (ImportLoc, diag::err_partition_import_outside_module);
2470
+ else
2471
+ SeenError = false ;
2468
2472
break ;
2469
2473
case Sema::ModuleImportState::GlobalFragment:
2470
2474
// We can only have pre-processor directives in the global module
2471
2475
// fragment. We can, however have a header unit import here.
2472
2476
if (!HeaderUnit)
2473
- // We do not have partition support yet, so first arg is 0.
2474
- Diag (ImportLoc, diag::err_import_in_wrong_fragment) << 0 << 0 ;
2477
+ Diag (ImportLoc, diag::err_import_in_wrong_fragment) << HasPart << 0 ;
2475
2478
else
2476
2479
SeenError = false ;
2477
2480
break ;
@@ -2482,8 +2485,7 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
2482
2485
SeenError = false ;
2483
2486
break ;
2484
2487
case Sema::ModuleImportState::PrivateFragment:
2485
- // We do not have partition support yet, so first arg is 0.
2486
- Diag (ImportLoc, diag::err_import_in_wrong_fragment) << 0 << 1 ;
2488
+ Diag (ImportLoc, diag::err_import_in_wrong_fragment) << HasPart << 1 ;
2487
2489
break ;
2488
2490
}
2489
2491
if (SeenError) {
@@ -2495,8 +2497,9 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
2495
2497
if (HeaderUnit)
2496
2498
Import =
2497
2499
Actions.ActOnModuleImport (StartLoc, ExportLoc, ImportLoc, HeaderUnit);
2498
- else if (!Path.empty ())
2499
- Import = Actions.ActOnModuleImport (StartLoc, ExportLoc, ImportLoc, Path);
2500
+ else if (!Path.empty () || !Partition.empty ())
2501
+ Import = Actions.ActOnModuleImport (StartLoc, ExportLoc, ImportLoc, Path,
2502
+ Partition);
2500
2503
ExpectAndConsumeSemi (diag::err_module_expected_semi);
2501
2504
if (Import.isInvalid ())
2502
2505
return nullptr ;
0 commit comments