@@ -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 ();
@@ -2168,7 +2175,13 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl,
21682175 if (auto *clangDecl = cast_or_null<clang::NamedDecl>(decl->getClangDecl ())){
21692176 bool hasNameForLinkage;
21702177 if (auto *tagDecl = dyn_cast<clang::TagDecl>(clangDecl))
2171- hasNameForLinkage = tagDecl->hasNameForLinkage ();
2178+ // Clang does not always populate the fields that determine if a tag
2179+ // decl has a linkage name. This is particularly the case for the
2180+ // C++ definition of CF_OPTIONS in the sdk. However, we use the
2181+ // name of the backing typedef as a linkage name, despite
2182+ // the enum itself not having one.
2183+ hasNameForLinkage =
2184+ tagDecl->hasNameForLinkage () || isCXXCFOptionsDefinition (decl);
21722185 else
21732186 hasNameForLinkage = !clangDecl->getDeclName ().isEmpty ();
21742187 if (hasNameForLinkage) {
@@ -2508,11 +2521,26 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
25082521 appendDeclName (protocol);
25092522}
25102523
2511- const clang::NamedDecl *ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2512- auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
2524+ bool ASTMangler::isCXXCFOptionsDefinition (const ValueDecl *decl) {
2525+ return getTypeDefForCXXCFOptionsDefinition (decl);
2526+ }
2527+
2528+ const clang::TypedefType *
2529+ ASTMangler::getTypeDefForCXXCFOptionsDefinition (const ValueDecl *decl) {
2530+ const clang::Decl *clangDecl = decl->getClangDecl ();
2531+ if (!clangDecl)
2532+ return nullptr ;
2533+
2534+ const auto &clangModuleLoader = decl->getASTContext ().getClangModuleLoader ();
2535+ return clangModuleLoader->getTypeDefForCXXCFOptionsDefinition (clangDecl);
2536+ }
2537+
2538+ const clang::NamedDecl *
2539+ ASTMangler::getClangDeclForMangling (const ValueDecl *vd) {
2540+ auto namedDecl = dyn_cast_or_null<clang::NamedDecl>(vd->getClangDecl ());
25132541 if (!namedDecl)
25142542 return nullptr ;
2515-
2543+
25162544 // Use an anonymous enum's enclosing typedef for the mangled name, if
25172545 // present. This matches C++'s rules for linkage names of tag declarations.
25182546 if (namedDecl->getDeclName ().isEmpty ())
@@ -2574,8 +2602,20 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
25742602 auto tryAppendClangName = [this , decl]() -> bool {
25752603 auto *nominal = dyn_cast<NominalTypeDecl>(decl);
25762604 auto namedDecl = getClangDeclForMangling (decl);
2577- if (!namedDecl)
2605+ if (!namedDecl) {
2606+ if (auto typedefType = getTypeDefForCXXCFOptionsDefinition (decl)) {
2607+ // To make sure the C++ definition of CF_OPTIONS mangles the
2608+ // same way as the Objective-C definition, we mangle using the
2609+ // name of the backing typedef, but pretend as if it was an enum.
2610+ // See CFAvailability.h to understand how the definitions differ
2611+ // in C++ and Objective-C
2612+ appendIdentifier (typedefType->getDecl ()->getName ());
2613+ appendOperator (" V" );
2614+ return true ;
2615+ }
2616+
25782617 return false ;
2618+ }
25792619
25802620 // Mangle ObjC classes using their runtime names.
25812621 auto interface = dyn_cast<clang::ObjCInterfaceDecl>(namedDecl);
0 commit comments