From: Anders Carlsson Date: Mon, 12 Oct 2009 19:41:04 +0000 (+0000) Subject: Factor out devirtualization checking into a separate function and make it handle... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8e7670de19334eccfe9ac5fc70fa57015b1654c8;p=clang Factor out devirtualization checking into a separate function and make it handle references correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83880 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index af49942738..0744b79d45 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -198,6 +198,20 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, Callee, Args, MD); } +/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given +/// expr can be devirtualized. +static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { + if (const DeclRefExpr *DRE = dyn_cast(Base)) { + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { + // This is a record decl. We know the type and can devirtualize it. + return VD->getType()->isRecordType(); + } + } + + // We can't devirtualize the call. + return false; +} + RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { if (isa(CE->getCallee())) return EmitCXXMemberPointerCallExpr(CE); @@ -235,7 +249,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { // because then we know what the type is. llvm::Value *Callee; if (MD->isVirtual() && !ME->hasQualifier() && - !ME->getBase()->getType()->isRecordType()) + !canDevirtualizeMemberFunctionCalls(ME->getBase())) Callee = BuildVirtualCall(MD, This, Ty); else if (const CXXDestructorDecl *Destructor = dyn_cast(MD)) diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp new file mode 100644 index 0000000000..19206aebce --- /dev/null +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s + +struct A { + virtual void f(); +}; + +void f(A a, A *ap, A& ar) { + // This should not be a virtual function call. + + // CHECK: call void @_ZN1A1fEv(%struct.A* %a) + a.f(); + + // CHECK: call void % + ap->f(); + + // CHECK: call void % + ar.f(); +} diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp index 34ab1df689..d27a7c9bfc 100644 --- a/test/CodeGenCXX/virtual-function-calls.cpp +++ b/test/CodeGenCXX/virtual-function-calls.cpp @@ -8,10 +8,3 @@ struct A { void f(A *a) { a->f('c'); } - -void f(A a) { - // This should not be a virtual function call. - - // CHECK: call void @_ZN1A1fEc - a.f('c'); -} \ No newline at end of file