@@ -4071,12 +4071,7 @@ void ASTMangler::appendEntity(const ValueDecl *decl) {
4071
4071
}
4072
4072
4073
4073
if (auto expansion = dyn_cast<MacroExpansionDecl>(decl)) {
4074
- appendMacroExpansionContext (
4075
- expansion->getLoc (), expansion->getDeclContext ());
4076
- appendMacroExpansionOperator (
4077
- expansion->getMacroName ().getBaseName ().userFacingName (),
4078
- MacroRole::Declaration,
4079
- expansion->getDiscriminator ());
4074
+ appendMacroExpansion (expansion);
4080
4075
return ;
4081
4076
}
4082
4077
@@ -4516,14 +4511,51 @@ std::string ASTMangler::mangleDistributedThunk(const AbstractFunctionDecl *thunk
4516
4511
return finalize ();
4517
4512
}
4518
4513
4514
+ // / Retrieve the outermost local context, or return NULL if there is no such
4515
+ // / local context.
4516
+ static const DeclContext *getOutermostLocalContext (const DeclContext *dc) {
4517
+ // If the parent has an outermost local context, it's ours as well.
4518
+ if (auto parentDC = dc->getParent ()) {
4519
+ if (auto outermost = getOutermostLocalContext (parentDC))
4520
+ return outermost;
4521
+ }
4522
+
4523
+ return dc->isLocalContext () ? dc : nullptr ;
4524
+ }
4525
+
4526
+ // / Enable a precheck discriminator into the identifier name. These mangled
4527
+ // / names are not ABI and are not stable.
4528
+ static Identifier encodeLocalPrecheckedDiscriminator (
4529
+ ASTContext &ctx, Identifier name, unsigned discriminator) {
4530
+ llvm::SmallString<16 > discriminatedName;
4531
+ {
4532
+ llvm::raw_svector_ostream out (discriminatedName);
4533
+ out << name.str () << " _$l" << discriminator;
4534
+ }
4535
+
4536
+ return ctx.getIdentifier (discriminatedName);
4537
+ }
4538
+
4519
4539
void ASTMangler::appendMacroExpansionContext (
4520
- SourceLoc loc, DeclContext *origDC
4540
+ SourceLoc loc, DeclContext *origDC,
4541
+ const FreestandingMacroExpansion *expansion
4521
4542
) {
4522
4543
origDC = MacroDiscriminatorContext::getInnermostMacroContext (origDC);
4523
4544
BaseEntitySignature nullBase (nullptr );
4524
4545
4525
- if (loc.isInvalid ())
4526
- return appendContext (origDC, nullBase, StringRef ());
4546
+ if (loc.isInvalid ()) {
4547
+ if (auto outermostLocalDC = getOutermostLocalContext (origDC)) {
4548
+ auto innermostNonlocalDC = outermostLocalDC->getParent ();
4549
+ appendContext (innermostNonlocalDC, nullBase, StringRef ());
4550
+ Identifier name = expansion->getMacroName ().getBaseIdentifier ();
4551
+ ASTContext &ctx = origDC->getASTContext ();
4552
+ unsigned discriminator = expansion->getDiscriminator ();
4553
+ name = encodeLocalPrecheckedDiscriminator (ctx, name, discriminator);
4554
+ appendIdentifier (name.str ());
4555
+ } else {
4556
+ return appendContext (origDC, nullBase, StringRef ());
4557
+ }
4558
+ }
4527
4559
4528
4560
SourceManager &sourceMgr = Context.SourceMgr ;
4529
4561
@@ -4622,7 +4654,7 @@ void ASTMangler::appendMacroExpansionContext(
4622
4654
return appendMacroExpansionLoc ();
4623
4655
4624
4656
// Append our own context and discriminator.
4625
- appendMacroExpansionContext (outerExpansionLoc, origDC);
4657
+ appendMacroExpansionContext (outerExpansionLoc, origDC, expansion );
4626
4658
appendMacroExpansionOperator (
4627
4659
baseName.userFacingName (), role, discriminator);
4628
4660
}
@@ -4686,11 +4718,11 @@ static StringRef getPrivateDiscriminatorIfNecessary(
4686
4718
}
4687
4719
}
4688
4720
4689
- std::string
4690
- ASTMangler::mangleMacroExpansion (const FreestandingMacroExpansion *expansion) {
4691
- beginMangling ();
4721
+ void
4722
+ ASTMangler::appendMacroExpansion (const FreestandingMacroExpansion *expansion) {
4692
4723
appendMacroExpansionContext (expansion->getPoundLoc (),
4693
- expansion->getDeclContext ());
4724
+ expansion->getDeclContext (),
4725
+ expansion);
4694
4726
auto privateDiscriminator = getPrivateDiscriminatorIfNecessary (expansion);
4695
4727
if (!privateDiscriminator.empty ()) {
4696
4728
appendIdentifier (privateDiscriminator);
@@ -4700,25 +4732,106 @@ ASTMangler::mangleMacroExpansion(const FreestandingMacroExpansion *expansion) {
4700
4732
expansion->getMacroName ().getBaseName ().userFacingName (),
4701
4733
MacroRole::Declaration,
4702
4734
expansion->getDiscriminator ());
4735
+ }
4736
+
4737
+ std::string
4738
+ ASTMangler::mangleMacroExpansion (const FreestandingMacroExpansion *expansion) {
4739
+ beginMangling ();
4740
+ appendMacroExpansion (expansion);
4703
4741
return finalize ();
4704
4742
}
4705
4743
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
+
4706
4792
std::string ASTMangler::mangleAttachedMacroExpansion (
4707
4793
const Decl *decl, CustomAttr *attr, MacroRole role) {
4708
4794
// FIXME(kavon): using the decl causes a cycle. Is a null base fine?
4709
4795
BaseEntitySignature nullBase (nullptr );
4710
4796
4711
4797
beginMangling ();
4712
4798
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
+
4713
4827
// Append the context and name of the declaration.
4714
4828
// We don't mangle the declaration itself because doing so requires semantic
4715
4829
// information (e.g., its interface type), which introduces cyclic
4716
4830
// dependencies.
4717
4831
const Decl *attachedTo = decl;
4718
- DeclBaseName attachedToName;
4832
+ Identifier attachedToName;
4719
4833
if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
4720
4834
auto storage = accessor->getStorage ();
4721
- appendContextOf (storage, nullBase);
4722
4835
4723
4836
// Introduce an identifier mangling that includes var/subscript, accessor
4724
4837
// kind, and static.
@@ -4744,23 +4857,24 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
4744
4857
attachedToName = decl->getASTContext ().getIdentifier (name);
4745
4858
}
4746
4859
4747
- appendDeclName (storage, attachedToName);
4860
+ appendDeclWithName (storage, attachedToName);
4748
4861
4749
4862
// For member attribute macros, the attribute is attached to the enclosing
4750
4863
// declaration.
4751
4864
if (role == MacroRole::MemberAttribute) {
4752
4865
attachedTo = storage->getDeclContext ()->getAsDecl ();
4753
4866
}
4754
4867
} else if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
4755
- appendContextOf (valueDecl, nullBase);
4756
-
4757
4868
// 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 ()) {
4760
4871
attachedToName =
4761
- decl->getASTContext ().getIdentifier (attachedToName.userFacingName ());
4872
+ decl->getASTContext ().getIdentifier (name.userFacingName ());
4873
+ } else {
4874
+ attachedToName = name.getIdentifier ();
4762
4875
}
4763
- appendDeclName (valueDecl, attachedToName);
4876
+
4877
+ appendDeclWithName (valueDecl, attachedToName);
4764
4878
4765
4879
// For member attribute macros, the attribute is attached to the enclosing
4766
4880
// declaration.
0 commit comments