@@ -416,7 +416,7 @@ void Decl::attachParsedAttrs(DeclAttributes attrs) {
416
416
for (auto *attr : attrs.getAttributes <DerivativeAttr>())
417
417
attr->setOriginalDeclaration (this );
418
418
for (auto attr : attrs.getAttributes <ABIAttr, /* AllowInvalid=*/ true >())
419
- this -> getASTContext (). recordABIAttr (attr, this );
419
+ recordABIAttr (attr);
420
420
421
421
getAttrs () = attrs;
422
422
}
@@ -4271,22 +4271,69 @@ void ValueDecl::setRenamedDecl(const AvailableAttr *attr,
4271
4271
std::move (renameDecl));
4272
4272
}
4273
4273
4274
- abi_role_detail::Storage abi_role_detail::computeStorage (Decl *decl ) {
4275
- ASSERT (decl) ;
4274
+ void Decl::recordABIAttr (ABIAttr *attr ) {
4275
+ Decl *owner = this ;
4276
4276
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);
4278
4315
4279
4316
Decl *counterpartDecl = decl;
4280
4317
ABIRole::Value flags = ABIRole::Either;
4281
4318
4282
4319
if (auto attr = decl->getAttrs ().getAttribute <ABIAttr>()) {
4283
4320
flags = ABIRole::ProvidesAPI;
4284
4321
counterpartDecl = attr->abiDecl ;
4285
- } else if (auto inverse = ctx.ABIDeclCounterparts .lookup (decl)) {
4286
- flags = ABIRole::ProvidesABI;
4287
- counterpartDecl = inverse;
4288
4322
}
4289
4323
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
+
4290
4337
// If we did find an `@abi` attribute, resolve PBD pointers to their VarDecl.
4291
4338
if (flags != ABIRole::Either) {
4292
4339
if (auto VD = dyn_cast<VarDecl>(decl))
0 commit comments