Determining Static vs Dynamic Dispatch

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.

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

Thanks, David, that’s very helpful! I haven’t been digging into the code-generation portion of the code.