Determining Static vs Dynamic Dispatch

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Determining Static vs Dynamic Dispatch

Vassil Vassilev via cfe-dev
Hello --

I'm working on a tool that gives a formal semantics to the clang C++ abstract syntax tree (the project is available here: github.com/bedrocksystems/cpp2v). I'm working on adding support for virtual functions and I'm trying to understand whether a call in the AST is a static call or a dynamic call and I'm having difficulty figuring out how to do it reliably. Here's a simple program:

struct A {
  virtual int foo() { return 100; }
};
struct B : public A {
  virtual int foo() { return 10; }
};
int test(B* b) {
  return b->foo() + b->B::foo();
}

From what I understand (and what the compiler does) the left call `b->foo()` uses dynamic dispatch to resolve `foo` in the most derived class of the argument B. But the call on the right always calls B::foo (returning 10) regardless of the most derived class of B. However, I don't understand what function I can call on the CXXMemberCallExpr node that distinguishes these two cases. getMethodDecl, getRecordDecl, and getImplicitObjectArgument all seem to return the exact same information.

How does clang differentiate between these two calls in order to get the correct behavior?

Thanks in advance for any pointers.

--
gregory malecha

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Determining Static vs Dynamic Dispatch

Vassil Vassilev via cfe-dev
I found this by setting a breakpoint on "llvm::CallInst::CallInst" and looking around at the two call instructions created in your example - it looks like Clang's IR generation tests whether the call is qualified to decide whether it can call virtually or not:

https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/CGExprCXX.cpp#L197

On Thu, May 28, 2020 at 4:35 PM Gregory Malecha via cfe-dev <[hidden email]> wrote:
Hello --

I'm working on a tool that gives a formal semantics to the clang C++ abstract syntax tree (the project is available here: github.com/bedrocksystems/cpp2v). I'm working on adding support for virtual functions and I'm trying to understand whether a call in the AST is a static call or a dynamic call and I'm having difficulty figuring out how to do it reliably. Here's a simple program:

struct A {
  virtual int foo() { return 100; }
};
struct B : public A {
  virtual int foo() { return 10; }
};
int test(B* b) {
  return b->foo() + b->B::foo();
}

From what I understand (and what the compiler does) the left call `b->foo()` uses dynamic dispatch to resolve `foo` in the most derived class of the argument B. But the call on the right always calls B::foo (returning 10) regardless of the most derived class of B. However, I don't understand what function I can call on the CXXMemberCallExpr node that distinguishes these two cases. getMethodDecl, getRecordDecl, and getImplicitObjectArgument all seem to return the exact same information.

How does clang differentiate between these two calls in order to get the correct behavior?

Thanks in advance for any pointers.

--
gregory malecha
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Determining Static vs Dynamic Dispatch

Vassil Vassilev via cfe-dev
Thanks, David, that's very helpful! I haven't been digging into the code-generation portion of the code.

On Thu, May 28, 2020 at 8:02 PM David Blaikie <[hidden email]> wrote:
I found this by setting a breakpoint on "llvm::CallInst::CallInst" and looking around at the two call instructions created in your example - it looks like Clang's IR generation tests whether the call is qualified to decide whether it can call virtually or not:

https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/CGExprCXX.cpp#L197

On Thu, May 28, 2020 at 4:35 PM Gregory Malecha via cfe-dev <[hidden email]> wrote:
Hello --

I'm working on a tool that gives a formal semantics to the clang C++ abstract syntax tree (the project is available here: github.com/bedrocksystems/cpp2v). I'm working on adding support for virtual functions and I'm trying to understand whether a call in the AST is a static call or a dynamic call and I'm having difficulty figuring out how to do it reliably. Here's a simple program:

struct A {
  virtual int foo() { return 100; }
};
struct B : public A {
  virtual int foo() { return 10; }
};
int test(B* b) {
  return b->foo() + b->B::foo();
}

From what I understand (and what the compiler does) the left call `b->foo()` uses dynamic dispatch to resolve `foo` in the most derived class of the argument B. But the call on the right always calls B::foo (returning 10) regardless of the most derived class of B. However, I don't understand what function I can call on the CXXMemberCallExpr node that distinguishes these two cases. getMethodDecl, getRecordDecl, and getImplicitObjectArgument all seem to return the exact same information.

How does clang differentiate between these two calls in order to get the correct behavior?

Thanks in advance for any pointers.

--
gregory malecha
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


--
gregory malecha

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev