summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-08-28 16:48:44 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-08-28 16:48:44 +0000
commit33375375a4c31cf31803c6f9555ca023864818fe (patch)
treef8e4e3072f6693adc5dce78cf2a499134ecb2bd8 /clang/lib/CodeGen
parent50cbfc513827b192b77f3c2ee5ea70fcda36433e (diff)
downloadbcm5719-llvm-33375375a4c31cf31803c6f9555ca023864818fe.tar.gz
bcm5719-llvm-33375375a4c31cf31803c6f9555ca023864818fe.zip
Throw a std::bad_array_new_length exception when the expression (or constant-expression) passed to operator new[] results in overflow in conformance with [expr.new]p7. Fixes PR11644.
llvm-svn: 216675
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCXXABI.cpp9
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h7
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp14
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp35
4 files changed, 58 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 55ddd666c49..bdd887c4a02 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -325,3 +325,12 @@ LValue CGCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
return false;
}
+
+llvm::Value *CGCXXABI::EmitNewArrayLengthOverflowCheck(
+ CodeGenFunction &CGF, bool ConstantOverflow, llvm::Value *DynamicOverflow,
+ llvm::Value *Size) {
+ llvm::Value *AllOnes = llvm::Constant::getAllOnesValue(CGF.SizeTy);
+ if (ConstantOverflow)
+ return AllOnes;
+ return CGF.Builder.CreateSelect(DynamicOverflow, AllOnes, Size);
+}
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 39813fd475d..af5fb19f256 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -236,6 +236,13 @@ public:
virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;
+ /// Emit the code required to throw a std::bad_array_new_length exception by
+ /// the ABI, and returns the array length size to allocate.
+ virtual llvm::Value *
+ EmitNewArrayLengthOverflowCheck(CodeGenFunction &CGF, bool ConstantOverflow,
+ llvm::Value *DynamicOverflow,
+ llvm::Value *Size);
+
virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
llvm::Value *This,
const CXXRecordDecl *ClassDecl,
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index db876b11694..1d175b25816 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -572,11 +572,11 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
}
// On overflow, produce a -1 so operator new will fail.
- if (hasAnyOverflow) {
- size = llvm::Constant::getAllOnesValue(CGF.SizeTy);
- } else {
+ if (hasAnyOverflow)
+ size = CGF.CGM.getCXXABI().EmitNewArrayLengthOverflowCheck(
+ CGF, true, nullptr, llvm::Constant::getAllOnesValue(CGF.SizeTy));
+ else
size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);
- }
// Otherwise, we might need to use the overflow intrinsics.
} else {
@@ -714,9 +714,9 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// overwrite 'size' with an all-ones value, which should cause
// operator new to throw.
if (hasOverflow)
- size = CGF.Builder.CreateSelect(hasOverflow,
- llvm::Constant::getAllOnesValue(CGF.SizeTy),
- size);
+ size = CGF.CGM.getCXXABI().EmitNewArrayLengthOverflowCheck(CGF, false,
+ hasOverflow,
+ size);
}
if (cookieSize == 0)
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5df3e43f488..8034e1e5b9b 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -133,6 +133,11 @@ public:
bool EmitBadCastCall(CodeGenFunction &CGF) override;
+ llvm::Value *EmitNewArrayLengthOverflowCheck(CodeGenFunction &CGF,
+ bool ConstantOverflow,
+ llvm::Value *DynamicOverflow,
+ llvm::Value *Size) override;
+
llvm::Value *
GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
const CXXRecordDecl *ClassDecl,
@@ -1044,6 +1049,36 @@ bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
return true;
}
+llvm::Value *ItaniumCXXABI::EmitNewArrayLengthOverflowCheck(
+ CodeGenFunction &CGF, bool ConstantOverflow, llvm::Value *DynamicOverflow,
+ llvm::Value *Size) {
+ // In C++11 and later, an overflow results in throwing
+ // std::bad_array_new_length.
+ if (!CGF.getLangOpts().CPlusPlus11)
+ return CGCXXABI::EmitNewArrayLengthOverflowCheck(CGF, ConstantOverflow,
+ DynamicOverflow, Size);
+
+ llvm::BasicBlock *BadArrayNewLengthBlock =
+ CGF.createBasicBlock("new.bad_array_new_length");
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("new.end");
+
+ if (!ConstantOverflow) {
+ assert(DynamicOverflow && "Called for dynamic case, but no overflow value");
+ CGF.Builder.CreateCondBr(DynamicOverflow, BadArrayNewLengthBlock, EndBlock);
+ }
+ CGF.EmitBlock(BadArrayNewLengthBlock);
+
+ // void __cxa_bad_array_new_length();
+ llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
+ llvm::Value *Fn =
+ CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_array_new_length");
+ CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
+ CGF.Builder.CreateUnreachable();
+
+ CGF.EmitBlock(EndBlock);
+ return Size;
+}
+
llvm::Value *
ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
llvm::Value *This,
OpenPOWER on IntegriCloud