@@ -416,7 +416,7 @@ void Decl::attachParsedAttrs(DeclAttributes attrs) {
416416 for (auto *attr : attrs.getAttributes <DerivativeAttr>())
417417 attr->setOriginalDeclaration (this );
418418 for (auto attr : attrs.getAttributes <ABIAttr, /* AllowInvalid=*/ true >())
419- this -> getASTContext (). recordABIAttr (attr, this );
419+ recordABIAttr (attr);
420420
421421 getAttrs () = attrs;
422422}
@@ -4271,22 +4271,69 @@ void ValueDecl::setRenamedDecl(const AvailableAttr *attr,
42714271 std::move (renameDecl));
42724272}
42734273
4274- abi_role_detail::Storage abi_role_detail::computeStorage (Decl *decl ) {
4275- ASSERT (decl) ;
4274+ void Decl::recordABIAttr (ABIAttr *attr ) {
4275+ Decl *owner = this ;
42764276
4277- auto &ctx = decl->getASTContext ();
4277+ // The ABIAttr on a VarDecl ought to point to its PBD.
4278+ if (auto VD = dyn_cast<VarDecl>(owner)) {
4279+ if (auto PBD = VD->getParentPatternBinding ()) {
4280+ owner = PBD;
4281+ }
4282+ }
4283+
4284+ auto record = [&](Decl *decl) {
4285+ auto &evaluator = owner->getASTContext ().evaluator ;
4286+ DeclABIRoleInfoRequest (decl).recordABIOnly (evaluator, owner);
4287+ };
4288+
4289+ if (auto abiPBD = dyn_cast<PatternBindingDecl>(attr->abiDecl )) {
4290+ // Add to *every* VarDecl in the ABI PBD, even ones that don't properly
4291+ // match anything in the API PBD.
4292+ for (auto i : range (abiPBD->getNumPatternEntries ())) {
4293+ abiPBD->getPattern (i)->forEachVariable (record);
4294+ }
4295+ return ;
4296+ }
4297+
4298+ record (attr->abiDecl );
4299+ }
4300+
4301+ void DeclABIRoleInfoRequest::recordABIOnly (Evaluator &evaluator,
4302+ Decl *counterpart) {
4303+ if (evaluator.hasCachedResult (*this ))
4304+ return ;
4305+ DeclABIRoleInfoResult result{counterpart, ABIRole::ProvidesABI};
4306+ evaluator.cacheOutput (*this , std::move (result));
4307+ }
4308+
4309+ DeclABIRoleInfoResult
4310+ DeclABIRoleInfoRequest::evaluate (Evaluator &evaluator, Decl *decl) const {
4311+ // NOTE: ABI decl -> API decl is manually cached through `recordABIOnly()`,
4312+ // so this code does not have to handle that case.
4313+
4314+ ASSERT (decl);
42784315
42794316 Decl *counterpartDecl = decl;
42804317 ABIRole::Value flags = ABIRole::Either;
42814318
42824319 if (auto attr = decl->getAttrs ().getAttribute <ABIAttr>()) {
42834320 flags = ABIRole::ProvidesAPI;
42844321 counterpartDecl = attr->abiDecl ;
4285- } else if (auto inverse = ctx.ABIDeclCounterparts .lookup (decl)) {
4286- flags = ABIRole::ProvidesABI;
4287- counterpartDecl = inverse;
42884322 }
42894323
4324+ return DeclABIRoleInfoResult (counterpartDecl, (uint8_t )flags);
4325+ }
4326+
4327+ abi_role_detail::Storage abi_role_detail::computeStorage (Decl *decl) {
4328+ ASSERT (decl);
4329+
4330+ auto &ctx = decl->getASTContext ();
4331+
4332+ auto result = evaluateOrDefault (ctx.evaluator , DeclABIRoleInfoRequest{decl},
4333+ { decl, ABIRole::Either });
4334+ Decl *counterpartDecl = result.storage .getPointer ();
4335+ auto flags = (ABIRole::Value)result.storage .getInt ();
4336+
42904337 // If we did find an `@abi` attribute, resolve PBD pointers to their VarDecl.
42914338 if (flags != ABIRole::Either) {
42924339 if (auto VD = dyn_cast<VarDecl>(decl))
0 commit comments