Merge pull request #7533 from adrian-prantl/30520286
Fix a bug in GenericCloner causing an LLVM assertion
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index cd344f0..f4afe92 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1789,6 +1789,12 @@
continue;
}
+ // Look through covariant return expressions.
+ if (auto covariantExpr
+ = dyn_cast<CovariantReturnConversionExpr>(candidate)) {
+ candidate = covariantExpr->getSubExpr();
+ continue;
+ }
break;
}
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 7b1cfe4..5f836c3 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2724,9 +2724,12 @@
auto member = Impl.importDecl(nd, getActiveSwiftVersion());
if (!member) {
- // We don't know what this field is. Assume it may be important in C.
- hasUnreferenceableStorage = true;
- hasMemberwiseInitializer = false;
+ if (!isa<clang::TypeDecl>(nd)) {
+ // We don't know what this field is.
+ // Assume it may be important in C.
+ hasUnreferenceableStorage = true;
+ hasMemberwiseInitializer = false;
+ }
continue;
}
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 1f37744..631a1ea 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -473,11 +473,19 @@
v.getCleanup());
}
- // Upcast to a superclass.
- return ManagedValue(SGF.B.createUpcast(Loc,
- v.getValue(),
- loweredResultTy),
- v.getCleanup());
+ if (outputSubstType->isExactSuperclassOf(inputSubstType, nullptr)) {
+ // Upcast to a superclass.
+ return ManagedValue(SGF.B.createUpcast(Loc,
+ v.getValue(),
+ loweredResultTy),
+ v.getCleanup());
+ } else {
+ // Unchecked-downcast to a covariant return type.
+ assert(inputSubstType->isExactSuperclassOf(outputSubstType, nullptr)
+ && "should be inheritance relationship between input and output");
+ return SGF.emitManagedRValueWithCleanup(
+ SGF.B.createUncheckedRefCast(Loc, v.forward(SGF), loweredResultTy));
+ }
}
// - upcasts from an archetype
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
index 388644d..294654c 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
@@ -1129,8 +1129,13 @@
LocExpr = TE->getSubExpr();
else if (auto *FVE = dyn_cast<ForceValueExpr>(LocExpr))
LocExpr = FVE->getSubExpr();
- }
+
+ }
+ // Look through covariant return, if any.
+ if (auto CRE = dyn_cast<CovariantReturnConversionExpr>(LocExpr))
+ LocExpr = CRE->getSubExpr();
+
// This is a self.init call if structured like this:
//
// (call_expr type='SomeClass'
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 17839e6..2c17be6 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -1378,7 +1378,8 @@
/// \brief Build a new reference to another constructor.
Expr *buildOtherConstructorRef(Type openedFullType,
- ConstructorDecl *ctor, DeclNameLoc loc,
+ ConstructorDecl *ctor, Expr *base,
+ DeclNameLoc loc,
ConstraintLocatorBuilder locator,
bool implicit) {
auto &tc = cs.getTypeChecker();
@@ -1416,8 +1417,21 @@
resultFnTy->getExtInfo());
// Build the constructor reference.
- return cs.cacheType(
+ Expr *ctorRef = cs.cacheType(
new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTy));
+
+ // Wrap in covariant `Self` return if needed.
+ if (selfTy->hasReferenceSemantics()) {
+ auto covariantTy = resultTy
+ ->replaceCovariantResultType(base->getType()
+ ->getLValueOrInOutObjectType(),
+ ctor->getNumParameterLists());
+ if (!covariantTy->isEqual(resultTy))
+ ctorRef = cs.cacheType(
+ new (ctx) CovariantFunctionConversionExpr(ctorRef, covariantTy));
+ }
+
+ return ctorRef;
}
/// Bridge the given value (which is an error type) to NSError.
@@ -2452,7 +2466,7 @@
}
// Build a partial application of the delegated initializer.
- Expr *ctorRef = buildOtherConstructorRef(openedType, ctor, nameLoc,
+ Expr *ctorRef = buildOtherConstructorRef(openedType, ctor, base, nameLoc,
ctorLocator, implicit);
auto *call = new (cs.getASTContext()) DotSyntaxCallExpr(ctorRef, dotLoc,
base);
diff --git a/test/ClangImporter/ctypes_parse.swift b/test/ClangImporter/ctypes_parse.swift
index 5a1c06c..eac83eb 100644
--- a/test/ClangImporter/ctypes_parse.swift
+++ b/test/ClangImporter/ctypes_parse.swift
@@ -235,3 +235,9 @@
}
hasVaList(nil) // expected-error {{nil is not compatible with expected argument type 'CVaListPointer'}}
}
+
+func testNestedForwardDeclaredStructs() {
+ // Check that we still have a memberwise initializer despite the forward-
+ // declared nested type. rdar://problem/30449400
+ _ = StructWithForwardDeclaredStruct(ptr: nil)
+}
diff --git a/test/Inputs/clang-importer-sdk/usr/include/ctypes.h b/test/Inputs/clang-importer-sdk/usr/include/ctypes.h
index d79aebb..758739b 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/ctypes.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/ctypes.h
@@ -123,6 +123,10 @@
double y;
};
+struct StructWithForwardDeclaredStruct {
+ struct ForwardDeclaredStruct *ptr;
+};
+
//===---
// Typedefs.
//===---
diff --git a/test/SILGen/witness-init-requirement-with-base-class-init.swift b/test/SILGen/witness-init-requirement-with-base-class-init.swift
new file mode 100644
index 0000000..cfd3176
--- /dev/null
+++ b/test/SILGen/witness-init-requirement-with-base-class-init.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-sil -verify %s
+
+protocol BestFriend: class {
+ init()
+ static func create() -> Self
+}
+
+class Animal {
+ required init(species: String) {}
+
+ static func create() -> Self { return self.init() }
+ required convenience init() { self.init(species: "\(type(of: self))") }
+}
+
+class Dog: Animal, BestFriend {}
+// CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC4main3DogS_10BestFriendS_FS1_CfT_x
+// CHECK: [[SELF:%.*]] = apply
+// CHECK: unchecked_ref_cast [[SELF]] : $Animal to $Dog
+// CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC4main3DogS_10BestFriendS_ZFS1_6createfT_x
+// CHECK: [[SELF:%.*]] = apply
+// CHECK: unchecked_ref_cast [[SELF]] : $Animal to $Dog
diff --git a/test/decl/init/Inputs/c-func-member-init.h b/test/decl/init/Inputs/c-func-member-init.h
new file mode 100644
index 0000000..431b7c8
--- /dev/null
+++ b/test/decl/init/Inputs/c-func-member-init.h
@@ -0,0 +1,6 @@
+__attribute__((objc_root_class))
+@interface MyObject
+@end
+
+__attribute__((swift_name("MyObject.init(id:)")))
+MyObject *_Nonnull my_object_create(int id);
diff --git a/test/decl/init/delegate-to-c-func-imported-as-member.swift b/test/decl/init/delegate-to-c-func-imported-as-member.swift
new file mode 100644
index 0000000..922c32f
--- /dev/null
+++ b/test/decl/init/delegate-to-c-func-imported-as-member.swift
@@ -0,0 +1,8 @@
+// RUN: %target-swift-frontend -emit-sil -verify -import-objc-header %S/Inputs/c-func-member-init.h %s
+// REQUIRES: objc_interop
+
+extension MyObject {
+ convenience init() {
+ self.init(id: 1738)
+ }
+}
diff --git a/test/decl/init/nonnull-delegate-to-nullable-in-base-class.swift b/test/decl/init/nonnull-delegate-to-nullable-in-base-class.swift
new file mode 100644
index 0000000..bd399a7
--- /dev/null
+++ b/test/decl/init/nonnull-delegate-to-nullable-in-base-class.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -emit-sil -verify %s
+
+class Animal {
+ convenience init?(species: String) {
+ self.init()
+ }
+}
+
+class Dog: Animal {
+ var butt = "dog \("butt")"
+
+ convenience init(owner: String) {
+ self.init(species: "Dog")!
+ }
+
+
+}
+
+print(Dog(owner: "John Arbuckle").butt)
+