@@ -195,68 +195,10 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
195195 IGNORED_ATTR(Unsafe)
196196#undef IGNORED_ATTR
197197
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);
257200 }
258201
259- public:
260202 void visitExecutionAttr (ExecutionAttr *attr) {
261203 auto *const decl = cast<ValueDecl>(D);
262204
@@ -300,81 +242,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
300242 }
301243 }
302244
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-
378245 void visitAlignmentAttr (AlignmentAttr *attr) {
379246 // Alignment must be a power of two.
380247 auto value = attr->getValue ();
0 commit comments