TBDGen: Improve correctness of API symbol visibility and availability.

By plumbing the currently visited Decl through to APIRecorder we can improve
the correctness of API symbol visibility and availability in swift-api-extract
output.
This commit is contained in:
Allan Shortlidge
2023-10-04 21:41:28 -07:00
parent 6f1f0b0e17
commit 80b1f4c1c2
7 changed files with 53 additions and 54 deletions

View File

@@ -222,26 +222,6 @@ public:
return irEntity;
}
/// Returns the associated decl.
const ValueDecl *getDecl() const {
switch (kind) {
case Kind::SIL: {
if (silDeclRef.hasDecl())
return silDeclRef.getDecl();
return nullptr;
}
case Kind::Global:
return Global;
case Kind::IR:
if (irEntity.hasDecl())
return irEntity.getDecl();
return nullptr;
case Kind::LinkerDirective:
case Kind::Unknown:
return nullptr;
}
}
/// Typecheck the entity wrapped by this `SymbolSource`
void typecheck() const {
switch (kind) {

View File

@@ -81,7 +81,8 @@ void TBDGenVisitor::addSymbolInternal(StringRef name, SymbolKind kind,
}
}
#endif
recorder.addSymbol(name, kind, source);
recorder.addSymbol(name, kind, source,
DeclStack.empty() ? nullptr : DeclStack.back());
}
static std::vector<OriginallyDefinedInAttr::ActiveVersion>
@@ -613,9 +614,8 @@ TBDFile GenerateTBDRequest::evaluate(Evaluator &evaluator,
targets.push_back(targetVar);
}
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) {
file.addSymbol(kind, symbol, targets);
};
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) { file.addSymbol(kind, symbol, targets); };
SimpleAPIRecorder recorder(addSymbol);
TBDGenVisitor visitor(desc, recorder);
visitor.visit(desc);
@@ -626,7 +626,8 @@ std::vector<std::string>
PublicSymbolsRequest::evaluate(Evaluator &evaluator,
TBDGenDescriptor desc) const {
std::vector<std::string> symbols;
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) {
auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) {
if (kind == SymbolKind::GlobalSymbol)
symbols.push_back(symbol.str());
// TextAPI ObjC Class Kinds represents two symbols.
@@ -668,14 +669,13 @@ public:
}
~APIGenRecorder() {}
void addSymbol(StringRef symbol, SymbolKind kind,
SymbolSource source) override {
void addSymbol(StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) override {
if (kind != SymbolKind::GlobalSymbol)
return;
apigen::APIAvailability availability;
auto access = apigen::APIAccess::Public;
auto decl = source.getDecl();
if (decl) {
availability = getAvailability(decl);
if (isSPI(decl))
@@ -856,7 +856,8 @@ SymbolSourceMapRequest::evaluate(Evaluator &evaluator,
auto &Ctx = desc.getParentModule()->getASTContext();
auto *SymbolSources = Ctx.Allocate<SymbolSourceMap>();
auto addSymbol = [=](StringRef symbol, SymbolKind kind, SymbolSource source) {
auto addSymbol = [=](StringRef symbol, SymbolKind kind, SymbolSource source,
Decl *decl) {
SymbolSources->insert({symbol, source});
};

View File

@@ -62,7 +62,7 @@ public:
virtual ~APIRecorder() {}
virtual void addSymbol(StringRef name, llvm::MachO::SymbolKind kind,
SymbolSource source) {}
SymbolSource source, Decl *decl) {}
virtual void addObjCInterface(const ClassDecl *decl) {}
virtual void addObjCCategory(const ExtensionDecl *decl) {}
virtual void addObjCMethod(const GenericContext *ctx, SILDeclRef method) {}
@@ -71,14 +71,15 @@ public:
class SimpleAPIRecorder final : public APIRecorder {
public:
using SymbolCallbackFn = llvm::function_ref<void(
StringRef, llvm::MachO::SymbolKind, SymbolSource)>;
StringRef, llvm::MachO::SymbolKind, SymbolSource, Decl *)>;
SimpleAPIRecorder(SymbolCallbackFn func) : func(func) {}
void addSymbol(StringRef symbol, llvm::MachO::SymbolKind kind,
SymbolSource source) override {
func(symbol, kind, source);
SymbolSource source, Decl *decl) override {
func(symbol, kind, source, decl);
}
private:
SymbolCallbackFn func;
};

View File

@@ -646,19 +646,24 @@ public:
void addMethod(SILDeclRef method) {
assert(method.getDecl()->getDeclContext() == CD);
if (VirtualFunctionElimination || CD->hasResilientMetadata()) {
// If the class is itself resilient and has at least one vtable
// entry, it has a method lookup function.
bool hasLookupFunc =
VirtualFunctionElimination || CD->hasResilientMetadata();
if (FirstTime) {
FirstTime = false;
// If the class is itself resilient and has at least one vtable
// entry, it has a method lookup function.
if (hasLookupFunc)
Visitor.addMethodLookupFunction(CD);
}
if (!Visitor.willVisitDecl(method.getDecl()))
return;
if (hasLookupFunc)
Visitor.addDispatchThunk(method);
}
Visitor.addMethodDescriptor(method);
Visitor.didVisitDecl(method.getDecl());
}
void addMethodOverride(SILDeclRef baseRef, SILDeclRef derivedRef) {}

View File

@@ -9,6 +9,7 @@ import Foundation
@available(macOS 10.13, *)
public class Test : NSObject {
@objc public func method1() {}
@available(macOS 10.14, *)
@objc public class func method2() {}
public func nonObjc() {}
}
@@ -80,13 +81,15 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivg",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule11myGlobalVarSivs",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method1yyFTj",
@@ -104,13 +107,15 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTj",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7method2yyFZTq",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestC7nonObjcyyFTj",
@@ -140,7 +145,8 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule4TestCMa",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCMn",
@@ -167,7 +173,8 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule4TestCN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule4TestCfD",
@@ -317,7 +324,8 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMa",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCMn",
@@ -337,7 +345,8 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule7DerivedCfD",
@@ -370,7 +379,8 @@ public var myGlobalVar: Int = 42
// CHECK-NEXT: {
// CHECK-NEXT: "name": "method2",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface"
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "introduced": "10.14"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },

View File

@@ -155,7 +155,7 @@ public func spiAvailableFunc() {}
// CHECK-SPI-NEXT: },
// CHECK-SPI-NEXT: {
// CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCMa",
// CHECK-SPI-NEXT: "access": "public",
// CHECK-SPI-NEXT: "access": "private",
// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule",
// CHECK-SPI-NEXT: "linkage": "exported"
// CHECK-SPI-NEXT: },
@@ -179,7 +179,7 @@ public func spiAvailableFunc() {}
// CHECK-SPI-NEXT: },
// CHECK-SPI-NEXT: {
// CHECK-SPI-NEXT: "name": "_$s8MyModule0A5ClassCN",
// CHECK-SPI-NEXT: "access": "public",
// CHECK-SPI-NEXT: "access": "private",
// CHECK-SPI-NEXT: "file": "/@input/MyModule.swiftmodule",
// CHECK-SPI-NEXT: "linkage": "exported"
// CHECK-SPI-NEXT: },

View File

@@ -33,7 +33,8 @@ public struct TestStruct {
// CHECK-NEXT: "name": "_$s8MyModule10TestStructVMa",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "name": "_$s8MyModule10TestStructVMn",
@@ -46,7 +47,8 @@ public struct TestStruct {
// CHECK-NEXT: "name": "_$s8MyModule10TestStructVN",
// CHECK-NEXT: "access": "public",
// CHECK-NEXT: "file": "/@input/MyModule.swiftinterface",
// CHECK-NEXT: "linkage": "exported"
// CHECK-NEXT: "linkage": "exported",
// CHECK-NEXT: "introduced": "10.13"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "interfaces": [],