-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CFI: Generate super vtables explicitly
CFI shimming means they're not gauranteed to be pre-generated. Traditionally, the base vtable has all the elements of the supertrait vtable, and so visiting the base vtable implies you don't need to visit the supertrait vtable. However, with CFI the base vtable entries will have invocation type `dyn Child`, and the parent vtable will have invocation type `dyn Parent`, so they aren't actually the same instance, and both must be visited.
- Loading branch information
Showing
2 changed files
with
81 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Check that super-traits with vptrs have their shims generated | ||
|
||
//@ needs-sanitizer-cfi | ||
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi | ||
//@ compile-flags: -C codegen-units=1 -C opt-level=0 | ||
//@ build-pass | ||
|
||
trait Parent1 { | ||
fn p1(&self); | ||
} | ||
|
||
trait Parent2 { | ||
fn p2(&self); | ||
} | ||
|
||
// We need two parent traits to force the vtable upcasting code to choose to add a pointer to | ||
// another vtable to the child. This vtable is generated even if trait upcasting is not in use. | ||
trait Child : Parent1 + Parent2 { | ||
fn c(&self); | ||
} | ||
|
||
struct Foo; | ||
|
||
impl Parent1 for Foo { | ||
fn p1(&self) {} | ||
} | ||
|
||
impl Parent2 for Foo { | ||
fn p2(&self) {} | ||
} | ||
|
||
impl Child for Foo { | ||
fn c(&self) {} | ||
} | ||
|
||
fn main() { | ||
let x = &Foo as &dyn Child; | ||
x.c(); | ||
} |