@@ -252,16 +252,43 @@ class UpdatedNodesMap : public MatchedNodeListener {
252
252
}
253
253
};
254
254
255
+ // Describing some attributes with ABI impact. The addition or removal of these
256
+ // attributes is considerred ABI-breaking.
257
+ struct ABIAttributeInfo {
258
+ const DeclAttrKind Kind;
259
+ const NodeAnnotation Annotation;
260
+ const StringRef Content;
261
+ };
262
+
255
263
class SDKContext {
256
- bool ABI;
257
264
llvm::StringSet<> TextData;
258
265
llvm::BumpPtrAllocator Allocator;
259
266
UpdatedNodesMap UpdateMap;
260
267
NodeMap TypeAliasUpdateMap;
261
268
NodeMap RevertTypeAliasUpdateMap;
262
269
TypeMemberDiffVector TypeMemberDiffs;
270
+
271
+ bool ABI;
272
+ std::vector<ABIAttributeInfo> ABIAttrs;
273
+
274
+ static StringRef getAttrName (DeclAttrKind Kind) {
275
+ switch (Kind) {
276
+ #define DECL_ATTR (NAME, CLASS, ...) case DAK_##CLASS: return " @" #NAME;
277
+ #include " swift/AST/Attr.def"
278
+ case DAK_Count:
279
+ llvm_unreachable (" unrecognized attribute kind." );
280
+ }
281
+ }
282
+
263
283
public:
264
- SDKContext (bool ABI): ABI(ABI) {}
284
+ SDKContext (bool ABI): ABI(ABI) {
285
+ #define ADD (NAME ) ABIAttrs.push_back({DeclAttrKind::DAK_##NAME, \
286
+ NodeAnnotation::Change##NAME, getAttrName (DeclAttrKind::DAK_##NAME)});
287
+ ADD (ObjC)
288
+ ADD (FixedLayout)
289
+ ADD (Frozen)
290
+ #undef ADD
291
+ }
265
292
llvm::BumpPtrAllocator &allocator () {
266
293
return Allocator;
267
294
}
@@ -281,6 +308,7 @@ class SDKContext {
281
308
return TypeMemberDiffs;
282
309
}
283
310
bool checkingABI () const { return ABI; }
311
+ ArrayRef<ABIAttributeInfo> getABIAttributeInfo () const { return ABIAttrs; }
284
312
};
285
313
286
314
// A node matcher will traverse two trees of SDKNode and find matched nodes
@@ -446,7 +474,6 @@ class SDKNodeDecl : public SDKNode {
446
474
bool IsStatic;
447
475
bool IsDeprecated;
448
476
uint8_t ReferenceOwnership;
449
- bool hasDeclAttribute (DeclAttrKind DAKind) const ;
450
477
StringRef GenericSig;
451
478
452
479
protected:
@@ -464,6 +491,7 @@ class SDKNodeDecl : public SDKNode {
464
491
StringRef getModuleName () const {return ModuleName;}
465
492
StringRef getHeaderName () const ;
466
493
ArrayRef<DeclAttrKind> getDeclAttributes () const ;
494
+ bool hasAttributeChange (const SDKNodeDecl &Another) const ;
467
495
swift::ReferenceOwnership getReferenceOwnership () const {
468
496
return swift::ReferenceOwnership (ReferenceOwnership);
469
497
}
@@ -474,7 +502,7 @@ class SDKNodeDecl : public SDKNode {
474
502
StringRef getFullyQualifiedName () const ;
475
503
bool isSDKPrivate () const ;
476
504
bool isDeprecated () const { return IsDeprecated; };
477
- bool hasFixedLayout ( ) const ;
505
+ bool hasDeclAttribute (DeclAttrKind DAKind ) const ;
478
506
bool isStatic () const { return IsStatic; };
479
507
StringRef getGenericSignature () const { return GenericSig; }
480
508
};
@@ -761,10 +789,6 @@ SDKNode *SDKNodeRoot::getInstance(SDKContext &Ctx) {
761
789
return Info.createSDKNode (SDKNodeKind::Root);
762
790
}
763
791
764
- bool SDKNodeDecl::hasFixedLayout () const {
765
- return hasDeclAttribute (DeclAttrKind::DAK_FixedLayout);
766
- }
767
-
768
792
bool SDKNodeDecl::isSDKPrivate () const {
769
793
if (getName ().startswith (" __" ))
770
794
return true ;
@@ -818,6 +842,16 @@ ArrayRef<DeclAttrKind> SDKNodeDecl::getDeclAttributes() const {
818
842
return llvm::makeArrayRef (DeclAttributes.data (), DeclAttributes.size ());
819
843
}
820
844
845
+ bool SDKNodeDecl::hasAttributeChange (const SDKNodeDecl &Another) const {
846
+ if (getDeclAttributes ().size () != Another.getDeclAttributes ().size ())
847
+ return true ;
848
+ for (auto K: getDeclAttributes ()) {
849
+ if (!Another.hasDeclAttribute (K))
850
+ return true ;
851
+ }
852
+ return false ;
853
+ }
854
+
821
855
SDKNodeDecl *SDKNodeType::getClosestParentDecl () const {
822
856
auto *Result = getParent ();
823
857
for (; !isa<SDKNodeDecl>(Result); Result = Result->getParent ());
@@ -1175,6 +1209,10 @@ bool SDKNode::operator==(const SDKNode &Other) const {
1175
1209
return false ;
1176
1210
if (Left->getReferenceOwnership () != Right->getReferenceOwnership ())
1177
1211
return false ;
1212
+ if (Left->hasAttributeChange (*Right))
1213
+ return false ;
1214
+ if (Left->getGenericSignature () != Right->getGenericSignature ())
1215
+ return false ;
1178
1216
LLVM_FALLTHROUGH;
1179
1217
}
1180
1218
case SDKNodeKind::Root: {
@@ -2454,13 +2492,19 @@ static bool isOwnershipEquivalent(ReferenceOwnership Left,
2454
2492
2455
2493
static void detectDeclChange (NodePtr L, NodePtr R) {
2456
2494
assert (L->getKind () == R->getKind ());
2495
+ auto &Ctx = L->getSDKContext ();
2457
2496
if (auto LD = dyn_cast<SDKNodeDecl>(L)) {
2458
2497
auto *RD = R->getAs <SDKNodeDecl>();
2459
2498
if (LD->isStatic () ^ RD->isStatic ())
2460
2499
L->annotate (NodeAnnotation::StaticChange);
2461
2500
if (!isOwnershipEquivalent (LD->getReferenceOwnership (),
2462
2501
RD->getReferenceOwnership ()))
2463
2502
L->annotate (NodeAnnotation::OwnershipChange);
2503
+ // Check if some attributes with ABI-impact have been added/removed.
2504
+ for (auto &Info: Ctx.getABIAttributeInfo ()) {
2505
+ if (LD->hasDeclAttribute (Info.Kind ) != RD->hasDeclAttribute (Info.Kind ))
2506
+ L->annotate (Info.Annotation );
2507
+ }
2464
2508
detectRename (L, R);
2465
2509
}
2466
2510
}
@@ -3519,7 +3563,9 @@ void DiagnosisEmitter::DeclTypeChangeDiag::output() const {
3519
3563
bool DiagnosisEmitter::DeclAttrDiag::operator <(DeclAttrDiag Other) const {
3520
3564
if (Kind != Other.Kind )
3521
3565
return Kind < Other.Kind ;
3522
- return DeclName.compare_lower (Other.DeclName );
3566
+ if (DeclName != Other.DeclName )
3567
+ return DeclName.compare (Other.DeclName ) < 0 ;
3568
+ return AttrAfter.compare (Other.AttrAfter ) < 0 ;
3523
3569
}
3524
3570
3525
3571
void DiagnosisEmitter::DeclAttrDiag::output () const {
@@ -3651,9 +3697,22 @@ void DiagnosisEmitter::handle(const SDKNodeDecl *Node, NodeAnnotation Anno) {
3651
3697
getOwnershipDescription (Count->getReferenceOwnership ()));
3652
3698
return ;
3653
3699
}
3654
- default :
3700
+ default : {
3701
+ // Diagnose the addition/removal of attributes with ABI impact.
3702
+ auto Infos = Ctx.getABIAttributeInfo ();
3703
+ auto It = std::find_if (Infos.begin (), Infos.end (),
3704
+ [&](const ABIAttributeInfo &I) { return I.Annotation == Anno; });
3705
+ if (It == Infos.end ())
3706
+ return ;
3707
+ MetaInfo ScreenInfo (Node, true );
3708
+ auto Desc = Node->hasDeclAttribute (It->Kind ) ?
3709
+ Ctx.buffer ((llvm::Twine (" without " ) + It->Content ).str ()):
3710
+ Ctx.buffer ((llvm::Twine (" with " ) + It->Content ).str ());
3711
+ AttrChangedDecls.Diags .emplace_back (ScreenInfo, Node->getDeclKind (),
3712
+ Node->getFullyQualifiedName (), Desc);
3655
3713
return ;
3656
3714
}
3715
+ }
3657
3716
}
3658
3717
3659
3718
void DiagnosisEmitter::visitDecl (SDKNodeDecl *Node) {
0 commit comments