aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-11-16 05:31:29 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-11-16 05:31:29 +0000
commit8dfa2b3a5b818aa888d21eed8585e3d1b9d3506b (patch)
tree08e3ceb40470b73c044431212fd55b65e647989b
parenteaea8c4c23b6892c82640c6f67034d9ed4498d45 (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.cpp27
-rw-r--r--test/CodeGenCXX/virtual-operator-call.cpp10
-rw-r--r--test/CodeGenCXX/virtual-pseudo-destructor-call.cpp10
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();
+}