]> granicus.if.org Git - clang/commitdiff
When generating the call arguments in a thunk to call the thunkee, do
authorDouglas Gregor <dgregor@apple.com>
Fri, 21 May 2010 17:55:12 +0000 (17:55 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 21 May 2010 17:55:12 +0000 (17:55 +0000)
not make copies non-POD arguments or arguments passed by reference:
just copy the pointers directly. This eliminates another source of the
dreaded memcpy-of-non-PODs. Fixes PR7188.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104327 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVTables.cpp
test/CodeGenCXX/thunks.cpp

index 3c9b45ba8c1c2c0a39c7b5201a40e37af4f2e846..b66b9f8493392a9248f7f3a3e9b521a6957f7347 100644 (file)
@@ -2642,9 +2642,15 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
     ParmVarDecl *Param = *I;
     QualType ArgType = Param->getType();
     
-    // FIXME: Declaring a DeclRefExpr on the stack is kinda icky.
-    DeclRefExpr ArgExpr(Param, ArgType.getNonReferenceType(), SourceLocation());
-    CallArgs.push_back(std::make_pair(EmitCallArg(&ArgExpr, ArgType), ArgType));
+    // Load the argument corresponding to this parameter.
+    RValue Arg;
+    if (ArgType->isReferenceType() ||
+        (hasAggregateLLVMType(ArgType) && !ArgType->isAnyComplexType()))
+      Arg = RValue::get(Builder.CreateLoad(LocalDeclMap[Param]));
+    else
+      Arg = RValue::get(EmitLoadOfScalar(LocalDeclMap[Param], false, ArgType));
+    
+    CallArgs.push_back(std::make_pair(Arg, ArgType));
   }
 
   // Get our callee.
index 8144770763dd9ab3f217f8ead7c4f66fb0f2dfa1..b6e18e6e01fe300102fa8eccb8db2af36abf41f2 100644 (file)
@@ -173,6 +173,51 @@ namespace Test6 {
   X Thunks::f() { return X(); }
 }
 
+namespace Test7 {
+  // PR7188
+  struct X {
+    X();
+    X(const X&);
+    X &operator=(const X&);
+    ~X();
+  };
+
+  struct Small { short s; };
+  struct Large {
+    char array[1024];
+  };
+
+  class A {
+  protected:
+    virtual void foo() = 0;
+  };
+
+  class B : public A {
+  protected:
+    virtual void bar() = 0;
+  };
+
+  class C : public A  {
+  protected:
+    virtual void baz(X, X&, _Complex float, Small, Small&, Large) = 0;
+  };
+
+  class D : public B,
+            public C {
+
+    void foo() {}
+    void bar() {}
+    void baz(X, X&, _Complex float, Small, Small&, Large);
+  };
+
+  void D::baz(X, X&, _Complex float, Small, Small&, Large) { }
+
+  // CHECK: define void @_ZThn8_N5Test71D3bazENS_1XERS1_CfNS_5SmallERS4_NS_5LargeE(
+  // CHECK-NOT: memcpy
+  // CHECK: ret void
+  void testD() { D d; }
+}
+
 // This is from Test5:
 // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
 // CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(