Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -610,6 +610,26 @@ return StdNamespace; } +// Determine if this is a constrained friend that meets the requirements to be a +// different scope, according to [temp.friend]p9. +static bool IsDifferentlyMangledConstrainedFriend(const Decl *D) { + if (const auto *FTD = dyn_cast(D)) + return IsDifferentlyMangledConstrainedFriend(FTD->getTemplatedDecl()); + + if (D->getFriendObjectKind() == Decl::FOK_None) + return false; + + const FunctionDecl *FD = dyn_cast(D); + + if (!FD) + return false; + + if (FD->getPrimaryTemplate()) + return FD->FriendConstraintRefersToEnclosingTemplate(); + + return FD->getTrailingRequiresClause(); +} + /// Retrieve the declaration context that should be used when mangling the given /// declaration. const DeclContext * @@ -659,6 +679,11 @@ if (FD->isExternC()) return getASTContext().getTranslationUnitDecl(); + // If these are mangled differently because they are constrained friends, + // mangle it in its lexical context. + if (IsDifferentlyMangledConstrainedFriend(D)) + return D->getLexicalDeclContext(); + return DC->getRedeclContext(); } @@ -1694,13 +1719,22 @@ Out << II->getLength() << II->getName(); } +// See if the 'F' between the prefix of a nested name or nested template is +// necessary. That is, is this a friend with a constraint that refers to an +// enclosing template. +static void mangleConstrainedFriendness(llvm::raw_ostream &Out, GlobalDecl GD) { + if (IsDifferentlyMangledConstrainedFriend(GD.getDecl())) + Out << 'F'; +} + void CXXNameMangler::mangleNestedName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags, bool NoFunction) { const NamedDecl *ND = cast(GD.getDecl()); // - // ::= N [] [] E + // ::= N [] [] [F] + // E // ::= N [] [] // E @@ -1721,6 +1755,7 @@ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs); } else { manglePrefix(DC, NoFunction); + mangleConstrainedFriendness(Out, GD); mangleUnqualifiedName(GD, DC, AdditionalAbiTags); } @@ -2139,7 +2174,7 @@ void CXXNameMangler::mangleTemplatePrefix(GlobalDecl GD, bool NoFunction) { const TemplateDecl *ND = cast(GD.getDecl()); - // ::=