]> granicus.if.org Git - clang/commitdiff
Handle operator call expressions where the callee is a member function.
authorAnders Carlsson <andersca@mac.com>
Wed, 27 May 2009 04:18:27 +0000 (04:18 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 27 May 2009 04:18:27 +0000 (04:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72458 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/member-functions.cpp

index 025749497741e81b7314609cddb44d8174603da2..94d69d846c6e201af40088d00ebb44a7060b588a 100644 (file)
@@ -124,6 +124,25 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
                            CE->arg_begin(), CE->arg_end());
 }
 
+RValue 
+CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
+                                               const CXXMethodDecl *MD) {
+  assert(MD->isInstance() && 
+         "Trying to emit a member call expr on a static method!");
+  
+  
+  const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
+  const llvm::Type *Ty = 
+  CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 
+                                 FPT->isVariadic());
+  llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
+  
+  llvm::Value *This = EmitLValue(E->getArg(0)).getAddress();
+  
+  return EmitCXXMemberCall(MD, Callee, This,
+                           E->arg_begin() + 1, E->arg_end());
+}
+
 llvm::Value *CodeGenFunction::LoadCXXThis() {
   assert(isa<CXXMethodDecl>(CurFuncDecl) && 
          "Must be in a C++ member function decl to load 'this'");
index 45e19f139ac65f509ba189216a560444b4167a44..ff61d5ba1cf23dc8fcd201d20e78eb26022b540b 100644 (file)
@@ -1136,6 +1136,11 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
     }
   }
 
+  if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) {
+    if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
+      return EmitCXXOperatorMemberCallExpr(CE, MD);
+  }
+      
   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
   return EmitCall(Callee, E->getCallee()->getType(),
                   E->arg_begin(), E->arg_end(), TargetDecl);
index 28c557c15617236c4f22e2d62aec80eddcd0001e..7d13071ece21b54013e920a81ca3d6bc4cc7bfe5 100644 (file)
@@ -686,6 +686,9 @@ public:
                            CallExpr::const_arg_iterator ArgEnd);
   RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E);
 
+  RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
+                                       const CXXMethodDecl *MD);
+  
   RValue EmitBuiltinExpr(const FunctionDecl *FD, 
                          unsigned BuiltinID, const CallExpr *E);
 
index 02c7e2c36d5faaaff850c7b619d33a39a8e3f3ad..3f40453e98663ed9422769b2315ec1407d5694ab 100644 (file)
@@ -37,7 +37,7 @@ struct S {
   static void f();
 };
 
-// RUN: grep "define void @_ZN1S1fEv" %t
+// RUN: grep "define void @_ZN1S1fEv" %t &&
 void S::f() {
 }
 
@@ -50,3 +50,14 @@ void test2() {
   S::g();
   
 }
+
+struct T {
+  T operator+(const T&);
+};
+
+void test3() {
+  T t1, t2;
+  
+  // RUN: grep "call void @_ZN1TpsERK1T" %t
+  T result = t1 + t2;
+}