Skip to content

Commit 411d3ab

Browse files
committed
[apinotes][cxx-interop] Add support for ImportAs, Retain, and Release.
1 parent 924930d commit 411d3ab

File tree

8 files changed

+162
-5
lines changed

8 files changed

+162
-5
lines changed

clang/include/clang/APINotes/Types.h

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,8 @@ class FunctionInfo : public CommonEntityInfo {
509509
/// The function parameters.
510510
std::vector<ParamInfo> Params;
511511

512+
llvm::Optional<std::string> ImportAs;
513+
512514
FunctionInfo()
513515
: NullabilityAudited(false), NumAdjustedNullable(0),
514516
RawRetainCountConvention() {}
@@ -659,7 +661,11 @@ class TagInfo : public CommonTypeInfo {
659661
public:
660662
llvm::Optional<EnumExtensibilityKind> EnumExtensibility;
661663

662-
TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}
664+
llvm::Optional<std::string> ImportAs;
665+
llvm::Optional<std::string> RetainOp;
666+
llvm::Optional<std::string> ReleaseOp;
667+
668+
TagInfo() : CommonTypeInfo(), HasFlagEnum(0), IsFlagEnum(0) {}
663669

664670
llvm::Optional<bool> isFlagEnum() const {
665671
if (HasFlagEnum)
@@ -671,6 +677,27 @@ class TagInfo : public CommonTypeInfo {
671677
IsFlagEnum = Value.value_or(false);
672678
}
673679

680+
void setImportAs(llvm::Optional<std::string> Value) {
681+
ImportAs = Value;
682+
}
683+
llvm::Optional<std::string> getImportAs() const {
684+
return ImportAs;
685+
}
686+
687+
void setRetainOp(llvm::Optional<std::string> Value) {
688+
RetainOp = Value;
689+
}
690+
llvm::Optional<std::string> getRetainOp() const {
691+
return RetainOp;
692+
}
693+
694+
void setReleaseOp(llvm::Optional<std::string> Value) {
695+
ReleaseOp = Value;
696+
}
697+
llvm::Optional<std::string> getReleaseOp() const {
698+
return ReleaseOp;
699+
}
700+
674701
TagInfo &operator|=(const TagInfo &RHS) {
675702
static_cast<CommonTypeInfo &>(*this) |= RHS;
676703

@@ -680,6 +707,13 @@ class TagInfo : public CommonTypeInfo {
680707
if (!EnumExtensibility)
681708
EnumExtensibility = RHS.EnumExtensibility;
682709

710+
if (!getImportAs())
711+
setImportAs(RHS.getImportAs());
712+
if (!getRetainOp())
713+
setImportAs(RHS.getRetainOp());
714+
if (!getReleaseOp())
715+
setImportAs(RHS.getReleaseOp());
716+
683717
return *this;
684718
}
685719

@@ -691,7 +725,10 @@ class TagInfo : public CommonTypeInfo {
691725
inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
692726
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
693727
LHS.isFlagEnum() == RHS.isFlagEnum() &&
694-
LHS.EnumExtensibility == RHS.EnumExtensibility;
728+
LHS.EnumExtensibility == RHS.EnumExtensibility &&
729+
LHS.getImportAs() == RHS.getImportAs() &&
730+
LHS.getRetainOp() == RHS.getRetainOp() &&
731+
LHS.getReleaseOp() == RHS.getReleaseOp();
695732
}
696733

697734
inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,14 @@ namespace {
351351
= endian::readNext<uint16_t, little, unaligned>(data);
352352
info.ResultType = std::string(data, data + resultTypeLen);
353353
data += resultTypeLen;
354+
355+
unsigned importAsLength =
356+
endian::readNext<uint16_t, little, unaligned>(data);
357+
if (importAsLength > 0) {
358+
info.ImportAs =
359+
std::string(reinterpret_cast<const char *>(data), importAsLength-1);
360+
data += importAsLength-1;
361+
}
354362
}
355363

356364
/// Used to deserialize the on-disk Objective-C method table.
@@ -524,6 +532,28 @@ namespace {
524532
static_cast<EnumExtensibilityKind>((payload & 0x3) - 1);
525533
}
526534

535+
unsigned importAsLength =
536+
endian::readNext<uint16_t, little, unaligned>(data);
537+
if (importAsLength > 0) {
538+
info.setImportAs(
539+
std::string(reinterpret_cast<const char *>(data), importAsLength-1));
540+
data += importAsLength-1;
541+
}
542+
unsigned retainOpLength =
543+
endian::readNext<uint16_t, little, unaligned>(data);
544+
if (retainOpLength > 0) {
545+
info.setRetainOp(
546+
std::string(reinterpret_cast<const char *>(data), retainOpLength-1));
547+
data += retainOpLength-1;
548+
}
549+
unsigned releaseOpLength =
550+
endian::readNext<uint16_t, little, unaligned>(data);
551+
if (releaseOpLength > 0) {
552+
info.setReleaseOp(
553+
std::string(reinterpret_cast<const char *>(data), releaseOpLength-1));
554+
data += releaseOpLength-1;
555+
}
556+
527557
readCommonTypeInfo(data, info);
528558
return info;
529559
}

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,8 @@ namespace {
739739
/// Retrieve the serialized size of the given FunctionInfo, for use in
740740
/// on-disk hash tables.
741741
static unsigned getFunctionInfoSize(const FunctionInfo &info) {
742-
unsigned size = 2 + sizeof(uint64_t) + getCommonEntityInfoSize(info) + 2;
742+
unsigned size = 2 + sizeof(uint64_t) + getCommonEntityInfoSize(info) + 2 +
743+
2 + (info.ImportAs ? info.ImportAs->size() : 0);
743744

744745
for (const auto &param : info.Params)
745746
size += getParamInfoSize(param);
@@ -773,6 +774,13 @@ namespace {
773774
// Result type.
774775
writer.write<uint16_t>(info.ResultType.size());
775776
out.write(info.ResultType.data(), info.ResultType.size());
777+
778+
if (auto importAs = info.ImportAs) {
779+
writer.write<uint16_t>(importAs->size() + 1);
780+
out.write(importAs->c_str(), importAs->size());
781+
} else {
782+
writer.write<uint16_t>(0);
783+
}
776784
}
777785

778786
/// Used to serialize the on-disk Objective-C method table.
@@ -1132,7 +1140,10 @@ namespace {
11321140
class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
11331141
public:
11341142
unsigned getUnversionedInfoSize(const TagInfo &info) {
1135-
return 1 + getCommonTypeInfoSize(info);
1143+
return 2 + (info.getImportAs() ? info.getImportAs()->size() : 0) +
1144+
2 + (info.getRetainOp() ? info.getRetainOp()->size() : 0) +
1145+
2 + (info.getReleaseOp() ? info.getReleaseOp()->size() : 0) +
1146+
1 + getCommonTypeInfoSize(info);
11361147
}
11371148

11381149
void emitUnversionedInfo(raw_ostream &out, const TagInfo &info) {
@@ -1152,6 +1163,27 @@ namespace {
11521163

11531164
writer.write<uint8_t>(payload);
11541165

1166+
if (auto importAs = info.getImportAs()) {
1167+
writer.write<uint16_t>(importAs->size() + 1);
1168+
out.write(importAs->c_str(), importAs->size());
1169+
} else {
1170+
writer.write<uint16_t>(0);
1171+
}
1172+
1173+
if (auto retainOp = info.getRetainOp()) {
1174+
writer.write<uint16_t>(retainOp->size() + 1);
1175+
out.write(retainOp->c_str(), retainOp->size());
1176+
} else {
1177+
writer.write<uint16_t>(0);
1178+
}
1179+
1180+
if (auto releaseOp = info.getReleaseOp()) {
1181+
writer.write<uint16_t>(releaseOp->size() + 1);
1182+
out.write(releaseOp->c_str(), releaseOp->size());
1183+
} else {
1184+
writer.write<uint16_t>(0);
1185+
}
1186+
11551187
emitCommonTypeInfo(out, info);
11561188
}
11571189
};

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ struct Function {
402402
StringRef SwiftName;
403403
StringRef Type;
404404
StringRef ResultType;
405+
Optional<StringRef> ImportAs;
405406
};
406407

407408
typedef std::vector<Function> FunctionsSeq;
@@ -424,6 +425,7 @@ template <> struct MappingTraits<Function> {
424425
IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
425426
IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
426427
IO.mapOptional("ResultType", F.ResultType, StringRef(""));
428+
IO.mapOptional("ImportAs", F.ImportAs);
427429
}
428430
};
429431
} // namespace yaml
@@ -530,6 +532,9 @@ struct Tag {
530532
Optional<EnumExtensibilityKind> EnumExtensibility;
531533
Optional<bool> FlagEnum;
532534
Optional<EnumConvenienceAliasKind> EnumConvenienceKind;
535+
Optional<StringRef> ImportAs;
536+
Optional<StringRef> RetainOp;
537+
Optional<StringRef> ReleaseOp;
533538
FunctionsSeq MemberFuncs;
534539
};
535540

@@ -561,6 +566,9 @@ template <> struct MappingTraits<Tag> {
561566
IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
562567
IO.mapOptional("FlagEnum", T.FlagEnum);
563568
IO.mapOptional("EnumKind", T.EnumConvenienceKind);
569+
IO.mapOptional("ImportAs", T.ImportAs);
570+
IO.mapOptional("Retain", T.RetainOp);
571+
IO.mapOptional("Release", T.ReleaseOp);
564572
IO.mapOptional("Methods", T.MemberFuncs);
565573
}
566574
};
@@ -1032,6 +1040,9 @@ namespace {
10321040
info, function.Name);
10331041
info.ResultType = std::string(function.ResultType);
10341042
info.setRetainCountConvention(function.RetainCountConvention);
1043+
if (function.ImportAs)
1044+
info.ImportAs = function.ImportAs->str();
1045+
10351046
Writer->addGlobalFunction(function.Name, info, swiftVersion);
10361047
}
10371048

@@ -1100,6 +1111,13 @@ namespace {
11001111
tagInfo.setFlagEnum(t.FlagEnum);
11011112
}
11021113

1114+
if (t.ImportAs)
1115+
tagInfo.setImportAs(t.ImportAs->str());
1116+
if (t.RetainOp)
1117+
tagInfo.setRetainOp(t.RetainOp->str());
1118+
if (t.ReleaseOp)
1119+
tagInfo.setReleaseOp(t.ReleaseOp->str());
1120+
11031121
Writer->addTag(t.Name, tagInfo, swiftVersion);
11041122

11051123
for (auto Member : t.MemberFuncs) {
@@ -1115,6 +1133,8 @@ namespace {
11151133
info, MemberName);
11161134
info.ResultType = std::string(Member.ResultType);
11171135
info.setRetainCountConvention(Member.RetainCountConvention);
1136+
if (Member.ImportAs)
1137+
info.ImportAs = Member.ImportAs->str();
11181138

11191139
Writer->addMemberFunction(MemberName, info, swiftVersion);
11201140
}

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,12 @@ static void ProcessAPINotes(Sema &S, FunctionOrMethod AnyFunc,
583583
}
584584
}
585585

586+
if (auto importAs = info.ImportAs) {
587+
auto str = "import_" + importAs.getValue();
588+
auto attr = SwiftAttrAttr::CreateImplicit(S.Context, str);
589+
D->addAttr(attr);
590+
}
591+
586592
// Retain count convention
587593
handleAPINotedRetainCountConvention(S, D, metadata,
588594
info.getRetainCountConvention());
@@ -667,6 +673,22 @@ static void ProcessAPINotes(Sema &S, TagDecl *D,
667673
});
668674
}
669675

676+
if (auto importAs = info.getImportAs()) {
677+
auto str = "import_" + importAs.getValue();
678+
auto attr = SwiftAttrAttr::CreateImplicit(S.Context, str);
679+
D->addAttr(attr);
680+
}
681+
if (auto retainOp = info.getRetainOp()) {
682+
auto str = "retain:" + retainOp.getValue();
683+
auto attr = SwiftAttrAttr::CreateImplicit(S.Context, str);
684+
D->addAttr(attr);
685+
}
686+
if (auto releaseOp = info.getReleaseOp()) {
687+
auto str = "release:" + releaseOp.getValue();
688+
auto attr = SwiftAttrAttr::CreateImplicit(S.Context, str);
689+
D->addAttr(attr);
690+
}
691+
670692
// Handle common type information.
671693
ProcessAPINotes(S, D, static_cast<const api_notes::CommonTypeInfo &>(info),
672694
metadata);

clang/test/APINotes/Inputs/Frameworks/CXXInteropKit.framework/Headers/CXXInteropKit.apinotes

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ Tags:
1717
Methods:
1818
- Name: 'method'
1919
SwiftName: globalMethod()
20+
ImportAs: unsafe
2021
- Name: ParentNS.ChildNS.ParentStruct.ChildStruct
2122
Methods:
2223
- Name: 'method'
2324
SwiftName: nestedMethod()
25+
- Name: ImportAsReference
26+
ImportAs: reference
27+
Retain: IARetain
28+
Release: IARelease
2429
Functions:
2530
- Name: ParentNS.ChildNS.gloablFnInNS
26-
SwiftName: childFnInNS()
31+
SwiftName: childFnInNS()
32+
ImportAs: unsafe

clang/test/APINotes/Inputs/Frameworks/CXXInteropKit.framework/Headers/CXXInteropKit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ struct ParentStruct {
4242

4343
}
4444
}
45+
46+
struct ImportAsReference { int x; };

clang/test/APINotes/objcxx-swift-name.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter SomeClass -x objective-c++ | FileCheck %s
44
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter method -x objective-c++ | FileCheck -check-prefix=CHECK-METHOD %s
55
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter gloablFnInNS -x objective-c++ | FileCheck -check-prefix=CHECK-FN %s
6+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter ImportAsReference -x objective-c++ | FileCheck -check-prefix=CHECK-REF %s
67
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter "(anonymous)" -x objective-c++ | FileCheck -check-prefix=CHECK-ANONYMOUS-ENUM %s
78

89
#import <CXXInteropKit/CXXInteropKit.h>
@@ -20,14 +21,21 @@
2021
// CHECK: SwiftNameAttr {{.+}} <<invalid sloc>> "red"
2122

2223
// CHECK-METHOD: Dumping GlobalStruct::method:
24+
// CHECK-METHOD: SwiftAttrAttr {{.+}} <<invalid sloc>> Implicit "import_unsafe"
2325
// CHECK-METHOD: SwiftNameAttr {{.+}} <<invalid sloc>> "globalMethod()"
2426

2527
// CHECK-METHOD: Dumping ParentNS::ChildNS::ParentStruct::ChildStruct::method:
2628
// CHECK-METHOD: SwiftNameAttr {{.+}} <<invalid sloc>> "nestedMethod()"
2729

2830
// CHECK-FN: Dumping ParentNS::ChildNS::gloablFnInNS:
31+
// CHECK-FN: SwiftAttrAttr {{.+}} <<invalid sloc>> Implicit "import_unsafe"
2932
// CHECK-FN: SwiftNameAttr {{.+}} <<invalid sloc>> "childFnInNS()"
3033

34+
// CHECK-REF: Dumping ImportAsReference:
35+
// CHECK-REF: SwiftAttrAttr {{.+}} <<invalid sloc>> Implicit "import_reference"
36+
// CHECK-REF: SwiftAttrAttr {{.+}} <<invalid sloc>> Implicit "retain:IARetain"
37+
// CHECK-REF: SwiftAttrAttr {{.+}} <<invalid sloc>> Implicit "release:IARelease"
38+
3139
// CHECK-ANONYMOUS-ENUM: Dumping (anonymous):
3240
// CHECK-ANONYMOUS-ENUM-NEXT: EnumDecl {{.+}} imported in CXXInteropKit <undeserialized declarations> 'NSSomeEnumOptions':'unsigned long'
3341
// CHECK-ANONYMOUS-ENUM-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "SomeEnum.Options"

0 commit comments

Comments
 (0)