From: Eli Friedman Date: Wed, 29 Jun 2011 07:04:55 +0000 (+0000) Subject: We don't pass classes with a copy-constructor or destructor byval, so the address... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ded137fcab19f0aace08a28b5c91574e6b23debc;p=clang We don't pass classes with a copy-constructor or destructor byval, so the address takes up an integer register (if one is available). Make sure the x86-64 ABI implementation takes that into account properly. The fixed implementation is compatible with the implementation both gcc and llvm-gcc use. rdar://9686430 . (This is the issue that was reported in the thread "[LLVMdev] Segfault calling LLVM libs from a clang-compiled executable".) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134059 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 47a764bbc0..f65fc185ba 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1765,6 +1765,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt, // COMPLEX_X87, it is passed in memory. case X87: case ComplexX87: + if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) + ++neededInt; return getIndirectResult(Ty); case SSEUp: diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp index 01f1a445b1..6d3748ca7d 100644 --- a/test/CodeGenCXX/x86_64-arguments.cpp +++ b/test/CodeGenCXX/x86_64-arguments.cpp @@ -115,3 +115,22 @@ namespace test6 { } // CHECK: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1) } + +namespace test7 { + struct StringRef {char* ptr; long len; }; + class A { public: ~A(); }; + A x(A, A, long, long, StringRef) { return A(); } + // Check that the StringRef is passed byval instead of expanded + // (which would split it between registers and memory). + // rdar://problem/9686430 + // CHECK: define void @_ZN5test71xENS_1AES0_llNS_9StringRefE({{.*}} byval align 8) + + // And a couple extra related tests: + A y(A, long double, long, long, StringRef) { return A(); } + // CHECK: define void @_ZN5test71yENS_1AEellNS_9StringRefE({{.*}} i8* + struct StringDouble {char * ptr; double d;}; + A z(A, A, A, A, A, StringDouble) { return A(); } + A zz(A, A, A, A, StringDouble) { return A(); } + // CHECK: define void @_ZN5test71zENS_1AES0_S0_S0_S0_NS_12StringDoubleE({{.*}} byval align 8) + // CHECK: define void @_ZN5test72zzENS_1AES0_S0_S0_NS_12StringDoubleE({{.*}} i8* +}