@@ -486,10 +486,10 @@ void ASTMangler::beginManglingWithAutoDiffOriginalFunction(
486
486
}
487
487
// For imported Clang declarations, use the Clang name in order to match how
488
488
// DifferentiationMangler handles these.
489
- auto clangDecl = getClangDeclForMangling (afd);
490
- if (clangDecl ) {
489
+ auto clangDeclContainer = getClangDeclForMangling (afd);
490
+ if (clangDeclContainer ) {
491
491
beginManglingWithoutPrefix ();
492
- appendOperator (clangDecl ->getName ());
492
+ appendOperator (clangDeclContainer. decl ->getName ());
493
493
return ;
494
494
}
495
495
beginMangling ();
@@ -2167,9 +2167,29 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl,
2167
2167
if (isa<TypeDecl>(decl)) {
2168
2168
if (auto *clangDecl = cast_or_null<clang::NamedDecl>(decl->getClangDecl ())){
2169
2169
bool hasNameForLinkage;
2170
- if (auto *tagDecl = dyn_cast<clang::TagDecl>(clangDecl))
2170
+ if (auto *tagDecl = dyn_cast<clang::TagDecl>(clangDecl)) {
2171
2171
hasNameForLinkage = tagDecl->hasNameForLinkage ();
2172
- else
2172
+ // Clang does not always populate the fields that determine if a tag
2173
+ // decl has a linkage name in the ways we expect. To support differing
2174
+ // definitions of CF_OPTIONS, we check if the tag decls is anonymous and
2175
+ // backed by an unavailable typedef.
2176
+ if (!hasNameForLinkage) {
2177
+ if (auto enumDecl = dyn_cast<clang::EnumDecl>(tagDecl);
2178
+ decl->getASTContext ().LangOpts .EnableCXXInterop &&
2179
+ enumDecl->getDeclName ().isEmpty ()) {
2180
+ if (auto typedefType = dyn_cast<clang::TypedefType>(
2181
+ enumDecl->getIntegerType ().getTypePtr ())) {
2182
+ for (auto *attr :
2183
+ typedefType->getDecl ()
2184
+ ->specific_attrs <clang::AvailabilityAttr>()) {
2185
+ if (attr->getPlatform ()->getName () == " swift" ) {
2186
+ hasNameForLinkage = true ;
2187
+ }
2188
+ }
2189
+ }
2190
+ }
2191
+ }
2192
+ } else
2173
2193
hasNameForLinkage = !clangDecl->getDeclName ().isEmpty ();
2174
2194
if (hasNameForLinkage) {
2175
2195
auto *clangDC = clangDecl->getDeclContext ();
@@ -2506,17 +2526,47 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
2506
2526
appendDeclName (protocol);
2507
2527
}
2508
2528
2509
- const clang::NamedDecl *ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2510
- auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
2529
+ const ASTMangler::ClangDeclForManglingContainer
2530
+ ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2531
+ auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
2511
2532
if (!namedDecl)
2512
2533
return nullptr ;
2513
-
2534
+
2514
2535
// Use an anonymous enum's enclosing typedef for the mangled name, if
2515
2536
// present. This matches C++'s rules for linkage names of tag declarations.
2516
2537
if (namedDecl->getDeclName ().isEmpty ())
2517
- if (auto *tagDecl = dyn_cast<clang::TagDecl>(namedDecl))
2518
- if (auto *typedefDecl = tagDecl->getTypedefNameForAnonDecl ())
2538
+ if (auto *tagDecl = dyn_cast<clang::TagDecl>(namedDecl)) {
2539
+ if (auto enumDecl = dyn_cast<clang::EnumDecl>(tagDecl)) {
2540
+ // CF_OPTION derived types are different in Objective-C vs Objective-C++
2541
+ // due different definitions in the SDK based on if __cplusplus is
2542
+ // defined. The linkage name of these CF_OPTION derived types must be
2543
+ // consistent regardless of if cxx interop is turned on or not,
2544
+ // otherwise modules compiled with cxx interop cannot interoperate with
2545
+ // those compiled without it.
2546
+ if (auto typedefType = dyn_cast<clang::TypedefType>(
2547
+ enumDecl->getIntegerType ().getTypePtr ());
2548
+ vd->getASTContext ().LangOpts .EnableCXXInterop ) {
2549
+ for (auto *attr : typedefType->getDecl ()
2550
+ ->specific_attrs <clang::AvailabilityAttr>()) {
2551
+ if (attr->getPlatform ()->getName () == " swift" ) {
2552
+ // Temporarily emulate the Objective-C definition of CF_OPTION
2553
+ // for mangling, removing the temporary name attached to the
2554
+ // anonymous enum once we are done with the value.
2555
+ const_cast <clang::NamedDecl *>(namedDecl)->setDeclName (
2556
+ typedefType->getDecl ()->getDeclName ());
2557
+ return {namedDecl, [](const clang::NamedDecl *decl) {
2558
+ const_cast <clang::NamedDecl *>(decl)->setDeclName (
2559
+ clang::DeclarationName ());
2560
+ }};
2561
+ }
2562
+ }
2563
+ }
2564
+ }
2565
+
2566
+ if (auto *typedefDecl = tagDecl->getTypedefNameForAnonDecl ()) {
2519
2567
namedDecl = typedefDecl;
2568
+ }
2569
+ }
2520
2570
2521
2571
if (namedDecl->getDeclName ().isEmpty ())
2522
2572
return nullptr ;
@@ -2571,10 +2621,12 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
2571
2621
// have one.
2572
2622
auto tryAppendClangName = [this , decl]() -> bool {
2573
2623
auto *nominal = dyn_cast<NominalTypeDecl>(decl);
2574
- auto namedDecl = getClangDeclForMangling (decl);
2575
- if (!namedDecl )
2624
+ auto namedDeclContainer = getClangDeclForMangling (decl);
2625
+ if (!namedDeclContainer )
2576
2626
return false ;
2577
2627
2628
+ const clang::NamedDecl *namedDecl = namedDeclContainer.decl ;
2629
+
2578
2630
// Mangle ObjC classes using their runtime names.
2579
2631
auto interface = dyn_cast<clang::ObjCInterfaceDecl>(namedDecl);
2580
2632
auto protocol = dyn_cast<clang::ObjCProtocolDecl>(namedDecl);
0 commit comments