@@ -193,6 +193,7 @@ namespace {
193193
194194 struct Property {
195195 StringRef Name;
196+ llvm::Optional<MethodKind> Kind;
196197 llvm::Optional<NullabilityKind> Nullability;
197198 AvailabilityItem Availability;
198199 bool SwiftPrivate = false ;
@@ -348,6 +349,7 @@ namespace llvm {
348349 struct MappingTraits <Property> {
349350 static void mapping (IO &io, Property& p) {
350351 io.mapRequired (" Name" , p.Name );
352+ io.mapOptional (" PropertyKind" , p.Kind );
351353 io.mapOptional (" Nullability" , p.Nullability ,
352354 AbsentNullability);
353355 io.mapOptional (" Availability" , p.Availability .Mode );
@@ -693,11 +695,20 @@ namespace {
693695 }
694696
695697 // Write all properties.
696- llvm::StringSet<> knownProperties;
698+ llvm::StringSet<> knownInstanceProperties;
699+ llvm::StringSet<> knownClassProperties;
697700 for (const auto &prop : cl.Properties ) {
698701 // Check for duplicate property definitions.
699- if (!knownProperties.insert (prop.Name ).second ) {
700- emitError (" duplicate definition of property '" + cl.Name + " ." +
702+ if ((!prop.Kind || *prop.Kind == MethodKind::Instance) &&
703+ !knownInstanceProperties.insert (prop.Name ).second ) {
704+ emitError (" duplicate definition of instance property '" + cl.Name +
705+ " ." + prop.Name + " '" );
706+ continue ;
707+ }
708+
709+ if ((!prop.Kind || *prop.Kind == MethodKind::Class) &&
710+ !knownClassProperties.insert (prop.Name ).second ) {
711+ emitError (" duplicate definition of class property '" + cl.Name + " ." +
701712 prop.Name + " '" );
702713 continue ;
703714 }
@@ -711,7 +722,14 @@ namespace {
711722 pInfo.SwiftName = prop.SwiftName ;
712723 if (prop.Nullability )
713724 pInfo.setNullabilityAudited (*prop.Nullability );
714- Writer->addObjCProperty (clID, prop.Name , pInfo);
725+ if (prop.Kind ) {
726+ Writer->addObjCProperty (clID, prop.Name ,
727+ *prop.Kind == MethodKind::Instance, pInfo);
728+ } else {
729+ // Add both instance and class properties with this name.
730+ Writer->addObjCProperty (clID, prop.Name , true , pInfo);
731+ Writer->addObjCProperty (clID, prop.Name , false , pInfo);
732+ }
715733 }
716734 }
717735
@@ -1037,9 +1055,11 @@ namespace {
10371055 }
10381056
10391057 virtual void visitObjCProperty (ContextID contextID, StringRef name,
1058+ bool isInstance,
10401059 const ObjCPropertyInfo &info) {
10411060 Property property;
10421061 property.Name = name;
1062+ property.Kind = isInstance ? MethodKind::Instance : MethodKind::Class;
10431063 handleCommon (property, info);
10441064
10451065 // FIXME: No way to represent "not audited for nullability".
@@ -1109,6 +1129,11 @@ namespace {
11091129 };
11101130}
11111131
1132+ // / Produce a flattened, numeric value for optional method/property kinds.
1133+ static unsigned flattenPropertyKind (llvm::Optional<MethodKind> kind) {
1134+ return kind ? (*kind == MethodKind::Instance ? 2 : 1 ) : 0 ;
1135+ }
1136+
11121137bool api_notes::decompileAPINotes (std::unique_ptr<llvm::MemoryBuffer> input,
11131138 llvm::raw_ostream &os) {
11141139 // Try to read the file.
@@ -1150,7 +1175,10 @@ bool api_notes::decompileAPINotes(std::unique_ptr<llvm::MemoryBuffer> input,
11501175 // Sort properties.
11511176 std::sort (record.Properties .begin (), record.Properties .end (),
11521177 [](const Property &lhs, const Property &rhs) -> bool {
1153- return lhs.Name < rhs.Name ;
1178+ return lhs.Name < rhs.Name ||
1179+ (lhs.Name == rhs.Name &&
1180+ flattenPropertyKind (lhs.Kind ) <
1181+ flattenPropertyKind (rhs.Kind ));
11541182 });
11551183
11561184 // Sort methods.
0 commit comments