Skip to content

Commit 97e454d

Browse files
committed
Diagnose a conflicting silgen_name/extern(c) name instead of asserting/crashing
1 parent bf50e2f commit 97e454d

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ ERROR(unsupported_variadic_function_abstraction,none,
121121
"convention; try wrapping it in a struct",
122122
(Type))
123123

124+
ERROR(function_type_mismatch,none,
125+
"function type mismatch, declared as %0 but used as %1", (Type, Type))
126+
NOTE(function_declared_here,none,
127+
"function declared here", ())
128+
124129
// Capture before declaration diagnostics.
125130
ERROR(capture_before_declaration,none,
126131
"closure captures %0 before it is declared", (Identifier))

lib/SILGen/SILGenThunk.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,22 @@ SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant,
163163
}
164164

165165
auto f = SGM.getFunction(constant, NotForDefinition);
166-
#ifndef NDEBUG
166+
167167
auto constantFnTypeInContext =
168-
SGM.Types.getLoweredType(constantInfo.SILFnType,
169-
B.getTypeExpansionContext())
170-
.castTo<SILFunctionType>();
171-
assert(f->getLoweredFunctionTypeInContext(B.getTypeExpansionContext())
172-
== constantFnTypeInContext);
173-
#endif
168+
SGM.Types
169+
.getLoweredType(constantInfo.SILFnType, B.getTypeExpansionContext())
170+
.castTo<SILFunctionType>();
171+
auto existingType =
172+
f->getLoweredFunctionTypeInContext(B.getTypeExpansionContext());
173+
if (existingType != constantFnTypeInContext) {
174+
// This can happen for example when using @_silgen_name or @_extern(c)
175+
// attributes
176+
SGM.diagnose(loc.getSourceLoc(), diag::function_type_mismatch, existingType,
177+
constantFnTypeInContext);
178+
SGM.diagnose(f->getLocation().getSourceLoc(), diag::function_declared_here);
179+
return SILUndef::get(constantInfo.getSILType(), F);
180+
}
181+
174182
if (callPreviousDynamicReplaceableImpl)
175183
return B.createPreviousDynamicFunctionRef(loc, f);
176184
else
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-emit-silgen %s -enable-experimental-feature Extern -verify
2+
3+
@_silgen_name("my_extern_func")
4+
func my_extern_func1() // expected-note {{function declared here}}
5+
6+
@_silgen_name("my_extern_func")
7+
func my_extern_func2(x: Int)
8+
9+
@_extern(c, "my_other_extern_func")
10+
func my_other_extern_func1() // expected-note {{function declared here}}
11+
12+
@_extern(c, "my_other_extern_func")
13+
func my_other_extern_func2(x: Int)
14+
15+
public func foo() {
16+
my_extern_func1()
17+
my_extern_func2(x: 42) // expected-error {{function type mismatch, declared as '@convention(thin) () -> ()' but used as '@convention(thin) (Int) -> ()'}}
18+
19+
my_other_extern_func1()
20+
my_other_extern_func2(x: 42) // expected-error {{function type mismatch, declared as '@convention(c) () -> ()' but used as '@convention(c) (Int) -> ()'}}
21+
}

0 commit comments

Comments
 (0)