Skip to content

Commit 6b19f27

Browse files
jrose-appletkremenek
authored andcommitted
Fix "Undefined symbol" linker error with default argument for inherited initializer (#7171)
* [SILGen] Don't crash when calling a generic init with default args. (#7169) In cases where a default value is used for a parameter with generic type, the argument list might be empty. In that case, we don't need to emit any arguments! * Fix ParameterList::clone to handle deserialized defaults arguments. (#7156) It was checking the wrong predicate, and therefore failing to mark inherited default arguments as actually being inherited. While here, explicitly clear out default arguments from non-inherited cloned parameter lists. I don't think this case can come up today, but it's better to be correct when we do hit it. rdar://problem/30167924
1 parent a42cee9 commit 6b19f27

File tree

5 files changed

+97
-8
lines changed

5 files changed

+97
-8
lines changed

lib/AST/Parameter.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ ParameterList *ParameterList::clone(const ASTContext &C,
8888

8989
// Remap the ParamDecls inside of the ParameterList.
9090
for (auto &decl : params) {
91-
bool hadDefaultArgument =decl->getDefaultValue() != nullptr;
91+
bool hadDefaultArgument =
92+
decl->getDefaultArgumentKind() == DefaultArgumentKind::Normal;
9293

9394
decl = new (C) ParamDecl(decl);
9495
if (options & Implicit)
@@ -101,8 +102,12 @@ ParameterList *ParameterList::clone(const ASTContext &C,
101102
decl->setName(C.getIdentifier("argument"));
102103

103104
// If we're inheriting a default argument, mark it as such.
104-
if (hadDefaultArgument && (options & Inherited)) {
105-
decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
105+
// FIXME: Figure out how to clone default arguments as well.
106+
if (hadDefaultArgument) {
107+
if (options & Inherited)
108+
decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
109+
else
110+
decl->setDefaultArgumentKind(DefaultArgumentKind::None);
106111
}
107112
}
108113

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3662,11 +3662,13 @@ void ArgEmitter::emitShuffle(Expr *inner,
36623662
// Emit the inner expression.
36633663
SmallVector<ManagedValue, 8> innerArgs;
36643664
SmallVector<InOutArgument, 2> innerInOutArgs;
3665-
ArgEmitter(SGF, Rep, ClaimedParamsRef(innerParams), innerArgs, innerInOutArgs,
3666-
/*foreign error*/ None, /*foreign self*/ ImportAsMemberStatus(),
3667-
(innerSpecialDests ? ArgSpecialDestArray(*innerSpecialDests)
3668-
: Optional<ArgSpecialDestArray>()))
3669-
.emitTopLevel(ArgumentSource(inner), innerOrigParamType);
3665+
if (!innerParams.empty()) {
3666+
ArgEmitter(SGF, Rep, ClaimedParamsRef(innerParams), innerArgs, innerInOutArgs,
3667+
/*foreign error*/ None, /*foreign self*/ ImportAsMemberStatus(),
3668+
(innerSpecialDests ? ArgSpecialDestArray(*innerSpecialDests)
3669+
: Optional<ArgSpecialDestArray>()))
3670+
.emitTopLevel(ArgumentSource(inner), innerOrigParamType);
3671+
}
36703672

36713673
// Make a second pass to split the inner arguments correctly.
36723674
{

test/SILGen/default_arguments_generic.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,21 @@ func bar() {
2828
// CHECK: apply [[ZANG_DFLT_1]]<Int, Double>
2929
Zim<Int>.zang(Double.self, 22)
3030
}
31+
32+
protocol Initializable {
33+
init()
34+
}
35+
struct Generic<T: Initializable> {
36+
init(_ value: T = T()) {}
37+
}
38+
struct InitializableImpl: Initializable {
39+
init() {}
40+
}
41+
// CHECK-LABEL: sil hidden @_TF25default_arguments_generic17testInitializableFT_T_
42+
func testInitializable() {
43+
// The ".init" is required to trigger the crash that used to happen.
44+
_ = Generic<InitializableImpl>.init()
45+
// CHECK: [[INIT:%.+]] = function_ref @_TFV25default_arguments_generic7GenericCfxGS0_x_
46+
// CHECK: function_ref @_TIFV25default_arguments_generic7GenericcFxGS0_x_A_ : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> @out τ_0_0
47+
// CHECK: apply [[INIT]]<InitializableImpl>({{%.+}}, {{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @thin Generic<τ_0_0>.Type) -> Generic<τ_0_0>
48+
} // CHECK: end sil function '_TF25default_arguments_generic17testInitializableFT_T_'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
open class Base {
2+
public init(_ value: Int = 0) {}
3+
}
4+
5+
public protocol Initializable {
6+
init()
7+
}
8+
open class GenericBase<T: Initializable> {
9+
public init(_ value: T = T()) {}
10+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
// RUN: %target-swift-frontend -emit-module -o %t -module-name InheritedInitializerBase %S/Inputs/inherited-initializer-base.swift
3+
// RUN: %target-swift-frontend -emit-silgen -I %t %s | %FileCheck %s
4+
5+
import InheritedInitializerBase
6+
7+
class InheritsInit : Base {}
8+
9+
// CHECK-LABEL: sil hidden @_TF4main10testSimpleFT_T_
10+
func testSimple() {
11+
// CHECK: [[INIT:%.+]] = function_ref @_TFC4main12InheritsInitCfSiS0_
12+
// CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase4BasecFSiS0_A_
13+
// CHECK: [[ARG:%.+]] = apply [[DEFAULT]]()
14+
// CHECK: apply [[INIT]]([[ARG]], {{%.+}})
15+
_ = InheritsInit()
16+
17+
// CHECK: [[INIT:%.+]] = function_ref @_TFC4main12InheritsInitCfSiS0_
18+
// CHECK: [[VALUE:%.+]] = integer_literal $Builtin.Int2048, 5
19+
// CHECK: [[ARG:%.+]] = apply {{%.+}}([[VALUE]], {{%.+}}) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
20+
// CHECK: apply [[INIT]]([[ARG]], {{%.+}})
21+
_ = InheritsInit(5)
22+
} // CHECK: end sil function '_TF4main10testSimpleFT_T_'
23+
24+
struct Reinitializable<T>: Initializable {
25+
init() {}
26+
}
27+
28+
class GenericSub<T: Initializable> : GenericBase<T> {}
29+
class ModifiedGenericSub<U> : GenericBase<Reinitializable<U>> {}
30+
class NonGenericSub : GenericBase<Reinitializable<Int>> {}
31+
32+
// CHECK-LABEL: sil hidden @_TF4main11testGenericFT_T_
33+
func testGeneric() {
34+
// CHECK: [[INIT:%.+]] = function_ref @_TFC4main10GenericSubCfxGS0_x_
35+
// CHECK: [[TYPE:%.+]] = metatype $@thick GenericSub<Reinitializable<Int8>>.Type
36+
// CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
37+
// CHECK: apply [[DEFAULT]]<Reinitializable<Int8>>({{%.+}})
38+
// CHECK: apply [[INIT]]<Reinitializable<Int8>>({{%.+}}, [[TYPE]])
39+
_ = GenericSub<Reinitializable<Int8>>.init() // works around SR-3806
40+
41+
// CHECK: [[INIT:%.+]] = function_ref @_TFC4main18ModifiedGenericSubCfGVS_15Reinitializablex_GS0_x_
42+
// CHECK: [[TYPE:%.+]] = metatype $@thick ModifiedGenericSub<Int16>.Type
43+
// CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
44+
// CHECK: apply [[DEFAULT]]<Reinitializable<Int16>>({{%.+}})
45+
// CHECK: apply [[INIT]]<Int16>({{%.+}}, [[TYPE]])
46+
_ = ModifiedGenericSub<Int16>()
47+
48+
// CHECK: [[INIT:%.+]] = function_ref @_TFC4main13NonGenericSubCfGVS_15ReinitializableSi_S0_
49+
// CHECK: [[TYPE:%.+]] = metatype $@thick NonGenericSub.Type
50+
// CHECK: [[DEFAULT:%.+]] = function_ref @_TIFC24InheritedInitializerBase11GenericBasecFxGS0_x_A_
51+
// CHECK: apply [[DEFAULT]]<Reinitializable<Int>>({{%.+}})
52+
// CHECK: apply [[INIT]]({{%.+}}, [[TYPE]])
53+
_ = NonGenericSub()
54+
} // CHECK: end sil function '_TF4main11testGenericFT_T_'

0 commit comments

Comments
 (0)