@@ -4070,12 +4070,7 @@ void ASTMangler::appendEntity(const ValueDecl *decl) {
40704070 }
40714071
40724072 if (auto expansion = dyn_cast<MacroExpansionDecl>(decl)) {
4073- appendMacroExpansionContext (
4074- expansion->getLoc (), expansion->getDeclContext ());
4075- appendMacroExpansionOperator (
4076- expansion->getMacroName ().getBaseName ().userFacingName (),
4077- MacroRole::Declaration,
4078- expansion->getDiscriminator ());
4073+ appendMacroExpansion (expansion);
40794074 return ;
40804075 }
40814076
@@ -4515,14 +4510,51 @@ std::string ASTMangler::mangleDistributedThunk(const AbstractFunctionDecl *thunk
45154510 return finalize ();
45164511}
45174512
4513+ // / Retrieve the outermost local context, or return NULL if there is no such
4514+ // / local context.
4515+ static const DeclContext *getOutermostLocalContext (const DeclContext *dc) {
4516+ // If the parent has an outermost local context, it's ours as well.
4517+ if (auto parentDC = dc->getParent ()) {
4518+ if (auto outermost = getOutermostLocalContext (parentDC))
4519+ return outermost;
4520+ }
4521+
4522+ return dc->isLocalContext () ? dc : nullptr ;
4523+ }
4524+
4525+ // / Enable a precheck discriminator into the identifier name. These mangled
4526+ // / names are not ABI and are not stable.
4527+ static Identifier encodeLocalPrecheckedDiscriminator (
4528+ ASTContext &ctx, Identifier name, unsigned discriminator) {
4529+ llvm::SmallString<16 > discriminatedName;
4530+ {
4531+ llvm::raw_svector_ostream out (discriminatedName);
4532+ out << name.str () << " _$l" << discriminator;
4533+ }
4534+
4535+ return ctx.getIdentifier (discriminatedName);
4536+ }
4537+
45184538void ASTMangler::appendMacroExpansionContext (
4519- SourceLoc loc, DeclContext *origDC
4539+ SourceLoc loc, DeclContext *origDC,
4540+ const FreestandingMacroExpansion *expansion
45204541) {
45214542 origDC = MacroDiscriminatorContext::getInnermostMacroContext (origDC);
45224543 BaseEntitySignature nullBase (nullptr );
45234544
4524- if (loc.isInvalid ())
4525- return appendContext (origDC, nullBase, StringRef ());
4545+ if (loc.isInvalid ()) {
4546+ if (auto outermostLocalDC = getOutermostLocalContext (origDC)) {
4547+ auto innermostNonlocalDC = outermostLocalDC->getParent ();
4548+ appendContext (innermostNonlocalDC, nullBase, StringRef ());
4549+ Identifier name = expansion->getMacroName ().getBaseIdentifier ();
4550+ ASTContext &ctx = origDC->getASTContext ();
4551+ unsigned discriminator = expansion->getDiscriminator ();
4552+ name = encodeLocalPrecheckedDiscriminator (ctx, name, discriminator);
4553+ appendIdentifier (name.str ());
4554+ } else {
4555+ return appendContext (origDC, nullBase, StringRef ());
4556+ }
4557+ }
45264558
45274559 ASTContext &ctx = origDC->getASTContext ();
45284560 SourceManager &sourceMgr = ctx.SourceMgr ;
@@ -4622,7 +4654,7 @@ void ASTMangler::appendMacroExpansionContext(
46224654 return appendMacroExpansionLoc ();
46234655
46244656 // Append our own context and discriminator.
4625- appendMacroExpansionContext (outerExpansionLoc, origDC);
4657+ appendMacroExpansionContext (outerExpansionLoc, origDC, expansion );
46264658 appendMacroExpansionOperator (
46274659 baseName.userFacingName (), role, discriminator);
46284660}
@@ -4686,11 +4718,11 @@ static StringRef getPrivateDiscriminatorIfNecessary(
46864718 }
46874719}
46884720
4689- std::string
4690- ASTMangler::mangleMacroExpansion (const FreestandingMacroExpansion *expansion) {
4691- beginMangling ();
4721+ void
4722+ ASTMangler::appendMacroExpansion (const FreestandingMacroExpansion *expansion) {
46924723 appendMacroExpansionContext (expansion->getPoundLoc (),
4693- expansion->getDeclContext ());
4724+ expansion->getDeclContext (),
4725+ expansion);
46944726 auto privateDiscriminator = getPrivateDiscriminatorIfNecessary (expansion);
46954727 if (!privateDiscriminator.empty ()) {
46964728 appendIdentifier (privateDiscriminator);
@@ -4700,25 +4732,106 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
47004732 expansion->getMacroName ().getBaseName ().userFacingName (),
47014733 MacroRole::Declaration,
47024734 expansion->getDiscriminator ());
4735+ }
4736+
4737+ std::string
4738+ ASTMangler::mangleMacroExpansion (const FreestandingMacroExpansion *expansion) {
4739+ beginMangling ();
4740+ appendMacroExpansion (expansion);
47034741 return finalize ();
47044742}
47054743
4744+ namespace {
4745+
4746+ // / Stores either a declaration or its enclosing context, for use in mangling
4747+ // / of macro expansion contexts.
4748+ struct DeclOrEnclosingContext : llvm::PointerUnion<const Decl *, const DeclContext *> {
4749+ using PointerUnion::PointerUnion;
4750+
4751+ const DeclContext *getEnclosingContext () const {
4752+ if (auto decl = dyn_cast<const Decl *>()) {
4753+ return decl->getDeclContext ();
4754+ }
4755+
4756+ return get<const DeclContext *>();
4757+ }
4758+ };
4759+
4760+ }
4761+
4762+ // / Given a declaration, find the declaration or enclosing context that is
4763+ // / the innermost context that is not a local context, along with a
4764+ // / discriminator that identifies this given specific declaration (along
4765+ // / with its `name`) within that enclosing context. This is used to
4766+ // / mangle entities within local contexts before they are fully type-checked,
4767+ // / as is needed for macro expansions.
4768+ static std::pair<DeclOrEnclosingContext, std::optional<unsigned >>
4769+ getPrecheckedLocalContextDiscriminator (const Decl *decl, Identifier name) {
4770+ auto outermostLocal = getOutermostLocalContext (decl->getDeclContext ());
4771+ if (!outermostLocal) {
4772+ return std::make_pair (
4773+ DeclOrEnclosingContext (decl),
4774+ std::optional<unsigned >()
4775+ );
4776+ }
4777+ DeclOrEnclosingContext declOrEnclosingContext;
4778+ if (decl->getDeclContext () == outermostLocal)
4779+ declOrEnclosingContext = decl;
4780+ else if (const Decl *fromDecl = outermostLocal->getAsDecl ())
4781+ declOrEnclosingContext = fromDecl;
4782+ else
4783+ declOrEnclosingContext = outermostLocal->getParent ();
4784+
4785+ DeclContext *enclosingDC = const_cast <DeclContext *>(
4786+ declOrEnclosingContext.getEnclosingContext ());
4787+ ASTContext &ctx = enclosingDC->getASTContext ();
4788+ auto discriminator = ctx.getNextMacroDiscriminator (enclosingDC, name);
4789+ return std::make_pair (declOrEnclosingContext, discriminator);
4790+ }
4791+
47064792std::string ASTMangler::mangleAttachedMacroExpansion (
47074793 const Decl *decl, CustomAttr *attr, MacroRole role) {
47084794 // FIXME(kavon): using the decl causes a cycle. Is a null base fine?
47094795 BaseEntitySignature nullBase (nullptr );
47104796
47114797 beginMangling ();
47124798
4799+ auto appendDeclWithName = [&](const Decl *decl, Identifier name) {
4800+ // Mangle the context.
4801+ auto precheckedMangleContext =
4802+ getPrecheckedLocalContextDiscriminator (decl, name);
4803+ if (auto mangleDecl = dyn_cast_or_null<ValueDecl>(
4804+ precheckedMangleContext.first .dyn_cast <const Decl *>())) {
4805+ appendContextOf (mangleDecl, nullBase);
4806+ } else {
4807+ appendContext (
4808+ precheckedMangleContext.first .getEnclosingContext (), nullBase,
4809+ StringRef ());
4810+ }
4811+
4812+ // If we needed a local discriminator, stuff that into the name itself.
4813+ // This is hack, but these names aren't stable anyway.
4814+ if (auto discriminator = precheckedMangleContext.second ) {
4815+ name = encodeLocalPrecheckedDiscriminator (
4816+ decl->getASTContext (), name, *discriminator);
4817+ }
4818+
4819+ if (auto valueDecl = dyn_cast<ValueDecl>(decl))
4820+ appendDeclName (valueDecl, name);
4821+ else if (!name.empty ())
4822+ appendIdentifier (name.str ());
4823+ else
4824+ appendIdentifier (" _" );
4825+ };
4826+
47134827 // Append the context and name of the declaration.
47144828 // We don't mangle the declaration itself because doing so requires semantic
47154829 // information (e.g., its interface type), which introduces cyclic
47164830 // dependencies.
47174831 const Decl *attachedTo = decl;
4718- DeclBaseName attachedToName;
4832+ Identifier attachedToName;
47194833 if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
47204834 auto storage = accessor->getStorage ();
4721- appendContextOf (storage, nullBase);
47224835
47234836 // Introduce an identifier mangling that includes var/subscript, accessor
47244837 // kind, and static.
@@ -4744,23 +4857,24 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
47444857 attachedToName = decl->getASTContext ().getIdentifier (name);
47454858 }
47464859
4747- appendDeclName (storage, attachedToName);
4860+ appendDeclWithName (storage, attachedToName);
47484861
47494862 // For member attribute macros, the attribute is attached to the enclosing
47504863 // declaration.
47514864 if (role == MacroRole::MemberAttribute) {
47524865 attachedTo = storage->getDeclContext ()->getAsDecl ();
47534866 }
47544867 } else if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
4755- appendContextOf (valueDecl, nullBase);
4756-
47574868 // Mangle the name, replacing special names with their user-facing names.
4758- attachedToName = valueDecl->getName ().getBaseName ();
4759- if (attachedToName .isSpecial ()) {
4869+ auto name = valueDecl->getName ().getBaseName ();
4870+ if (name .isSpecial ()) {
47604871 attachedToName =
4761- decl->getASTContext ().getIdentifier (attachedToName.userFacingName ());
4872+ decl->getASTContext ().getIdentifier (name.userFacingName ());
4873+ } else {
4874+ attachedToName = name.getIdentifier ();
47624875 }
4763- appendDeclName (valueDecl, attachedToName);
4876+
4877+ appendDeclWithName (valueDecl, attachedToName);
47644878
47654879 // For member attribute macros, the attribute is attached to the enclosing
47664880 // declaration.
0 commit comments