diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-11-16 05:31:29 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-11-16 05:31:29 +0000 |
commit | 8dfa2b3a5b818aa888d21eed8585e3d1b9d3506b (patch) | |
tree | 08e3ceb40470b73c044431212fd55b65e647989b | |
parent | eaea8c4c23b6892c82640c6f67034d9ed4498d45 (diff) |
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
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 27 | ||||
-rw-r--r-- | test/CodeGenCXX/virtual-operator-call.cpp | 10 | ||||
-rw-r--r-- | test/CodeGenCXX/virtual-pseudo-destructor-call.cpp | 10 |
3 files changed, 39 insertions, 8 deletions
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<CXXDestructorDecl>(MD)) - Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); - else + if (const CXXDestructorDecl *Destructor + = dyn_cast<CXXDestructorDecl>(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(); +} |