-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MS ABI: Bad this adjustment for virtual methods in a diamond virtual inheritance hierarchy #19341
Comments
assigned to @timurrrr |
This was reduced from your best friend and mine, RenderWidgetHostView in Chromium. |
We're missing an adjusting thunk for foo in the the vftable for A in D. |
This isn't going to be an easy fix. Timur, can you take a look at it? I don't have a patch yet, and I'll work on vftable name mangling tomorrow, since David wanted me to look at that. What I've learned so far is that we iterate over the paths from the MDC to vftables, and in this instance, we get: vftable for B in D Because the final override of 'foo' is in C, we don't observe it. We don't observe it because we have code like:
... Meaning, we always say the this offset is zero when we can't see the final overrider along this inheritance path. If C were D's primary base, things would work. |
I've started looking at this but got distracted by other duties. |
We're looking into emitting an error on this so we can fallback. I'm not going to try to do a full fix for now. |
In your example, I believe you said it was significant that D inherits from a non-primary base (C) that overrides methods from a virtual base (A). Your example returns the correct value if the inheritance order is reversed, i.e. struct D : C, B I think I've found a different way to make it fail. If I change C to this, and look at the value of d.bar() instead: struct D : B, C { D.bar() will now return 3 independently of in which order it inherits from B and C. (Reduced from Chromium's RenderViewImpl.) |
I've made Clang error out on this case in r202331. We should revert that when we fix the issue. |
Here's another example of a (possibly related) bad vftable layout in the presence of virtual inheritance: struct A { virtual void f() {} }; This test case is from #18122 . We generate an empty vftable for the non-virtual A in C: Which gives this IR: Which crashes the COFF writer as reported in llvm/llvm-bugzilla-archive#18993 . |
I think the latter one is unrelated and should be fixed separately -- filed llvm/llvm-bugzilla-archive#19066 . |
r203222 |
The test from Comment 6 still fails: struct A { |
Hm, interesting. Looks like it's the "C::foo()" call that we miscompile. |
mentioned in issue llvm/llvm-bugzilla-archive#19066 |
mentioned in issue llvm/llvm-bugzilla-archive#19104 |
Extended Description
Semi-reduced test case:
$ cat t.cpp
struct A {
virtual int foo() { return a; }
int a;
};
struct B : virtual A {
B() : b(1) {}
virtual int bar() { return b; }
int b;
};
struct C : virtual A {
C() : c(2) {}
virtual int foo() { return c; }
int c;
};
struct D : B, C {
D() : d(3) {}
virtual int bar() { return d; }
int d;
};
int main() {
D d;
return d.foo();
}
$ clang-cl -GR- t.cpp && ./t.exe ; echo $?
3
This should return 2, not 3. It's accessing 'd' instead of 'c'.
The text was updated successfully, but these errors were encountered: