@@ -461,7 +461,19 @@ class CXXNameMangler {
461461
462462  void  mangleExistingSubstitution (TemplateName name);
463463
464+   struct  Namespaces  {
465+     const  NamespaceDecl *NS;
466+     std::string_view InnerNamespace{};
467+   };
468+ 
469+   auto  specializedClassInNamespace (
470+       std::string_view Name, Namespaces NS,
471+       std::initializer_list<
472+           llvm::function_ref<bool (const  TemplateArgument &)>>);
473+   template  <class ... Args> auto  anyBuiltin (Args... Builtins);
474+ 
464475  bool  mangleStandardSubstitution (const  NamedDecl *ND);
476+   bool  mangleVersionedStandardSubstitution (const  NamedDecl *ND);
465477
466478  void  addSubstitution (const  NamedDecl *ND) {
467479    ND = cast<NamedDecl>(ND->getCanonicalDecl ());
@@ -6319,16 +6331,227 @@ bool CXXNameMangler::isStdCharSpecialization(
63196331  return  true ;
63206332}
63216333
6334+ static  bool  isSpecialization (const  ClassTemplateSpecializationDecl *SD,
6335+                              std::string_view Name,
6336+                              std::initializer_list<llvm::function_ref<bool (const  TemplateArgument&)>> Args) {
6337+   if  (!SD->getIdentifier ()->isStr (Name))
6338+     return  false ;
6339+ 
6340+   if  (SD->getSpecializedTemplate ()->getOwningModuleForLinkage ())
6341+     return  false ;
6342+ 
6343+   const  auto & TemplateArgs = SD->getTemplateArgs ();
6344+   if  (TemplateArgs.size () != Args.size ())
6345+     return  false ;
6346+ 
6347+   return  llvm::all_of (llvm::zip (Args, TemplateArgs.asArray ()), [](auto  Arg) {
6348+     return  std::get<0 >(Arg)(std::get<1 >(Arg));
6349+   });
6350+ }
6351+ 
6352+ auto  CXXNameMangler::specializedClassInNamespace (
6353+     std::string_view Name, Namespaces NS,
6354+     std::initializer_list<llvm::function_ref<bool (const  TemplateArgument &)>>
6355+         Args) {
6356+   return  [=, this ](const  TemplateArgument &Type) -> bool  {
6357+     const  auto * RT = Type.getAsType ()->getAs <RecordType>();
6358+     if  (!RT)
6359+       return  false ;
6360+     const  auto * SD = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl ());
6361+     if  (!SD || !SD->getIdentifier ()->isStr (Name))
6362+       return  false ;
6363+ 
6364+     const  auto  *DC = Context.getEffectiveDeclContext (SD);
6365+     if  (!DC->isNamespace ())
6366+       return  false ;
6367+     const  auto  *ND = cast<NamespaceDecl>(DC);
6368+     if  (NS.InnerNamespace  != " " 
6369+       if  (ND->getIdentifier ()->getName () != StringRef (NS.InnerNamespace ))
6370+         return  false ;
6371+       if  (!ND->getParent ()->isNamespace ())
6372+         return  false ;
6373+       ND = cast<NamespaceDecl>(ND->getParent ());
6374+     }
6375+     if  (ND->getOriginalNamespace () != NS.NS ->getOriginalNamespace ())
6376+       return  false ;
6377+     return  isSpecialization (SD, Name, Args);
6378+   };
6379+ }
6380+ 
6381+ template  <class ... Args>
6382+ auto  CXXNameMangler::anyBuiltin (Args... Builtins) {
6383+   return  [=](const  TemplateArgument &TA) {
6384+     auto  QT = TA.getAsType ();
6385+     return  (QT->isSpecificBuiltinType (Builtins) || ...);
6386+   };
6387+ }
6388+ 
6389+ static  bool  isVersionedStdNamespace (const  DeclContext *DC) {
6390+   if  (!DC->getEnclosingNamespaceContext ()->isStdNamespace ())
6391+     return  false ;
6392+   if  (!DC->isNamespace ())
6393+     return  false ;
6394+   auto  Name = cast<NamespaceDecl>(DC)->getIdentifier ()->getName ();
6395+   if  (!Name.starts_with (" __" 
6396+     return  false ;
6397+   Name = Name.drop_front (2 );
6398+   auto  NoVersion = Name.drop_while ([](char  c) { return  std::isdigit (c); });
6399+   if  (NoVersion.size () == Name.size ())
6400+     return  false ;
6401+   return  NoVersion.size () == 1  && std::islower (NoVersion[0 ]);
6402+ }
6403+ 
6404+ bool  CXXNameMangler::mangleVersionedStandardSubstitution (const  NamedDecl *ND) {
6405+   if  (const  NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
6406+     if  (isVersionedStdNamespace (NS)) {
6407+       auto  Name = NS->getName ().drop_front (2 );
6408+       Out << " S" " T" 
6409+       return  true ;
6410+     }
6411+   }
6412+ 
6413+   if  (!isVersionedStdNamespace (ND->getDeclContext ()))
6414+     return  false ;
6415+ 
6416+   auto  Version = cast<NamespaceDecl>(ND->getDeclContext ())
6417+                      ->getIdentifier ()
6418+                      ->getName ()
6419+                      .drop_front (2 );
6420+ 
6421+   if  (const  ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
6422+     const  auto  *EnclosingNamespace = Context.getEffectiveDeclContext (TD);
6423+     if  (isVersionedStdNamespace (EnclosingNamespace)) {
6424+       if  (TD->getOwningModuleForLinkage ())
6425+         return  false ;
6426+ 
6427+       static  std::pair<std::string_view, std::string_view> replacements[] {
6428+         {" allocator" " aL" 
6429+         {" atomic" " aT" 
6430+         {" expected" " eX" 
6431+         {" vector" " vE" 
6432+         {" copyable_function" " fC" 
6433+         {" function" " fF" 
6434+         {" move_only_function" " fM" 
6435+         {" function_ref" " fF" 
6436+         {" optional" " oP" 
6437+         {" shared_ptr" " sP" 
6438+         {" tuple" " tU" 
6439+         {" variant" " vA" 
6440+       };
6441+ 
6442+       for  (auto  [name, substitution] : replacements) {
6443+         if  (TD->getIdentifier ()->isStr (name)) {
6444+           Out << " S" 
6445+           return  true ;
6446+         }
6447+       }
6448+     }
6449+   }
6450+ 
6451+   if  (const  ClassTemplateSpecializationDecl *SD =
6452+           dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
6453+     const  auto  *EnclosingNamespace = SD->getEnclosingNamespaceContext ();
6454+     if  (isVersionedStdNamespace (EnclosingNamespace)) {
6455+       const  auto  *NS = cast<NamespaceDecl>(EnclosingNamespace);
6456+ 
6457+       { //  char strings
6458+         auto  Char = anyBuiltin (BuiltinType::Char_S, BuiltinType::Char_U);
6459+         auto  CharTraitsChar =
6460+             specializedClassInNamespace (" char_traits" 
6461+         auto  AllocatorChar =
6462+             specializedClassInNamespace (" allocator" 
6463+         auto  PolymorphicAllocatorChar = specializedClassInNamespace (
6464+             " polymorphic_allocator" " pmr" 
6465+ 
6466+         if  (isSpecialization (SD, " basic_string" 
6467+                             {Char, CharTraitsChar, AllocatorChar})) {
6468+           Out << " S" " S" 
6469+           return  true ;
6470+         }
6471+         if  (isSpecialization (SD, " basic_string" 
6472+                             {Char, CharTraitsChar, PolymorphicAllocatorChar})) {
6473+           Out << " S" " sA" 
6474+           return  true ;
6475+         }
6476+         if  (isSpecialization (SD, " basic_string_view" 
6477+           Out << " S" " sB" 
6478+           return  true ;
6479+         }
6480+         if  (isSpecialization (SD, " basic_istream" 
6481+           Out << " S" " bI" 
6482+           return  true ;
6483+         }
6484+         if  (isSpecialization (SD, " basic_ostream" 
6485+           Out << " S" " bO" 
6486+           return  true ;
6487+         }
6488+         if  (isSpecialization (SD, " basic_iostream" 
6489+           Out << " S" " bS" 
6490+           return  true ;
6491+         }
6492+       }
6493+ 
6494+       { //  wchar strings
6495+         auto  WChar = anyBuiltin (BuiltinType::WChar_S, BuiltinType::WChar_U);
6496+         auto  CharTraitsWChar =
6497+             specializedClassInNamespace (" char_traits" 
6498+         auto  AllocatorWChar =
6499+             specializedClassInNamespace (" allocator" 
6500+         auto  PolymorphicAllocatorWChar = specializedClassInNamespace (
6501+             " polymorphic_allocator" " pmr" 
6502+ 
6503+         if  (isSpecialization (SD, " basic_string" 
6504+                             {WChar, CharTraitsWChar, AllocatorWChar})) {
6505+           Out << " S" " sC" 
6506+           return  true ;
6507+         }
6508+         if  (isSpecialization (
6509+                 SD, " basic_string" 
6510+                 {WChar, CharTraitsWChar, PolymorphicAllocatorWChar})) {
6511+           Out << " S" " sD" 
6512+           return  true ;
6513+         }
6514+         if  (isSpecialization (SD, " basic_string_view" 
6515+           Out << " S" " sE" 
6516+           return  true ;
6517+         }
6518+       }
6519+ 
6520+       { //  complex
6521+         if  (isSpecialization (SD, " complex" anyBuiltin (BuiltinType::Float)})) {
6522+           Out << " S" " cF" 
6523+           return  true ;
6524+         }
6525+         if  (isSpecialization (SD, " complex" anyBuiltin (BuiltinType::Double)})) {
6526+           Out << " S" " cD" 
6527+           return  true ;
6528+         }
6529+         if  (isSpecialization (SD, " complex" anyBuiltin (BuiltinType::LongDouble)})) {
6530+           Out << " S" " cL" 
6531+           return  true ;
6532+         }
6533+       }
6534+     }
6535+   }
6536+ 
6537+   return  false ;
6538+ }
6539+ 
63226540bool  CXXNameMangler::mangleStandardSubstitution (const  NamedDecl *ND) {
63236541  //  <substitution> ::= St # ::std::
63246542  if  (const  NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
63256543    if  (isStd (NS)) {
63266544      Out << " St" 
63276545      return  true ;
63286546    }
6547+     if  (isVersionedStdNamespace (NS))
6548+       return  mangleVersionedStandardSubstitution (ND);
63296549    return  false ;
63306550  }
63316551
6552+   if  (ND->isInStdNamespace ())
6553+     return  mangleVersionedStandardSubstitution (ND);
6554+ 
63326555  if  (const  ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
63336556    if  (!isStdNamespace (Context.getEffectiveDeclContext (TD)))
63346557      return  false ;
@@ -6352,7 +6575,11 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
63526575
63536576  if  (const  ClassTemplateSpecializationDecl *SD =
63546577        dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
6355-     if  (!isStdNamespace (Context.getEffectiveDeclContext (SD)))
6578+     const  DeclContext *DC = Context.getEffectiveDeclContext (ND);
6579+     if  (isVersionedStdNamespace (DC))
6580+       return  mangleVersionedStandardSubstitution (ND);
6581+ 
6582+     if  (!isStdNamespace (DC))
63566583      return  false ;
63576584
63586585    if  (SD->getSpecializedTemplate ()->getOwningModuleForLinkage ())
0 commit comments