mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
ABI checker: diagnose the missing of @available attributes for added ABIs
New ABIs should have an @available attribute to describe the introducing version. This patch teaches the tool to diagnose its missing. Decls with @_AlwaysEmitIntoClient are excluded from the blaming lists since they are essentially available all the time. rdar://51089418
This commit is contained in:
@@ -96,6 +96,8 @@ ERROR(type_witness_change,none,"%0 has type witness type for %1 changing from %2
|
||||
|
||||
ERROR(decl_new_witness_table_entry,none,"%0 now requires %select{|no}1 new witness table entry", (StringRef, bool))
|
||||
|
||||
ERROR(new_decl_without_intro,none,"%0 is a new API without @available attribute", (StringRef))
|
||||
|
||||
#ifndef DIAG_NO_UNDEF
|
||||
# if defined(DIAG)
|
||||
# undef DIAG
|
||||
|
||||
@@ -57,6 +57,20 @@ cake1: Var C1.CIIns1 changes from weak to strong
|
||||
cake1: Var C1.CIIns2 changes from strong to weak
|
||||
cake1: Var GlobalLetChangedToVar changes from let to var
|
||||
cake1: Var GlobalVarChangedToLet changes from var to let
|
||||
cake2: Accessor GlobalLetChangedToVar.Set() is a new API without @available attribute
|
||||
cake2: Accessor fixedLayoutStruct2.BecomeFixedBinaryOrder.Set() is a new API without @available attribute
|
||||
cake2: AssociatedType RequiementChanges.addedTypeWithDefault is a new API without @available attribute
|
||||
cake2: AssociatedType RequiementChanges.addedTypeWithoutDefault is a new API without @available attribute
|
||||
cake2: Class C0 is a new API without @available attribute
|
||||
cake2: Class C8 is a new API without @available attribute
|
||||
cake2: Constructor C1.init(_:) is a new API without @available attribute
|
||||
cake2: EnumElement FrozenKind.AddedCase is a new API without @available attribute
|
||||
cake2: Func RequiementChanges.addedFunc() is a new API without @available attribute
|
||||
cake2: Func fixedLayoutStruct.OKChange() is a new API without @available attribute
|
||||
cake2: Protocol P4 is a new API without @available attribute
|
||||
cake2: Var RequiementChanges.addedVar is a new API without @available attribute
|
||||
cake2: Var fixedLayoutStruct.$__lazy_storage_$_lazy_d is a new API without @available attribute
|
||||
cake2: Var fixedLayoutStruct.c is a new API without @available attribute
|
||||
|
||||
/* Fixed-layout Type changes */
|
||||
cake1: EnumElement FrozenKind.Fixed in a non-resilient type changes position from 1 to 2
|
||||
|
||||
@@ -1035,6 +1035,10 @@
|
||||
"moduleName": "cake",
|
||||
"genericSig": "<τ_0_0 where τ_0_0 : PSuper>",
|
||||
"isABIPlaceholder": true,
|
||||
"intro_Macosx": "9999",
|
||||
"intro_iOS": "9999",
|
||||
"intro_tvOS": "9999",
|
||||
"intro_watchOS": "9999",
|
||||
"funcSelfKind": "NonMutating"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -982,6 +982,10 @@
|
||||
"moduleName": "cake",
|
||||
"genericSig": "<Self where Self : PSuper>",
|
||||
"isABIPlaceholder": true,
|
||||
"intro_Macosx": "9999",
|
||||
"intro_iOS": "9999",
|
||||
"intro_tvOS": "9999",
|
||||
"intro_watchOS": "9999",
|
||||
"funcSelfKind": "NonMutating"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
// The init(signOf:magnitudeOf:) blames are false positives. They are not new APIs.
|
||||
Constructor Double.init(signOf:magnitudeOf:) is a new API without @available attribute
|
||||
Constructor Float.init(signOf:magnitudeOf:) is a new API without @available attribute
|
||||
Constructor Float80.init(signOf:magnitudeOf:) is a new API without @available attribute
|
||||
|
||||
Constructor __RawDictionaryStorage.init(coder:) is a new API without @available attribute
|
||||
Constructor __RawSetStorage.init(coder:) is a new API without @available attribute
|
||||
Constructor __SwiftNativeNSData.init(coder:) is a new API without @available attribute
|
||||
Constructor __SwiftNativeNSDictionary.init(coder:) is a new API without @available attribute
|
||||
Constructor __SwiftNativeNSSet.init(coder:) is a new API without @available attribute
|
||||
|
||||
Func _cos(_:) has been removed
|
||||
Func _exp(_:) has been removed
|
||||
Func _exp2(_:) has been removed
|
||||
|
||||
@@ -1145,6 +1145,8 @@ static bool isABIPlaceholderRecursive(Decl *D) {
|
||||
}
|
||||
|
||||
StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
|
||||
if (!D)
|
||||
return StringRef();
|
||||
for (auto *ATT: D->getAttrs()) {
|
||||
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
|
||||
if (AVA->Platform == Kind && AVA->Introduced) {
|
||||
@@ -1152,10 +1154,12 @@ StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringRef();
|
||||
return getPlatformIntroVersion(D->getDeclContext()->getAsDecl(), Kind);
|
||||
}
|
||||
|
||||
StringRef SDKContext::getLanguageIntroVersion(Decl *D) {
|
||||
if (!D)
|
||||
return StringRef();
|
||||
for (auto *ATT: D->getAttrs()) {
|
||||
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
|
||||
if (AVA->isLanguageVersionSpecific() && AVA->Introduced) {
|
||||
@@ -1163,7 +1167,7 @@ StringRef SDKContext::getLanguageIntroVersion(Decl *D) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return StringRef();
|
||||
return getLanguageIntroVersion(D->getDeclContext()->getAsDecl());
|
||||
}
|
||||
|
||||
SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Type Ty, TypeInitInfo Info) :
|
||||
|
||||
@@ -293,6 +293,9 @@ struct PlatformIntroVersion {
|
||||
StringRef tvos;
|
||||
StringRef watchos;
|
||||
StringRef swift;
|
||||
bool hasOSAvailability() const {
|
||||
return !macos.empty() || !ios.empty() || !tvos.empty() || !watchos.empty();
|
||||
}
|
||||
};
|
||||
|
||||
class SDKNodeDecl: public SDKNode {
|
||||
@@ -347,6 +350,7 @@ public:
|
||||
StringRef getScreenInfo() const;
|
||||
bool hasFixedBinaryOrder() const { return FixedBinaryOrder.hasValue(); }
|
||||
uint8_t getFixedBinaryOrder() const { return *FixedBinaryOrder; }
|
||||
PlatformIntroVersion getIntroducingVersion() const { return introVersions; }
|
||||
virtual void jsonize(json::Output &Out) override;
|
||||
virtual void diagnose(SDKNode *Right) override;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static StringRef getCategoryName(uint32_t ID) {
|
||||
case LocalDiagID::decl_new_attr:
|
||||
case LocalDiagID::var_let_changed:
|
||||
case LocalDiagID::func_self_access_change:
|
||||
case LocalDiagID::new_decl_without_intro:
|
||||
return "/* Decl Attribute changes */";
|
||||
case LocalDiagID::default_arg_removed:
|
||||
case LocalDiagID::decl_type_change:
|
||||
|
||||
@@ -1003,6 +1003,13 @@ public:
|
||||
if (D->hasFixedBinaryOrder()) {
|
||||
D->emitDiag(diag::decl_added);
|
||||
}
|
||||
// Diagnose the missing of @available attributes.
|
||||
// Decls with @_alwaysEmitIntoClient aren't required to have an
|
||||
// @available attribute.
|
||||
if (!D->getIntroducingVersion().hasOSAvailability() &&
|
||||
!D->hasDeclAttribute(DeclAttrKind::DAK_AlwaysEmitIntoClient)) {
|
||||
D->emitDiag(diag::new_decl_without_intro);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Complain about added protocol requirements
|
||||
@@ -1038,7 +1045,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
case NodeMatchReason::Removed:
|
||||
assert(!Right);
|
||||
|
||||
Reference in New Issue
Block a user