@@ -2445,19 +2445,116 @@ namespace {
2445
2445
auto importedName = importFullName (decl, correctSwiftName);
2446
2446
if (!importedName) return nullptr ;
2447
2447
2448
- auto dc =
2448
+ auto extensionDC =
2449
2449
Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
2450
- if (!dc )
2450
+ if (!extensionDC )
2451
2451
return nullptr ;
2452
2452
2453
2453
SourceLoc loc = Impl.importSourceLoc (decl->getBeginLoc ());
2454
-
2455
- // FIXME: If Swift gets namespaces, import as a namespace.
2456
- auto enumDecl = Impl.createDeclWithClangNode <EnumDecl>(
2454
+ DeclContext *dc = nullptr ;
2455
+ // If this is a top-level namespace, don't put it in the module we're
2456
+ // importing, put it in the "__ObjC" module that is implicitly imported.
2457
+ // This way, if we have multiple modules that all open the same namespace,
2458
+ // we won't import multiple enums with the same name in swift.
2459
+ if (extensionDC->getContextKind () == DeclContextKind::FileUnit)
2460
+ dc = Impl.ImportedHeaderUnit ;
2461
+ else {
2462
+ // This is a nested namespace, we need to find its extension decl
2463
+ // context and then use that to find the parent enum. It's important
2464
+ // that we add this to the parent enum (in the "__ObjC" module) and not
2465
+ // to the extension.
2466
+ auto parentNS = cast<clang::NamespaceDecl>(decl->getParent ());
2467
+ auto parent = Impl.importDecl (parentNS, getVersion ());
2468
+ // Sometimes when the parent namespace is imported, this namespace
2469
+ // also gets imported. If that's the case, then the parent namespace
2470
+ // will be an enum (because it was able to be fully imported) in which
2471
+ // case we need to bail here.
2472
+ auto cachedResult =
2473
+ Impl.ImportedDecls .find ({decl->getCanonicalDecl (), getVersion ()});
2474
+ if (cachedResult != Impl.ImportedDecls .end ())
2475
+ return cachedResult->second ;
2476
+ dc = cast<ExtensionDecl>(parent)
2477
+ ->getExtendedType ()
2478
+ ->getEnumOrBoundGenericEnum ();
2479
+ }
2480
+ auto *enumDecl = Impl.createDeclWithClangNode <EnumDecl>(
2457
2481
decl, AccessLevel::Public, loc,
2458
2482
importedName.getDeclName ().getBaseIdentifier (),
2459
2483
Impl.importSourceLoc (decl->getLocation ()), None, nullptr , dc);
2460
- enumDecl->setMemberLoader (&Impl, 0 );
2484
+ if (isa<clang::NamespaceDecl>(decl->getParent ()))
2485
+ cast<EnumDecl>(dc)->addMember (enumDecl);
2486
+
2487
+ // We are creating an extension, so put it at the top level. This is done
2488
+ // after creating the enum, though, because we may need the correctly
2489
+ // nested decl context above when creating the enum.
2490
+ while (extensionDC->getParent () &&
2491
+ extensionDC->getContextKind () != DeclContextKind::FileUnit)
2492
+ extensionDC = extensionDC->getParent ();
2493
+
2494
+ auto *extension = ExtensionDecl::create (Impl.SwiftContext , loc, nullptr ,
2495
+ {}, extensionDC, nullptr , decl);
2496
+ Impl.SwiftContext .evaluator .cacheOutput (ExtendedTypeRequest{extension},
2497
+ enumDecl->getDeclaredType ());
2498
+ Impl.SwiftContext .evaluator .cacheOutput (ExtendedNominalRequest{extension},
2499
+ std::move (enumDecl));
2500
+ // Keep track of what members we've already added so we don't add the same
2501
+ // member twice. Note: we can't use "ImportedDecls" for this because we
2502
+ // might import a decl that we don't add (for example, if it was a
2503
+ // parameter to another decl).
2504
+ SmallPtrSet<Decl *, 16 > addedMembers;
2505
+ for (auto redecl : decl->redecls ()) {
2506
+ // This will be reset as the EnumDecl after we return from
2507
+ // VisitNamespaceDecl.
2508
+ Impl.ImportedDecls [{redecl->getCanonicalDecl (), getVersion ()}] =
2509
+ extension;
2510
+
2511
+ // Insert these backwards into "namespaceDecls" so we can pop them off
2512
+ // the end without loosing order.
2513
+ SmallVector<clang::Decl *, 16 > namespaceDecls;
2514
+ auto addDeclsReversed = [&](auto decls) {
2515
+ auto begin = decls.begin ();
2516
+ auto end = decls.end ();
2517
+ int currentSize = namespaceDecls.size ();
2518
+ int declCount = currentSize + std::distance (begin, end);
2519
+ namespaceDecls.resize (declCount);
2520
+ for (int index = declCount - 1 ; index >= currentSize; --index)
2521
+ namespaceDecls[index] = *(begin++);
2522
+ };
2523
+ addDeclsReversed (redecl->decls ());
2524
+ while (!namespaceDecls.empty ()) {
2525
+ auto nd = dyn_cast<clang::NamedDecl>(namespaceDecls.pop_back_val ());
2526
+ // Make sure we only import the defenition of a record.
2527
+ if (auto tagDecl = dyn_cast_or_null<clang::TagDecl>(nd))
2528
+ // Some decls, for example ClassTemplateSpecializationDecls, won't
2529
+ // have a definition here. That's OK.
2530
+ nd = tagDecl->getDefinition () ? tagDecl->getDefinition () : tagDecl;
2531
+ if (!nd)
2532
+ continue ;
2533
+
2534
+ // Special case class templates: import all their specilizations here.
2535
+ if (auto classTemplate = dyn_cast<clang::ClassTemplateDecl>(nd)) {
2536
+ addDeclsReversed (classTemplate->specializations ());
2537
+ continue ;
2538
+ }
2539
+
2540
+ auto member = Impl.importDecl (nd, getVersion ());
2541
+ if (!member || addedMembers.count (member) ||
2542
+ isa<clang::NamespaceDecl>(nd))
2543
+ continue ;
2544
+ // This happens (for example) when a struct is declared inside another
2545
+ // struct inside a namespace but defined out of line.
2546
+ assert (member->getDeclContext ()->getAsDecl ());
2547
+ if (dyn_cast<ExtensionDecl>(member->getDeclContext ()->getAsDecl ()) !=
2548
+ extension)
2549
+ continue ;
2550
+ extension->addMember (member);
2551
+ addedMembers.insert (member);
2552
+ }
2553
+ }
2554
+
2555
+ if (!extension->getMembers ().empty ())
2556
+ enumDecl->addExtension (extension);
2557
+
2461
2558
return enumDecl;
2462
2559
}
2463
2560
@@ -8583,6 +8680,7 @@ DeclContext *ClangImporter::Implementation::importDeclContextImpl(
8583
8680
auto decl = dyn_cast<clang::NamedDecl>(dc);
8584
8681
if (!decl)
8585
8682
return nullptr ;
8683
+
8586
8684
// Category decls with same name can be merged and using canonical decl always
8587
8685
// leads to the first category of the given name. We'd like to keep these
8588
8686
// categories separated.
0 commit comments