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