From: Eli Friedman Date: Mon, 16 Nov 2009 05:31:29 +0000 (+0000) Subject: Fix a couple of cases where we weren't generating the right kind of call X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8dfa2b3a5b818aa888d21eed8585e3d1b9d3506b;p=clang Fix a couple of cases where we weren't generating the right kind of call for a call to a virtual function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88891 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 5a0cb1621b..a3ab476511 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -282,14 +282,20 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { // We also don't emit a virtual call if the base expression has a record type // because then we know what the type is. llvm::Value *Callee; - if (MD->isVirtual() && !ME->hasQualifier() && - !canDevirtualizeMemberFunctionCalls(ME->getBase())) - Callee = BuildVirtualCall(MD, This, Ty); - else if (const CXXDestructorDecl *Destructor - = dyn_cast(MD)) - Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); - else + if (const CXXDestructorDecl *Destructor + = dyn_cast(MD)) { + if (MD->isVirtual() && !ME->hasQualifier() && + !canDevirtualizeMemberFunctionCalls(ME->getBase())) { + Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty); + } else { + Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); + } + } else if (MD->isVirtual() && !ME->hasQualifier() && + !canDevirtualizeMemberFunctionCalls(ME->getBase())) { + Callee = BuildVirtualCall(MD, This, Ty); + } else { Callee = CGM.GetAddrOfFunction(MD, Ty); + } return EmitCXXMemberCall(MD, Callee, This, CE->arg_begin(), CE->arg_end()); @@ -425,10 +431,15 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), FPT->isVariadic()); - llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty); llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + llvm::Value *Callee; + if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0))) + Callee = BuildVirtualCall(MD, This, Ty); + else + Callee = CGM.GetAddrOfFunction(MD, Ty); + return EmitCXXMemberCall(MD, Callee, This, E->arg_begin() + 1, E->arg_end()); } diff --git a/test/CodeGenCXX/virtual-operator-call.cpp b/test/CodeGenCXX/virtual-operator-call.cpp new file mode 100644 index 0000000000..018052bb47 --- /dev/null +++ b/test/CodeGenCXX/virtual-operator-call.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s + +struct A { + virtual int operator-() = 0; +}; + +void f(A *a) { + // CHECK: call i32 % + -*a; +} diff --git a/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp new file mode 100644 index 0000000000..3d99a02160 --- /dev/null +++ b/test/CodeGenCXX/virtual-pseudo-destructor-call.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s + +struct A { + virtual ~A(); +}; + +void f(A *a) { + // CHECK: call void % + a->~A(); +}