@@ -40,7 +40,12 @@ class SILProfiler;
4040enum IsBare_t { IsNotBare, IsBare };
4141enum IsTransparent_t { IsNotTransparent, IsTransparent };
4242enum Inline_t { InlineDefault, NoInline, AlwaysInline };
43- enum IsThunk_t { IsNotThunk, IsThunk, IsReabstractionThunk };
43+ enum IsThunk_t {
44+ IsNotThunk,
45+ IsThunk,
46+ IsReabstractionThunk,
47+ IsSignatureOptimizedThunk
48+ };
4449
4550class SILSpecializeAttr final {
4651 friend SILFunction;
@@ -224,6 +229,33 @@ class SILFunction
224229 // / serialization.
225230 bool WasDeserializedCanonical = false ;
226231
232+ static void
233+ validateSubclassScope (SubclassScope scope, IsThunk_t isThunk,
234+ const GenericSpecializationInformation *genericInfo) {
235+ #ifndef NDEBUG
236+ // The _original_ function for a method can turn into a thunk through
237+ // signature optimization, meaning it needs to retain its subclassScope, but
238+ // other thunks and specializations are implementation details and so
239+ // shouldn't be connected to their parent class.
240+ bool thunkCanHaveSubclassScope;
241+ switch (isThunk) {
242+ case IsNotThunk:
243+ case IsSignatureOptimizedThunk:
244+ thunkCanHaveSubclassScope = true ;
245+ break ;
246+ case IsThunk:
247+ case IsReabstractionThunk:
248+ thunkCanHaveSubclassScope = false ;
249+ break ;
250+ }
251+ auto allowsInterestingScopes = thunkCanHaveSubclassScope && !genericInfo;
252+ assert (
253+ allowsInterestingScopes ||
254+ scope == SubclassScope::NotApplicable &&
255+ " SubclassScope on specialization or non-signature-optimized thunk" );
256+ #endif
257+ }
258+
227259 SILFunction (SILModule &module , SILLinkage linkage, StringRef mangledName,
228260 CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
229261 Optional<SILLocation> loc, IsBare_t isBareSILFunction,
@@ -573,13 +605,20 @@ class SILFunction
573605
574606 // / Get this function's thunk attribute.
575607 IsThunk_t isThunk () const { return IsThunk_t (Thunk); }
576- void setThunk (IsThunk_t isThunk) { Thunk = isThunk; }
608+ void setThunk (IsThunk_t isThunk) {
609+ validateSubclassScope (getClassSubclassScope (), isThunk, SpecializationInfo);
610+ Thunk = isThunk;
611+ }
577612
578613 // / Get the class visibility (relevant for class methods).
579614 SubclassScope getClassSubclassScope () const {
580615 return SubclassScope (ClassSubclassScope);
581616 }
582-
617+ void setClassSubclassScope (SubclassScope scope) {
618+ validateSubclassScope (scope, isThunk (), SpecializationInfo);
619+ ClassSubclassScope = static_cast <unsigned >(scope);
620+ }
621+
583622 // / Get this function's noinline attribute.
584623 Inline_t getInlineStrategy () const { return Inline_t (InlineStrategy); }
585624 void setInlineStrategy (Inline_t inStr) { InlineStrategy = inStr; }
@@ -655,6 +694,7 @@ class SILFunction
655694
656695 void setSpecializationInfo (const GenericSpecializationInformation *Info) {
657696 assert (!isSpecialization ());
697+ validateSubclassScope (getClassSubclassScope (), isThunk (), Info);
658698 SpecializationInfo = Info;
659699 }
660700
0 commit comments