@@ -195,68 +195,10 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
195
195
IGNORED_ATTR(Unsafe)
196
196
#undef IGNORED_ATTR
197
197
198
- private:
199
- static unsigned getABIArity (AbstractFunctionDecl *afd) {
200
- unsigned arity = afd->getParameters ()->size ();
201
- arity += afd->getGenericSignature ().getGenericParams ().size ();
202
- if (afd->hasImplicitSelfDecl ())
203
- arity += 1 ;
204
- return arity;
205
- }
206
-
207
- void checkABIAttrPBD (PatternBindingDecl *APBD, VarDecl *VD) {
208
- auto PBD = VD->getParentPatternBinding ();
209
-
210
- // To make sure we only diagnose this stuff once, check that VD is the first
211
- // anchoring variable in the PBD.
212
- bool isFirstAnchor = false ;
213
- for (auto i : range (PBD->getNumPatternEntries ())) {
214
- auto anchorVD = PBD->getAnchoringVarDecl (i);
215
- if (anchorVD) {
216
- isFirstAnchor = (anchorVD == VD);
217
- break ;
218
- }
219
- }
220
-
221
- if (!isFirstAnchor)
222
- return ;
223
-
224
- // Check that the PBDs have the same number of patterns.
225
- if (PBD->getNumPatternEntries () < APBD->getNumPatternEntries ()) {
226
- diagnose (APBD->getPattern (PBD->getNumPatternEntries ())->getLoc (),
227
- diag::attr_abi_mismatched_pbd_size, /* abiHasExtra=*/ false );
228
- return ;
229
- }
230
- if (PBD->getNumPatternEntries () > APBD->getNumPatternEntries ()) {
231
- diagnose (PBD->getPattern (APBD->getNumPatternEntries ())->getLoc (),
232
- diag::attr_abi_mismatched_pbd_size, /* abiHasExtra=*/ true );
233
- return ;
234
- }
235
-
236
- // Check that each pattern has the same number of variables.
237
- for (auto i : range (PBD->getNumPatternEntries ())) {
238
- SmallVector<VarDecl *, 8 > VDs;
239
- SmallVector<VarDecl *, 8 > AVDs;
240
-
241
- PBD->getPattern (i)->collectVariables (VDs);
242
- APBD->getPattern (i)->collectVariables (AVDs);
243
-
244
- if (VDs.size () < AVDs.size ()) {
245
- for (auto AVD : drop_begin (AVDs, VDs.size ())) {
246
- AVD->diagnose (diag::attr_abi_mismatched_var,
247
- AVD, /* isABI=*/ true );
248
- }
249
- }
250
- else if (VDs.size () > AVDs.size ()) {
251
- for (auto VD : drop_begin (VDs, AVDs.size ())) {
252
- VD->diagnose (diag::attr_abi_mismatched_var,
253
- VD, /* isABI=*/ false );
254
- }
255
- }
256
- }
198
+ void visitABIAttr (ABIAttr *attr) {
199
+ TypeChecker::checkDeclABIAttribute (D, attr);
257
200
}
258
201
259
- public:
260
202
void visitExecutionAttr (ExecutionAttr *attr) {
261
203
auto *const decl = cast<ValueDecl>(D);
262
204
@@ -300,81 +242,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
300
242
}
301
243
}
302
244
303
- void visitABIAttr (ABIAttr *attr) {
304
- Decl *AD = attr->abiDecl ;
305
- if (isa<VarDecl>(D) && isa<PatternBindingDecl>(AD)) {
306
- auto VD = cast<VarDecl>(D);
307
- auto APBD = cast<PatternBindingDecl>(AD);
308
-
309
- // Diagnose dissimilar PBD structures.
310
- checkABIAttrPBD (APBD, VD);
311
-
312
- // Do the rest of this checking on the corresponding VarDecl, not the
313
- // PBD that's actually in the attribute. Note that `AD` will become null
314
- // if they're too dissimilar to match up.
315
- AD = APBD->getVarAtSimilarStructuralPosition (VD);
316
- }
317
- // TODO: EnumElementDecl?
318
-
319
- if (!AD)
320
- return ;
321
-
322
- // Check the ABI decl and bail if there was a problem with it.
323
- TypeChecker::typeCheckDecl (AD);
324
- if (AD->isInvalid ())
325
- return ;
326
-
327
- // Do the declarations have the same kind, broadly speaking? Many kinds have
328
- // special mangling behavior (e.g. inits vs normal funcs) that make it
329
- // unrealistic to treat one kind as though it were another.
330
- if (D->getKind () != AD->getKind ()) {
331
- // FIXME: DescriptiveDeclKind is overly specific; we really just want to
332
- // say that e.g. a `func` can't have the ABI of a `var`.
333
- diagnoseAndRemoveAttr (attr, diag::attr_abi_mismatched_kind,
334
- D, AD->getDescriptiveKind ());
335
- return ;
336
- }
337
-
338
- if (isa<AbstractFunctionDecl>(D)) {
339
- auto AFD = cast<AbstractFunctionDecl>(D);
340
- auto AAFD = cast<AbstractFunctionDecl>(AD);
341
-
342
- // FIXME: How much should we diagnose in IRGen for more precise ABI info?
343
-
344
- // Do the declarations have roughly the same number of parameters? We'll
345
- // allow some fuzziness for what these parameters *are*, since there isn't
346
- // always an ABI difference between e.g. a free function with N parameters
347
- // and an instance method with N-1 parameters (plus an implicit `self`).
348
- if (getABIArity (AFD) != getABIArity (AAFD)) {
349
- diagnoseAndRemoveAttr (attr, diag::attr_abi_mismatched_arity,
350
- AFD);
351
- }
352
-
353
- // Do the declarations match in throwing behavior? We don't care about
354
- // `throws` vs. `rethrows` here, just whether callers will account for an
355
- // error return.
356
- // FIXME: Typed throws?
357
- if (AFD->hasThrows () != AAFD->hasThrows ()) {
358
- diagnoseAndRemoveAttr (attr, diag::attr_abi_mismatched_throws,
359
- AFD, /* abiCanThrow=*/ AAFD->hasThrows ());
360
- }
361
-
362
- // Do the declarations match in async-ness?
363
- if (AFD->hasAsync () != AAFD->hasAsync ()) {
364
- diagnoseAndRemoveAttr (attr, diag::attr_abi_mismatched_async,
365
- AFD, /* abiHasAsync=*/ AAFD->hasAsync ());
366
- }
367
- }
368
-
369
- // TODO: Diagnose if Protocol::isMarkerProtocol() - contradiction in terms
370
- // (and mangler can't handle invertible protocols with @abi)
371
-
372
- // TODO: Validate more
373
- // FIXME: The list of properties that have to match is practically endless
374
- // and will grow as new features are added to the compiler. We might want to
375
- // write an AttributeVisitor just to help us catch omissions over time.
376
- }
377
-
378
245
void visitAlignmentAttr (AlignmentAttr *attr) {
379
246
// Alignment must be a power of two.
380
247
auto value = attr->getValue ();
0 commit comments