Skip to content

Commit 5ca85f5

Browse files
committed
Filter bad attrs out of module interface @abis
When printing an `@abi` attribute’s decl, we now filter out any attrs that are not valid in that position. Fixes a broken test.
1 parent a82035a commit 5ca85f5

File tree

5 files changed

+125
-10
lines changed

5 files changed

+125
-10
lines changed

Diff for: include/swift/AST/AttrKind.h

+2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ enum class DeclAttrKind : unsigned {
145145
#include "swift/AST/DeclAttr.def"
146146
};
147147

148+
StringRef getDeclAttrKindID(DeclAttrKind kind);
149+
148150
enum : unsigned {
149151
NumDeclAttrKinds = static_cast<unsigned>(DeclAttrKind::Last_DeclAttr) + 1,
150152
NumDeclAttrKindBits = countBitsUsed(NumDeclAttrKinds - 1),

Diff for: lib/AST/ASTPrinter.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,15 @@ void PrintAST::printAttributes(const Decl *D) {
12841284
// for each decl They cannot be shared across different decls.
12851285
assert(Options.ExcludeCustomAttrList.empty());
12861286

1287+
// If there is an `@abi` attr, we need to print it first so that it isn't
1288+
// affected by subsequent mutation of `Options.ExcludeAttrList`.
1289+
if (auto abiAttr = attrs.getAttribute<ABIAttr>()) {
1290+
if (Options.PrintImplicitAttrs && !Options.excludeAttr(abiAttr)) {
1291+
abiAttr->print(Printer, Options, D);
1292+
Options.ExcludeAttrList.push_back(DeclAttrKind::ABI);
1293+
}
1294+
}
1295+
12871296
if (Options.PrintSyntheticSILGenName
12881297
&& !D->getAttrs().hasAttribute<SILGenNameAttr>()) {
12891298
if (canPrintSyntheticSILGenName(D)) {
@@ -1334,7 +1343,8 @@ void PrintAST::printAttributes(const Decl *D) {
13341343
// Add SPIs to both private and package interfaces
13351344
if (!Options.printPublicInterface() &&
13361345
DeclAttribute::canAttributeAppearOnDeclKind(
1337-
DeclAttrKind::SPIAccessControl, D->getKind())) {
1346+
DeclAttrKind::SPIAccessControl, D->getKind()) &&
1347+
!Options.excludeAttrKind(DeclAttrKind::SPIAccessControl)) {
13381348
interleave(D->getSPIGroups(),
13391349
[&](Identifier spiName) {
13401350
Printer.printAttrName("_spi", true);
@@ -1358,7 +1368,7 @@ void PrintAST::printAttributes(const Decl *D) {
13581368
// If the declaration is implicitly @objc, print the attribute now.
13591369
if (auto VD = dyn_cast<ValueDecl>(D)) {
13601370
if (VD->isObjC() && !isa<EnumElementDecl>(VD) &&
1361-
!attrs.hasAttribute<ObjCAttr>()) {
1371+
!attrs.hasAttribute<ObjCAttr>() && ABIRoleInfo(D).providesAPI()) {
13621372
Printer.printAttrName("@objc");
13631373
Printer << " ";
13641374
}

Diff for: lib/AST/Attr.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ static_assert(IsTriviallyDestructible<DeclAttributes>::value,
6868
static_assert(TypeAttrKind::Id <= TypeAttrKind::Last_TypeAttr);
6969
#include "swift/AST/TypeAttr.def"
7070

71+
LLVM_ATTRIBUTE_USED StringRef swift::getDeclAttrKindID(DeclAttrKind kind) {
72+
switch (kind) {
73+
#define DECL_ATTR(_, CLASS, ...) \
74+
case DeclAttrKind::CLASS: \
75+
return #CLASS;
76+
#include "swift/AST/DeclAttr.def"
77+
}
78+
}
79+
7180
StringRef swift::getAccessLevelSpelling(AccessLevel value) {
7281
switch (value) {
7382
case AccessLevel::Private: return "private";
@@ -1677,8 +1686,26 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
16771686
abiDecl = cast<PatternBindingDecl>(abiDecl)
16781687
->getVarAtSimilarStructuralPosition(
16791688
const_cast<VarDecl *>(cast<VarDecl>(D)));
1680-
if (abiDecl)
1681-
abiDecl->print(Printer, Options);
1689+
if (abiDecl) {
1690+
auto optionsCopy = Options;
1691+
1692+
// Don't print any attributes marked with `ForbiddenInABIAttr`.
1693+
// (Reminder: There is manual logic in `PrintAST::printAttributes()`
1694+
// to handle non-ABI attributes when `PrintImplicitAttrs` is set.)
1695+
for (auto rawAttrKind : range(0, unsigned(DeclAttrKind::Last_DeclAttr))) {
1696+
DeclAttrKind attrKind{rawAttrKind};
1697+
if (!(DeclAttribute::getBehaviors(attrKind)
1698+
& DeclAttribute::ForbiddenInABIAttr))
1699+
continue;
1700+
1701+
if (attrKind == DeclAttrKind::AccessControl)
1702+
optionsCopy.PrintAccess = false;
1703+
else
1704+
optionsCopy.ExcludeAttrList.push_back(attrKind);
1705+
}
1706+
1707+
abiDecl->print(Printer, optionsCopy);
1708+
}
16821709
Printer << ")";
16831710

16841711
break;
@@ -1743,7 +1770,7 @@ uint64_t DeclAttribute::getBehaviors(DeclAttrKind DK) {
17431770
return BEHAVIORS;
17441771
#include "swift/AST/DeclAttr.def"
17451772
}
1746-
llvm_unreachable("bad DeclAttrKind");
1773+
return 0;
17471774
}
17481775

17491776
std::optional<Feature> DeclAttribute::getRequiredFeature(DeclAttrKind DK) {

Diff for: test/ModuleInterface/attrs.swift

+37-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name attrs \
2+
// RUN: -emit-private-module-interface-path %t.private.swiftinterface \
23
// RUN: -enable-experimental-feature ABIAttribute \
34
// RUN: -enable-experimental-feature ExecutionAttribute
45

56
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name attrs
7+
// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -module-name attrs
68

7-
// RUN: %FileCheck %s --input-file %t.swiftinterface
9+
// RUN: %FileCheck %s --check-prefixes CHECK,PUBLIC-CHECK --input-file %t.swiftinterface
10+
// RUN: %FileCheck %s --check-prefixes CHECK,PRIVATE-CHECK --input-file %t.private.swiftinterface
811

912
// REQUIRES: swift_feature_ABIAttribute
1013
// REQUIRES: swift_feature_ExecutionAttribute
@@ -35,26 +38,55 @@ internal func __specialize_someGenericFunction<T>(_ t: T) -> Int {
3538
fatalError("don't call")
3639
}
3740

38-
@abi(public func __abi__abiAttrOnFunction(param: Int))
41+
@abi(func __abi__abiAttrOnFunction(param: Int))
3942
public func abiAttrOnFunction(param: Int) {}
4043
// CHECK: #if {{.*}} $ABIAttribute
41-
// CHECK: @abi(public func __abi__abiAttrOnFunction(param: Swift.Int))
44+
// CHECK: @abi(func __abi__abiAttrOnFunction(param: Swift.Int))
4245
// CHECK: public func abiAttrOnFunction(param: Swift.Int)
4346
// CHECK: #else
4447
// CHECK: @_silgen_name("$s5attrs07__abi__B14AttrOnFunction5paramySi_tF")
4548
// CHECK: public func abiAttrOnFunction(param: Swift.Int)
4649
// CHECK: #endif
4750

48-
@abi(public let __abi__abiAttrOnVar: Int)
51+
@abi(let __abi__abiAttrOnVar: Int)
4952
public var abiAttrOnVar: Int = 42
5053
// CHECK: #if {{.*}} $ABIAttribute
51-
// CHECK: @abi(public var __abi__abiAttrOnVar: Swift.Int)
54+
// CHECK: @abi(var __abi__abiAttrOnVar: Swift.Int)
5255
// CHECK: public var abiAttrOnVar: Swift.Int
5356
// CHECK: #else
5457
// CHECK: @available(*, unavailable, message: "this compiler cannot match the ABI specified by the @abi attribute")
5558
// CHECK: public var abiAttrOnVar: Swift.Int
5659
// CHECK: #endif
5760

61+
public struct MutatingTest {
62+
// CHECK: #if {{.*}} $ABIAttribute
63+
// CHECK: @abi(mutating func abiMutFunc())
64+
// CHECK: public mutating func abiMutFunc()
65+
// CHECK: #else
66+
// CHECK: @_silgen_name("$s5attrs12MutatingTestV10abiMutFuncyyF")
67+
// CHECK: public mutating func abiMutFunc()
68+
// CHECK: #endif
69+
@abi(mutating func abiMutFunc())
70+
public mutating func abiMutFunc() {}
71+
}
72+
73+
// PUBLIC-CHECK-NOT: #if {{.*}} $ABIAttribute
74+
// PUBLIC-CHECK-NOT: @abi(func abiSpiFunc())
75+
// PUBLIC-CHECK-NOT: public func abiSpiFunc()
76+
// PUBLIC-CHECK-NOT: #else
77+
// PUBLIC-CHECK-NOT: @_silgen_name("$s5attrs10abiSpiFuncyyF")
78+
// PUBLIC-CHECK-NOT: public func abiSpiFunc()
79+
// PUBLIC-CHECK-NOT: #endif
80+
// PRIVATE-CHECK: #if {{.*}} $ABIAttribute
81+
// PRIVATE-CHECK: @abi(func abiSpiFunc())
82+
// PRIVATE-CHECK: public func abiSpiFunc()
83+
// PRIVATE-CHECK: #else
84+
// PRIVATE-CHECK: @_silgen_name("$s5attrs10abiSpiFuncyyF")
85+
// PRIVATE-CHECK: public func abiSpiFunc()
86+
// PRIVATE-CHECK: #endif
87+
@abi(func abiSpiFunc())
88+
@_spi(spiGroup) public func abiSpiFunc() {}
89+
5890
@execution(concurrent)
5991
public func testExecutionConcurrent() async {}
6092
// CHECK: @execution(concurrent) public func testExecutionConcurrent() async

Diff for: test/ModuleInterface/attrs_objc.swift

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s \
2+
// RUN: -enable-objc-interop -module-name attrs_objc \
3+
// RUN: -enable-experimental-feature ABIAttribute
4+
5+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name attrs_objc
6+
7+
// RUN: %FileCheck %s --input-file %t.swiftinterface
8+
9+
// REQUIRES: swift_feature_ABIAttribute
10+
11+
import Foundation
12+
13+
@objcMembers
14+
public class ObjCTest: NSObject {
15+
// CHECK: #if {{.*}} $ABIAttribute
16+
// CHECK: @abi(func abiObjCFunc())
17+
// CHECK: @objc public func abiObjCFunc()
18+
// CHECK: #else
19+
// CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC03abiC5CFuncyyF")
20+
// CHECK: @objc public func abiObjCFunc()
21+
// CHECK: #endif
22+
@abi(func abiObjCFunc())
23+
@objc public func abiObjCFunc() {}
24+
25+
// CHECK: #if {{.*}} $ABIAttribute
26+
// CHECK: @abi(func abiImplicitObjCFunc())
27+
// CHECK: @objc public func abiImplicitObjCFunc()
28+
// CHECK: #else
29+
// CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC011abiImplicitC5CFuncyyF")
30+
// CHECK: @objc public func abiImplicitObjCFunc()
31+
// CHECK: #endif
32+
@abi(func abiImplicitObjCFunc())
33+
public func abiImplicitObjCFunc() {}
34+
35+
// CHECK: #if {{.*}} $ABIAttribute
36+
// CHECK: @abi(func abiIBActionFunc(_: Any))
37+
// CHECK: @objc @IBAction @_Concurrency.MainActor @preconcurrency public func abiIBActionFunc(_: Any)
38+
// CHECK: #else
39+
// CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC15abiIBActionFuncyyypF")
40+
// CHECK: @objc @IBAction @_Concurrency.MainActor @preconcurrency public func abiIBActionFunc(_: Any)
41+
// CHECK: #endif
42+
@abi(func abiIBActionFunc(_: Any))
43+
@IBAction public func abiIBActionFunc(_: Any) {}
44+
}

0 commit comments

Comments
 (0)