Skip to content

Commit 3785e5c

Browse files
committed
[APINotes] Add SWIFT_RETURNS_(UN)RETAINED support to APINotes
rdar://141007510
1 parent 1a89604 commit 3785e5c

File tree

9 files changed

+78
-2
lines changed

9 files changed

+78
-2
lines changed

clang/include/clang/APINotes/Types.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@ class FunctionInfo : public CommonEntityInfo {
542542
/// The result type of this function, as a C type.
543543
std::string ResultType;
544544

545+
/// Swift name of this entity.
546+
std::string SwiftReturnOwnership;
547+
545548
/// The function parameters.
546549
std::vector<ParamInfo> Params;
547550

@@ -600,6 +603,13 @@ class FunctionInfo : public CommonEntityInfo {
600603

601604
friend bool operator==(const FunctionInfo &, const FunctionInfo &);
602605

606+
FunctionInfo &operator|=(const FunctionInfo &RHS) {
607+
if (SwiftReturnOwnership.empty())
608+
SwiftReturnOwnership = RHS.SwiftReturnOwnership;
609+
610+
return *this;
611+
}
612+
603613
private:
604614
NullabilityKind getTypeInfo(unsigned index) const {
605615
assert(NullabilityAudited &&
@@ -622,7 +632,8 @@ inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
622632
LHS.NumAdjustedNullable == RHS.NumAdjustedNullable &&
623633
LHS.NullabilityPayload == RHS.NullabilityPayload &&
624634
LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params &&
625-
LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
635+
LHS.RawRetainCountConvention == RHS.RawRetainCountConvention &&
636+
LHS.SwiftReturnOwnership == RHS.SwiftReturnOwnership;
626637
}
627638

628639
inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,13 @@ void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
373373
endian::readNext<uint16_t, llvm::endianness::little>(Data);
374374
Info.ResultType = std::string(Data, Data + ResultTypeLen);
375375
Data += ResultTypeLen;
376+
377+
unsigned SwiftReturnOwnershipLength =
378+
endian::readNext<uint16_t, llvm::endianness::little>(Data);
379+
Info.SwiftReturnOwnership = std::string(reinterpret_cast<const char *>(Data),
380+
reinterpret_cast<const char *>(Data) +
381+
SwiftReturnOwnershipLength);
382+
Data += SwiftReturnOwnershipLength;
376383
}
377384

378385
/// Used to deserialize the on-disk Objective-C method table.

clang/lib/APINotes/APINotesTypes.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ LLVM_DUMP_METHOD void FunctionInfo::dump(llvm::raw_ostream &OS) const {
7777
<< "RawRetainCountConvention: " << RawRetainCountConvention << ' ';
7878
if (!ResultType.empty())
7979
OS << "Result Type: " << ResultType << ' ';
80+
if (!SwiftReturnOwnership.empty())
81+
OS << "SwiftReturnOwnership: " << SwiftReturnOwnership << ' ';
8082
if (!Params.empty())
8183
OS << '\n';
8284
for (auto &PI : Params)

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,7 @@ unsigned getFunctionInfoSize(const FunctionInfo &FI) {
10931093
for (const auto &P : FI.Params)
10941094
size += getParamInfoSize(P);
10951095
size += sizeof(uint16_t) + FI.ResultType.size();
1096+
size += FI.SwiftReturnOwnership.size();
10961097
return size;
10971098
}
10981099

@@ -1118,6 +1119,8 @@ void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) {
11181119

11191120
writer.write<uint16_t>(FI.ResultType.size());
11201121
writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
1122+
writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1123+
OS.write(FI.SwiftReturnOwnership.c_str(), FI.SwiftReturnOwnership.size());
11211124
}
11221125

11231126
/// Used to serialize the on-disk global function table.

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct Method {
162162
bool DesignatedInit = false;
163163
bool Required = false;
164164
StringRef ResultType;
165+
StringRef SwiftReturnOwnership;
165166
};
166167

167168
typedef std::vector<Method> MethodsSeq;
@@ -196,6 +197,8 @@ template <> struct MappingTraits<Method> {
196197
IO.mapOptional("DesignatedInit", M.DesignatedInit, false);
197198
IO.mapOptional("Required", M.Required, false);
198199
IO.mapOptional("ResultType", M.ResultType, StringRef(""));
200+
IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership,
201+
StringRef(""));
199202
}
200203
};
201204
} // namespace yaml
@@ -291,6 +294,7 @@ struct Function {
291294
StringRef SwiftName;
292295
StringRef Type;
293296
StringRef ResultType;
297+
StringRef SwiftReturnOwnership;
294298
};
295299

296300
typedef std::vector<Function> FunctionsSeq;
@@ -313,6 +317,8 @@ template <> struct MappingTraits<Function> {
313317
IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
314318
IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
315319
IO.mapOptional("ResultType", F.ResultType, StringRef(""));
320+
IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership,
321+
StringRef(""));
316322
}
317323
};
318324
} // namespace yaml
@@ -825,6 +831,7 @@ class YAMLConverter {
825831
emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
826832

827833
MI.ResultType = std::string(M.ResultType);
834+
MI.SwiftReturnOwnership = std::string(M.SwiftReturnOwnership);
828835

829836
// Translate parameter information.
830837
convertParams(M.Params, MI, MI.Self);
@@ -950,6 +957,7 @@ class YAMLConverter {
950957
convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,
951958
Function.Name);
952959
FI.ResultType = std::string(Function.ResultType);
960+
FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership);
953961
FI.setRetainCountConvention(Function.RetainCountConvention);
954962
}
955963

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
511511
AnyTypeChanged = true;
512512
}
513513

514+
// returns_(un)retained
515+
if (!Info.SwiftReturnOwnership.empty())
516+
D->addAttr(SwiftAttrAttr::Create(S.Context, Info.SwiftReturnOwnership));
517+
514518
// Result type override.
515519
QualType OverriddenResultType;
516520
if (Metadata.IsActive && !Info.ResultType.empty() &&

clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ Name: SwiftImportAs
33
Tags:
44
- Name: ImmortalRefType
55
SwiftImportAs: reference
6+
Methods:
7+
- Name: methodReturningFrt_returns_retained
8+
SwiftReturnOwnership: 'returns_retained'
69
- Name: RefCountedType
710
SwiftImportAs: reference
811
SwiftReleaseOp: RCRelease
@@ -17,3 +20,11 @@ Tags:
1720
SwiftEscapable: false
1821
- Name: EscapableType
1922
SwiftEscapable: true
23+
24+
Functions:
25+
- Name: functionReturningFrt__
26+
- Name: functionReturningFrt_returns_unretained
27+
SwiftReturnOwnership: 'returns_unretained'
28+
- Name: functionReturningFrt_returns_retained
29+
SwiftReturnOwnership: 'returns_retained'
30+

clang/test/APINotes/Inputs/Headers/SwiftImportAs.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
struct ImmortalRefType {};
1+
struct ImmortalRefType {
2+
ImmortalRefType * methodReturningFrt__(void);
3+
ImmortalRefType * methodReturningFrt_returns_unretained(void);
4+
ImmortalRefType * methodReturningFrt_returns_retained(void);
5+
};
6+
7+
ImmortalRefType * functionReturningFrt__(void);
8+
ImmortalRefType * functionReturningFrt_returns_unretained(void);
9+
ImmortalRefType * functionReturningFrt_returns_retained(void);
10+
211

312
struct RefCountedType { int value; };
413

clang/test/APINotes/swift-import-as.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter CopyableType | FileCheck -check-prefix=CHECK-COPYABLE %s
77
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonEscapableType | FileCheck -check-prefix=CHECK-NON-ESCAPABLE %s
88
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter EscapableType | FileCheck -check-prefix=CHECK-ESCAPABLE %s
9+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter functionReturningFrt__ | FileCheck -check-prefix=CHECK-FUNCTION-RETURNING-FRT %s
10+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter functionReturningFrt_returns_unretained | FileCheck -check-prefix=CHECK-FUNCTION-RETURNING-FRT-UNRETAINED %s
11+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter functionReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-FUNCTION-RETURNING-FRT-RETAINED %s
12+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-RETAINED %s
913

1014
#include <SwiftImportAs.h>
1115

@@ -36,3 +40,20 @@
3640
// CHECK-ESCAPABLE: Dumping EscapableType:
3741
// CHECK-ESCAPABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct EscapableType
3842
// CHECK-ESCAPABLE: SwiftAttrAttr {{.+}} "Escapable"
43+
44+
//CHECK-FUNCTION-RETURNING-FRT: Dumping functionReturningFrt__:
45+
//CHECK-FUNCTION-RETURNING-FRT: FunctionDecl {{.+}} imported in SwiftImportAs functionReturningFrt__ 'ImmortalRefType *()'
46+
//CHECK-FUNCTION-RETURNING-FRT-NOT: `-SwiftAttrAttr {{.+}} "returns_unretained"
47+
//CHECK-FUNCTION-RETURNING-FRT-NOT: `-SwiftAttrAttr {{.+}} "returns_retained"
48+
49+
//CHECK-FUNCTION-RETURNING-FRT-UNRETAINED: Dumping functionReturningFrt_returns_unretained:
50+
//CHECK-FUNCTION-RETURNING-FRT-UNRETAINED: FunctionDecl {{.+}} imported in SwiftImportAs functionReturningFrt_returns_unretained 'ImmortalRefType *()'
51+
//CHECK-FUNCTION-RETURNING-FRT-UNRETAINED: `-SwiftAttrAttr {{.+}} "returns_unretained"
52+
53+
//CHECK-FUNCTION-RETURNING-FRT-RETAINED: Dumping functionReturningFrt_returns_retained:
54+
//CHECK-FUNCTION-RETURNING-FRT-RETAINED: FunctionDecl {{.+}} imported in SwiftImportAs functionReturningFrt_returns_retained 'ImmortalRefType *()'
55+
//CHECK-FUNCTION-RETURNING-FRT-RETAINED: `-SwiftAttrAttr {{.+}} "returns_retained"
56+
57+
// CHECK-METHOD-RETURNING-FRT-RETAINED: Dumping ImmortalRefType::methodReturningFrt_returns_retained:
58+
// CHECK-METHOD-RETURNING-FRT-RETAINED: CXXMethodDecl {{.+}} imported in SwiftImportAs methodReturningFrt_returns_retained 'ImmortalRefType *()'
59+
// CHECK-METHOD-RETURNING-FRT-RETAINED: `-SwiftAttrAttr {{.+}} "returns_retained"

0 commit comments

Comments
 (0)