@@ -484,12 +484,19 @@ void ASTMangler::beginManglingWithAutoDiffOriginalFunction(
484484 appendOperator (attr->Name );
485485 return ;
486486 }
487+
488+ auto beginManglingClangDecl = [&](const clang::NamedDecl *decl) {
489+ beginManglingWithoutPrefix ();
490+ appendOperator (decl->getName ());
491+ };
492+
487493 // For imported Clang declarations, use the Clang name in order to match how
488494 // DifferentiationMangler handles these.
489- auto clangDecl = getClangDeclForMangling (afd);
490- if (clangDecl) {
491- beginManglingWithoutPrefix ();
492- appendOperator (clangDecl->getName ());
495+ if (auto clangDecl = getClangDeclForMangling (afd)) {
496+ beginManglingClangDecl (clangDecl);
497+ return ;
498+ } else if (auto typedefType = getTypeDefForCXXCFOptionsDefinition (afd)) {
499+ beginManglingClangDecl (typedefType->getDecl ());
493500 return ;
494501 }
495502 beginMangling ();
@@ -2170,7 +2177,13 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl,
21702177 if (auto *clangDecl = cast_or_null<clang::NamedDecl>(decl->getClangDecl ())){
21712178 bool hasNameForLinkage;
21722179 if (auto *tagDecl = dyn_cast<clang::TagDecl>(clangDecl))
2173- hasNameForLinkage = tagDecl->hasNameForLinkage ();
2180+ // Clang does not always populate the fields that determine if a tag
2181+ // decl has a linkage name. This is particularly the case for the
2182+ // C++ definition of CF_OPTIONS in the sdk. However, we use the
2183+ // name of the backing typedef as a linkage name, despite
2184+ // the enum itself not having one.
2185+ hasNameForLinkage =
2186+ tagDecl->hasNameForLinkage () || isCXXCFOptionsDefinition (decl);
21742187 else
21752188 hasNameForLinkage = !clangDecl->getDeclName ().isEmpty ();
21762189 if (hasNameForLinkage) {
@@ -2510,11 +2523,26 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
25102523 appendDeclName (protocol);
25112524}
25122525
2513- const clang::NamedDecl *ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2514- auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
2526+ bool ASTMangler::isCXXCFOptionsDefinition (const ValueDecl *decl) {
2527+ return getTypeDefForCXXCFOptionsDefinition (decl);
2528+ }
2529+
2530+ const clang::TypedefType *
2531+ ASTMangler::getTypeDefForCXXCFOptionsDefinition (const ValueDecl *decl) {
2532+ const clang::Decl *clangDecl = decl->getClangDecl ();
2533+ if (!clangDecl)
2534+ return nullptr ;
2535+
2536+ const auto &clangModuleLoader = decl->getASTContext ().getClangModuleLoader ();
2537+ return clangModuleLoader->getTypeDefForCXXCFOptionsDefinition (clangDecl);
2538+ }
2539+
2540+ const clang::NamedDecl *
2541+ ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2542+ auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
25152543 if (!namedDecl)
25162544 return nullptr ;
2517-
2545+
25182546 // Use an anonymous enum's enclosing typedef for the mangled name, if
25192547 // present. This matches C++'s rules for linkage names of tag declarations.
25202548 if (namedDecl->getDeclName ().isEmpty ())
@@ -2576,8 +2604,20 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
25762604 auto tryAppendClangName = [this , decl]() -> bool {
25772605 auto *nominal = dyn_cast<NominalTypeDecl>(decl);
25782606 auto namedDecl = getClangDeclForMangling (decl);
2579- if (!namedDecl)
2607+ if (!namedDecl) {
2608+ if (auto typedefType = getTypeDefForCXXCFOptionsDefinition (decl)) {
2609+ // To make sure the C++ definition of CF_OPTIONS mangles the
2610+ // same way as the Objective-C definition, we mangle using the
2611+ // name of the backing typedef, but pretend as if it was an enum.
2612+ // See CFAvailability.h to understand how the definitions differ
2613+ // in C++ and Objective-C
2614+ appendIdentifier (typedefType->getDecl ()->getName ());
2615+ appendOperator (" V" );
2616+ return true ;
2617+ }
2618+
25802619 return false ;
2620+ }
25812621
25822622 // Mangle ObjC classes using their runtime names.
25832623 auto interface = dyn_cast<clang::ObjCInterfaceDecl>(namedDecl);
0 commit comments