diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-22 05:51:36 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-22 05:51:36 +0000 |
commit | 1664d540d1524f0faffd2f839fccb56178975c60 (patch) | |
tree | c0b092e0317e16743510727d7a57ffbeef2f1247 | |
parent | a77e0726341a4afbe9c25b05cf944edf17f64543 (diff) |
PR12571: Objects of type clang::ConstantArrayType aren't always emitted with
type llvm::ArrayType -- sometimes we emit them as packed structs. Don't assert
if such a global array has an element type with a non-trivial destructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155305 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 36 | ||||
-rw-r--r-- | test/CodeGenCXX/global-array-destruction.cpp | 33 |
2 files changed, 48 insertions, 21 deletions
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 2939062c9b..fd787394d7 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -881,33 +881,49 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, llvm::ConstantInt *zero = Builder.getInt32(0); gepIndices.push_back(zero); - // It's more efficient to calculate the count from the LLVM - // constant-length arrays than to re-evaluate the array bounds. uint64_t countFromCLAs = 1; + QualType eltType; llvm::ArrayType *llvmArrayType = - cast<llvm::ArrayType>( + dyn_cast<llvm::ArrayType>( cast<llvm::PointerType>(addr->getType())->getElementType()); - while (true) { + while (llvmArrayType) { assert(isa<ConstantArrayType>(arrayType)); assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue() == llvmArrayType->getNumElements()); gepIndices.push_back(zero); countFromCLAs *= llvmArrayType->getNumElements(); + eltType = arrayType->getElementType(); llvmArrayType = dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType()); - if (!llvmArrayType) break; - arrayType = getContext().getAsArrayType(arrayType->getElementType()); - assert(arrayType && "LLVM and Clang types are out-of-synch"); + assert((!llvmArrayType || arrayType) && + "LLVM and Clang types are out-of-synch"); } - baseType = arrayType->getElementType(); + if (arrayType) { + // From this point onwards, the Clang array type has been emitted + // as some other type (probably a packed struct). Compute the array + // size, and just emit the 'begin' expression as a bitcast. + while (arrayType) { + countFromCLAs *= + cast<ConstantArrayType>(arrayType)->getSize().getZExtValue(); + eltType = arrayType->getElementType(); + arrayType = getContext().getAsArrayType(eltType); + } + + unsigned AddressSpace = + cast<llvm::PointerType>(addr->getType())->getAddressSpace(); + llvm::Type *BaseType = ConvertType(eltType)->getPointerTo(AddressSpace); + addr = Builder.CreateBitCast(addr, BaseType, "array.begin"); + } else { + // Create the actual GEP. + addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin"); + } - // Create the actual GEP. - addr = Builder.CreateInBoundsGEP(addr, gepIndices, "array.begin"); + baseType = eltType; llvm::Value *numElements = llvm::ConstantInt::get(SizeTy, countFromCLAs); diff --git a/test/CodeGenCXX/global-array-destruction.cpp b/test/CodeGenCXX/global-array-destruction.cpp index 5b5dfac0f2..076ef94220 100644 --- a/test/CodeGenCXX/global-array-destruction.cpp +++ b/test/CodeGenCXX/global-array-destruction.cpp @@ -1,6 +1,4 @@ -// REQUIRES: x86-64-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s -// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | FileCheck %s extern "C" int printf(...); @@ -24,11 +22,24 @@ static S sarr1[4]; S s2; S arr3[3]; -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit -// CHECK-LP64: callq ___cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: call {{.*}} @__cxa_atexit + +struct T { + double d; + int n; + ~T(); +}; +T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; + +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @t to %struct.T*), i64 6 +// CHECK: call void @_ZN1TD1Ev +// CHECK: icmp eq {{.*}} @t +// CHECK: br i1 {{.*}} |