Skip to content

Commit 470b7ca

Browse files
committed
---
yaml --- r: 344943 b: refs/heads/master c: 2125f7f h: refs/heads/master i: 344941: 9b30281 344939: f268d1e 344935: 86d6048 344927: 4f6b4cf
1 parent b853d07 commit 470b7ca

File tree

12 files changed

+212
-95
lines changed

12 files changed

+212
-95
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 1813ecb85e36a98b71e3c32fc07344a32455d764
2+
refs/heads/master: 2125f7ffc5573359bc13e9365aefefb31a88ee4a
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/Builtins.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,11 @@ BUILTIN_SIL_OPERATION(AllocWithTailElems, "allocWithTailElems", Special)
390390
/// Projects the first tail-allocated element of type E from a class C.
391391
BUILTIN_SIL_OPERATION(ProjectTailElems, "projectTailElems", Special)
392392

393+
/// identityKeyPath : <T> () -> WritableKeyPath<T, T>
394+
///
395+
/// Creates an identity key path object. (TODO: replace with proper syntax)
396+
BUILTIN_SIL_OPERATION(IdentityKeyPath, "identityKeyPath", Special)
397+
393398
#undef BUILTIN_SIL_OPERATION
394399

395400
// BUILTIN_RUNTIME_CALL - A call into a runtime function.

trunk/include/swift/AST/DiagnosticsParse.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,6 @@ ERROR(sil_keypath_computed_property_missing_part,none,
583583
ERROR(sil_keypath_external_missing_part,none,
584584
"keypath external component with indices needs an indices_equals and "
585585
"indices_hash function", ())
586-
ERROR(sil_keypath_no_components,none,
587-
"keypath must have at least one component", ())
588586
ERROR(sil_keypath_no_root,none,
589587
"keypath must have a root component declared",())
590588
ERROR(sil_keypath_index_not_hashable,none,

trunk/lib/AST/Builtins.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,20 @@ makeTuple(const Gs & ...elementGenerators) {
556556
};
557557
}
558558

559+
template <class... Gs>
560+
static BuiltinGenericSignatureBuilder::LambdaGenerator
561+
makeBoundGenericType(NominalTypeDecl *decl,
562+
const Gs & ...argumentGenerators) {
563+
return {
564+
[=](BuiltinGenericSignatureBuilder &builder) -> Type {
565+
Type args[] = {
566+
argumentGenerators.build(builder)...
567+
};
568+
return BoundGenericType::get(decl, Type(), args);
569+
}
570+
};
571+
}
572+
559573
template <class T>
560574
static BuiltinGenericSignatureBuilder::MetatypeGenerator<T>
561575
makeMetatype(const T &object, Optional<MetatypeRepresentation> repr = None) {
@@ -972,6 +986,15 @@ static ValueDecl *getTypeJoinMetaOperation(ASTContext &Context, Identifier Id) {
972986
return builder.build(Id);
973987
}
974988

989+
static ValueDecl *getIdentityKeyPathOperation(ASTContext &Context,
990+
Identifier Id) {
991+
BuiltinGenericSignatureBuilder builder(Context, 1);
992+
auto arg = makeGenericParam();
993+
builder.setResult(makeBoundGenericType(Context.getWritableKeyPathDecl(),
994+
arg, arg));
995+
return builder.build(Id);
996+
}
997+
975998
static ValueDecl *getCanBeObjCClassOperation(ASTContext &Context,
976999
Identifier Id) {
9771000
// <T> T.Type -> Builtin.Int8
@@ -1865,6 +1888,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
18651888

18661889
case BuiltinValueKind::TypeJoinMeta:
18671890
return getTypeJoinMetaOperation(Context, Id);
1891+
1892+
case BuiltinValueKind::IdentityKeyPath:
1893+
return getIdentityKeyPathOperation(Context, Id);
18681894
}
18691895

18701896
llvm_unreachable("bad builtin value!");

trunk/lib/ParseSIL/ParseSIL.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2884,8 +2884,6 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
28842884
return true;
28852885
}
28862886

2887-
if (components.empty())
2888-
P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_components);
28892887
if (rootType.isNull())
28902888
P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_root);
28912889

@@ -2943,8 +2941,13 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
29432941
if (patternEnv && patternEnv->getGenericSignature()) {
29442942
canSig = patternEnv->getGenericSignature()->getCanonicalSignature();
29452943
}
2944+
CanType leafType;
2945+
if (!components.empty())
2946+
leafType = components.back().getComponentType();
2947+
else
2948+
leafType = rootType;
29462949
auto pattern = KeyPathPattern::get(B.getModule(), canSig,
2947-
rootType, components.back().getComponentType(),
2950+
rootType, leafType,
29482951
components, objcString);
29492952

29502953
ResultVal = B.createKeyPath(InstLoc, pattern, subMap, operands, Ty);

trunk/lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,56 +1288,14 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Swift3ImplicitObjCEntrypoint)
12881288

12891289
// Builtins that should be lowered to SIL instructions so we should never see
12901290
// them.
1291-
#define BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ID) \
1291+
#define BUILTIN_SIL_OPERATION(ID, NAME, CATEGORY) \
12921292
OwnershipUseCheckerResult \
12931293
OwnershipCompatibilityBuiltinUseChecker::visit##ID(BuiltinInst *BI, \
12941294
StringRef Attr) { \
12951295
llvm_unreachable("Builtin should have been lowered to SIL instruction?!"); \
12961296
}
1297-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Retain)
1298-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Release)
1299-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Autorelease)
1300-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(TryPin)
1301-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Unpin)
1302-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Load)
1303-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadRaw)
1304-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadInvariant)
1305-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Take)
1306-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Destroy)
1307-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Assign)
1308-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Init)
1309-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastToNativeObject)
1310-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(UnsafeCastToNativeObject)
1311-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastFromNativeObject)
1312-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastToBridgeObject)
1313-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(
1314-
CastReferenceFromBridgeObject)
1315-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(
1316-
CastBitPatternFromBridgeObject)
1317-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ClassifyBridgeObject)
1318-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ValueToBridgeObject)
1319-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BridgeToRawPointer)
1320-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BridgeFromRawPointer)
1321-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastReference)
1322-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ReinterpretCast)
1323-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AddressOf)
1324-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AddressOfBorrow)
1325-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GepRaw)
1326-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Gep)
1327-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GetTailAddr)
1328-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(PerformInstantaneousReadAccess)
1329-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BeginUnpairedModifyAccess)
1330-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(EndUnpairedAccess)
1331-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CondFail)
1332-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(FixLifetime)
1333-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUnique)
1334-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUniqueOrPinned)
1335-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUnique_native)
1336-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUniqueOrPinned_native)
1337-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BindMemory)
1338-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AllocWithTailElems)
1339-
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ProjectTailElems)
1340-
#undef BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS
1297+
#define BUILTIN(X, Y, Z)
1298+
#include "swift/AST/Builtins.def"
13411299

13421300
OwnershipUseCheckerResult
13431301
OwnershipCompatibilityUseChecker::visitBuiltinInst(BuiltinInst *BI) {

trunk/lib/SIL/ValueOwnershipKindClassifier.cpp

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,6 @@ struct ValueOwnershipKindBuiltinVisitor
397397
} \
398398
return ValueOwnershipKind::OWNERSHIP; \
399399
}
400-
CONSTANT_OWNERSHIP_BUILTIN(Owned, Take)
401-
CONSTANT_OWNERSHIP_BUILTIN(Owned, TryPin)
402400
// This returns a value at +1 that is destroyed strictly /after/ the
403401
// UnsafeGuaranteedEnd. This provides the guarantee that we want.
404402
CONSTANT_OWNERSHIP_BUILTIN(Owned, UnsafeGuaranteed)
@@ -443,9 +441,6 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, ICMP_ULE)
443441
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ICMP_ULT)
444442
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IntToPtr)
445443
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LShr)
446-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Load)
447-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadRaw)
448-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadInvariant)
449444
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Mul)
450445
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Or)
451446
CONSTANT_OWNERSHIP_BUILTIN(Trivial, PtrToInt)
@@ -472,32 +467,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, ZExt)
472467
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ZExtOrBitCast)
473468
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FCMP_ORD)
474469
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FCMP_UNO)
475-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastToNativeObject)
476-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, UnsafeCastToNativeObject)
477-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastFromNativeObject)
478-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastToBridgeObject)
479-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastReferenceFromBridgeObject)
480-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, CastBitPatternFromBridgeObject)
481-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ClassifyBridgeObject)
482-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BridgeToRawPointer)
483-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, BridgeFromRawPointer)
484-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastReference)
485-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AddressOf)
486-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AddressOfBorrow)
487-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GepRaw)
488-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Gep)
489-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GetTailAddr)
490-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, PerformInstantaneousReadAccess)
491-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BeginUnpairedModifyAccess)
492-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, EndUnpairedAccess)
493470
CONSTANT_OWNERSHIP_BUILTIN(Trivial, OnFastPath)
494-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUnique)
495-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUniqueOrPinned)
496-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUnique_native)
497-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUniqueOrPinned_native)
498-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BindMemory)
499-
CONSTANT_OWNERSHIP_BUILTIN(Owned, AllocWithTailElems)
500-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ProjectTailElems)
501471
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsOptionalType)
502472
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Sizeof)
503473
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Strideof)
@@ -543,21 +513,11 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, UnexpectedError)
543513
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ErrorInMain)
544514
CONSTANT_OWNERSHIP_BUILTIN(Trivial, DeallocRaw)
545515
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Fence)
546-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Retain)
547-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Release)
548-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, CondFail)
549-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FixLifetime)
550-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Autorelease)
551-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Unpin)
552-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Destroy)
553-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Assign)
554-
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Init)
555516
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AtomicStore)
556517
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Once)
557518
CONSTANT_OWNERSHIP_BUILTIN(Trivial, OnceWithContext)
558519
CONSTANT_OWNERSHIP_BUILTIN(Trivial, TSanInoutAccess)
559520
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Swift3ImplicitObjCEntrypoint)
560-
CONSTANT_OWNERSHIP_BUILTIN(Unowned, ValueToBridgeObject)
561521

562522
#undef CONSTANT_OWNERSHIP_BUILTIN
563523

@@ -570,14 +530,22 @@ CONSTANT_OWNERSHIP_BUILTIN(Unowned, ValueToBridgeObject)
570530
} \
571531
return ValueOwnershipKind::Unowned; \
572532
}
573-
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ReinterpretCast)
574533
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(CmpXChg)
575534
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(AtomicLoad)
576535
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ExtractElement)
577536
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(InsertElement)
578537
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ZeroInitializer)
579538
#undef UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT
580539

540+
#define BUILTIN(X,Y,Z)
541+
#define BUILTIN_SIL_OPERATION(ID, NAME, CATEGORY) \
542+
ValueOwnershipKind ValueOwnershipKindBuiltinVisitor::visit##ID( \
543+
BuiltinInst *BI, StringRef Attr) { \
544+
llvm_unreachable("builtin should have been lowered in SILGen"); \
545+
}
546+
547+
#include "swift/AST/Builtins.def"
548+
581549
ValueOwnershipKind
582550
ValueOwnershipKindClassifier::visitBuiltinInst(BuiltinInst *BI) {
583551
// For now, just conservatively say builtins are None. We need to use a

trunk/lib/SILGen/SILGenBuiltin.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ASTContext.h"
2222
#include "swift/AST/Builtins.h"
2323
#include "swift/AST/DiagnosticsSIL.h"
24+
#include "swift/AST/GenericEnvironment.h"
2425
#include "swift/AST/Module.h"
2526
#include "swift/AST/ReferenceCounting.h"
2627
#include "swift/SIL/SILArgument.h"
@@ -1055,6 +1056,58 @@ static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
10551056
return ManagedValue::forUnmanaged(result);
10561057
}
10571058

1059+
static ManagedValue emitBuiltinIdentityKeyPath(SILGenFunction &SGF,
1060+
SILLocation loc,
1061+
SubstitutionMap subs,
1062+
ArrayRef<ManagedValue> args,
1063+
SGFContext C) {
1064+
assert(subs.getReplacementTypes().size() == 1 &&
1065+
"identityKeyPath should have one substitution");
1066+
assert(args.size() == 0 &&
1067+
"identityKeyPath should have no args");
1068+
1069+
auto identityTy = subs.getReplacementTypes()[0]->getCanonicalType();
1070+
1071+
// The `self` key can be used for identity in Cocoa KVC as well.
1072+
StringRef objcString = SGF.getASTContext().LangOpts.EnableObjCInterop
1073+
? "self" : "";
1074+
1075+
// The key path pattern has to capture some generic context if the type is
1076+
// dependent on this generic context. We only need the specific type, though,
1077+
// not the entire generic environment.
1078+
bool isDependent = identityTy->hasArchetype();
1079+
CanType identityPatternTy = identityTy;
1080+
CanGenericSignature patternSig = nullptr;
1081+
SubstitutionMap patternSubs;
1082+
if (isDependent) {
1083+
auto param = GenericTypeParamType::get(0, 0, SGF.getASTContext());
1084+
identityPatternTy = param->getCanonicalType();
1085+
patternSig = GenericSignature::get(param, {})->getCanonicalSignature();
1086+
patternSubs = SubstitutionMap::get(patternSig,
1087+
llvm::makeArrayRef((Type)identityTy),
1088+
{});
1089+
}
1090+
1091+
auto identityPattern = KeyPathPattern::get(SGF.SGM.M,
1092+
patternSig,
1093+
identityPatternTy,
1094+
identityPatternTy,
1095+
{},
1096+
objcString);
1097+
1098+
auto kpTy = BoundGenericType::get(SGF.getASTContext().getWritableKeyPathDecl(),
1099+
Type(),
1100+
{identityTy, identityTy})
1101+
->getCanonicalType();
1102+
1103+
auto keyPath = SGF.B.createKeyPath(loc, identityPattern,
1104+
patternSubs,
1105+
{},
1106+
SILType::getPrimitiveObjectType(kpTy));
1107+
return SGF.emitManagedRValueWithCleanup(keyPath);
1108+
}
1109+
1110+
10581111
/// Specialized emitter for type traits.
10591112
template<TypeTraitResult (TypeBase::*Trait)(),
10601113
BuiltinValueKind Kind>

0 commit comments

Comments
 (0)