Skip to content

Commit 965a2d1

Browse files
authored
Merge pull request #19025 from jckarter/verify-class-method-inst
[SIL] Verify that the method referenced in {Class,Super}MethodInsts appears in the class vtable.
2 parents f50ddf9 + a0fced4 commit 965a2d1

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

lib/SIL/SILVerifier.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/SIL/SILModule.h"
3434
#include "swift/SIL/SILOpenedArchetypesTracker.h"
3535
#include "swift/SIL/SILVTable.h"
36+
#include "swift/SIL/SILVTableVisitor.h"
3637
#include "swift/SIL/SILVisitor.h"
3738
#include "swift/SIL/BasicBlockUtils.h"
3839
#include "swift/SIL/TypeLowering.h"
@@ -2554,7 +2555,56 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25542555
F.getASTContext());
25552556
return SILType::getPrimitiveObjectType(fnTy);
25562557
}
2557-
2558+
2559+
/// Visitor class that checks whether a given decl ref has an entry in the
2560+
/// class's vtable.
2561+
class VerifyClassMethodVisitor
2562+
: public SILVTableVisitor<VerifyClassMethodVisitor>
2563+
{
2564+
public:
2565+
SILDeclRef MethodToSee;
2566+
bool Seen = false;
2567+
2568+
VerifyClassMethodVisitor(ClassDecl *theClass,
2569+
SILDeclRef method)
2570+
: MethodToSee(method)
2571+
{
2572+
addVTableEntries(theClass);
2573+
}
2574+
2575+
bool methodMatches(SILDeclRef method) {
2576+
auto methodToCheck = MethodToSee;
2577+
do {
2578+
if (method == methodToCheck) {
2579+
return true;
2580+
}
2581+
} while ((methodToCheck = methodToCheck.getNextOverriddenVTableEntry()));
2582+
2583+
return false;
2584+
}
2585+
2586+
void addMethod(SILDeclRef method) {
2587+
if (Seen)
2588+
return;
2589+
if (methodMatches(method))
2590+
Seen = true;
2591+
}
2592+
2593+
void addMethodOverride(SILDeclRef base, SILDeclRef derived) {
2594+
if (Seen)
2595+
return;
2596+
// The derived method should already have been checked.
2597+
// Test against the overridden base.
2598+
if (methodMatches(base))
2599+
Seen = true;
2600+
}
2601+
2602+
2603+
void addPlaceholder(MissingMemberDecl *) {
2604+
/* no-op */
2605+
}
2606+
};
2607+
25582608
void checkClassMethodInst(ClassMethodInst *CMI) {
25592609
auto member = CMI->getMember();
25602610
auto overrideTy = TC.getConstantOverrideType(member);
@@ -2577,6 +2627,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25772627
"foreign method cannot be dispatched natively");
25782628
require(!isa<ExtensionDecl>(member.getDecl()->getDeclContext()),
25792629
"extension method cannot be dispatched natively");
2630+
2631+
// The method ought to appear in the class vtable.
2632+
require(VerifyClassMethodVisitor(
2633+
operandType.getASTType()->getMetatypeInstanceType()
2634+
->getClassOrBoundGenericClass(),
2635+
member).Seen,
2636+
"method does not appear in the class's vtable");
25802637
}
25812638

25822639
void checkSuperMethodInst(SuperMethodInst *CMI) {
@@ -2607,6 +2664,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
26072664

26082665
require(methodClass->getClassOrBoundGenericClass(),
26092666
"super_method must look up a class method");
2667+
2668+
// The method ought to appear in the class vtable.
2669+
require(VerifyClassMethodVisitor(
2670+
operandType.getASTType()->getMetatypeInstanceType()
2671+
->getClassOrBoundGenericClass(),
2672+
member).Seen,
2673+
"method does not appear in the class's vtable");
26102674
}
26112675

26122676
void checkObjCMethodInst(ObjCMethodInst *OMI) {

test/SIL/Parser/undef.sil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ class C {
1313
@objc func fn() { }
1414
}
1515

16-
class D : C, P, ClassP { }
16+
class D : C, P, ClassP {
17+
override func fn() { }
18+
}
1719

1820
struct S {
1921
let x : ()

test/SIL/ownership-verifier/use_verifier.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct TupleContainingNonTrivialStruct {
5555

5656
class SuperKlass {
5757
func d() {}
58-
static func f() {}
58+
class func f() {}
5959
}
6060
class SubKlass : SuperKlass {}
6161
class X {

0 commit comments

Comments
 (0)