<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Aug 28, 2014 at 9:48 AM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: aaronballman<br>
Date: Thu Aug 28 11:48:44 2014<br>
New Revision: 216675<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=216675&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=216675&view=rev</a><br>
Log:<br>
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.<br></blockquote><div><br></div><div>This is certainly an improvement, but we're still not implementing [expr.new]p7 correctly. Here are some cases we get wrong:</div>
<div><br></div><div>// We convert this to -1 rather than throwing.</div><div>int k = 0x80000000; char *p = new char[k];<br></div><div><br></div><div>// We convert these to -1 rather than rejecting with an error.</div><div>
char *p = new char[-1];</div><div>char *q = new char[1]{1, 2};</div><div><br></div><div>// We reject this at compile time even though it is valid.</div><div>int k = 10; char *p = new char[k]{"foobar"};<br></div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Modified:<br>
    cfe/trunk/lib/CodeGen/CGCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp<br>
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
    cfe/trunk/test/CodeGenCXX/new-array-init.cpp<br>
    cfe/trunk/test/CodeGenCXX/operator-new.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.cpp?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXXABI.cpp Thu Aug 28 11:48:44 2014<br>
@@ -325,3 +325,12 @@ LValue CGCXXABI::EmitThreadLocalVarDeclL<br>
 bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {<br>
   return false;<br>
 }<br>
+<br>
+llvm::Value *CGCXXABI::EmitNewArrayLengthOverflowCheck(<br>
+    CodeGenFunction &CGF, bool ConstantOverflow, llvm::Value *DynamicOverflow,<br>
+    llvm::Value *Size) {<br>
+  llvm::Value *AllOnes = llvm::Constant::getAllOnesValue(CGF.SizeTy);<br>
+  if (ConstantOverflow)<br>
+    return AllOnes;<br>
+  return CGF.Builder.CreateSelect(DynamicOverflow, AllOnes, Size);<br>
+}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Thu Aug 28 11:48:44 2014<br>
@@ -236,6 +236,13 @@ public:<br>
<br>
   virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;<br>
<br>
+  /// Emit the code required to throw a std::bad_array_new_length exception by<br>
+  /// the ABI, and returns the array length size to allocate.<br>
+  virtual llvm::Value *<br>
+  EmitNewArrayLengthOverflowCheck(CodeGenFunction &CGF, bool ConstantOverflow,<br>
+                                  llvm::Value *DynamicOverflow,<br>
+                                  llvm::Value *Size);<br>
+<br>
   virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,<br>
                                                  llvm::Value *This,<br>
                                                  const CXXRecordDecl *ClassDecl,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Aug 28 11:48:44 2014<br>
@@ -572,11 +572,11 @@ static llvm::Value *EmitCXXNewAllocSize(<br>
     }<br>
<br>
     // On overflow, produce a -1 so operator new will fail.<br>
-    if (hasAnyOverflow) {<br>
-      size = llvm::Constant::getAllOnesValue(CGF.SizeTy);<br>
-    } else {<br>
+    if (hasAnyOverflow)<br>
+      size = CGF.CGM.getCXXABI().EmitNewArrayLengthOverflowCheck(<br>
+          CGF, true, nullptr, llvm::Constant::getAllOnesValue(CGF.SizeTy));<br>
+    else<br>
       size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);<br>
-    }<br>
<br>
   // Otherwise, we might need to use the overflow intrinsics.<br>
   } else {<br>
@@ -714,9 +714,9 @@ static llvm::Value *EmitCXXNewAllocSize(<br>
     // overwrite 'size' with an all-ones value, which should cause<br>
     // operator new to throw.<br>
     if (hasOverflow)<br>
-      size = CGF.Builder.CreateSelect(hasOverflow,<br>
-                                 llvm::Constant::getAllOnesValue(CGF.SizeTy),<br>
-                                      size);<br>
+      size = CGF.CGM.getCXXABI().EmitNewArrayLengthOverflowCheck(CGF, false,<br>
+                                                                 hasOverflow,<br>
+                                                                 size);<br>
   }<br>
<br>
   if (cookieSize == 0)<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Aug 28 11:48:44 2014<br>
@@ -133,6 +133,11 @@ public:<br>
<br>
   bool EmitBadCastCall(CodeGenFunction &CGF) override;<br>
<br>
+  llvm::Value *EmitNewArrayLengthOverflowCheck(CodeGenFunction &CGF,<br>
+                                               bool ConstantOverflow,<br>
+                                               llvm::Value *DynamicOverflow,<br>
+                                               llvm::Value *Size) override;<br>
+<br>
   llvm::Value *<br>
     GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,<br>
                               const CXXRecordDecl *ClassDecl,<br>
@@ -1044,6 +1049,36 @@ bool ItaniumCXXABI::EmitBadCastCall(Code<br>
   return true;<br>
 }<br>
<br>
+llvm::Value *ItaniumCXXABI::EmitNewArrayLengthOverflowCheck(<br>
+    CodeGenFunction &CGF, bool ConstantOverflow, llvm::Value *DynamicOverflow,<br>
+    llvm::Value *Size) {<br>
+  // In C++11 and later, an overflow results in throwing<br>
+  // std::bad_array_new_length.<br>
+  if (!CGF.getLangOpts().CPlusPlus11)<br>
+    return CGCXXABI::EmitNewArrayLengthOverflowCheck(CGF, ConstantOverflow,<br>
+                                                     DynamicOverflow, Size);<br>
+<br>
+  llvm::BasicBlock *BadArrayNewLengthBlock =<br>
+    CGF.createBasicBlock("new.bad_array_new_length");<br>
+  llvm::BasicBlock *EndBlock = CGF.createBasicBlock("new.end");<br>
+<br>
+  if (!ConstantOverflow) {<br>
+    assert(DynamicOverflow && "Called for dynamic case, but no overflow value");<br>
+    CGF.Builder.CreateCondBr(DynamicOverflow, BadArrayNewLengthBlock, EndBlock);<br>
+  }<br>
+  CGF.EmitBlock(BadArrayNewLengthBlock);<br>
+<br>
+  // void __cxa_bad_array_new_length();<br>
+  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);<br>
+  llvm::Value *Fn =<br>
+    CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_array_new_length");<br></blockquote><div><br></div><div>This is incorrect; see <a href="http://mentorembedded.github.io/cxx-abi/abi.html#array-ctor">http://mentorembedded.github.io/cxx-abi/abi.html#array-ctor</a></div>
<div><br></div><div>The function is named __cxa_<b>throw_</b>bad_array_new_length</div><div><br></div><div>Have you thought about how we might support this when our C++ runtime library doesn't contain this symbol? I expect that will be the case for a lot of systems. We could emit a weak definition of this function that calls _Zna[lm](-1) then calls std::terminate, for instance.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();<br>
+  CGF.Builder.CreateUnreachable();<br>
+<br>
+  CGF.EmitBlock(EndBlock);<br>
+  return Size;<br>
+}<br>
+<br>
 llvm::Value *<br>
 ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,<br>
                                          llvm::Value *This,<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/new-array-init.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-array-init.cpp?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new-array-init.cpp?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/new-array-init.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/new-array-init.cpp Thu Aug 28 11:48:44 2014<br>
@@ -14,7 +14,12 @@ void fn(int n) {<br>
 // CHECK-LABEL: define void @_Z15const_underflowv<br>
 void const_underflow() {<br>
   // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3<br>
-  // CHECK: call noalias i8* @_Zna{{.}}(i{{32|64}} -1)<br>
+  // CHECK: br label %[[BAD:.*]]<br>
+  // CHECK: [[BAD]]:<br>
+  // CHECK-NEXT: call void @__cxa_bad_array_new_length()<br>
+  // CHECK-NEXT: unreachable<br>
+  // CHECK: {{.*}}:<br>
+  // CHECK: ret void<br>
   new int[2] { 1, 2, 3 };<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/operator-new.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/operator-new.cpp?rev=216675&r1=216674&r2=216675&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/operator-new.cpp?rev=216675&r1=216674&r2=216675&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/operator-new.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/operator-new.cpp Thu Aug 28 11:48:44 2014<br>
@@ -1,8 +1,7 @@<br>
-// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -o %t-1.ll %s<br>
-// RUN: FileCheck -check-prefix SANE --input-file=%t-1.ll %s<br>
-// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -fno-assume-sane-operator-new -o %t-2.ll %s<br>
-// RUN: FileCheck -check-prefix SANENOT --input-file=%t-2.ll %s<br>
-<br>
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -std=c++98 -emit-llvm -o - %s | FileCheck -check-prefix SANE98 %s<br>
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -std=c++11 -emit-llvm -o - %s | FileCheck -check-prefix SANE11 %s<br>
+// RUN: %clang_cc1 -triple i686-pc-win32-msvc -std=c++11 -emit-llvm -o - %s | FileCheck -check-prefix SANE11MS %s<br>
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -fno-assume-sane-operator-new -o - %s | FileCheck -check-prefix SANENOT %s<br>
<br>
 class teste {<br>
   int A;<br>
@@ -20,10 +19,44 @@ void f1() {<br>
 // rdar://5739832 - operator new should check for overflow in multiply.<br>
 void *f2(long N) {<br>
   return new int[N];<br>
-<br>
-// SANE:      [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow<br>
-// SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1<br>
-// SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0<br>
-// SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]<br>
-// SANE-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]])<br>
+<br>
+// SANE98:      [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow<br>
+// SANE98-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1<br>
+// SANE98-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0<br>
+// SANE98-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]<br>
+// SANE98-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]])<br>
+<br>
+// SANE11:      [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow<br>
+// SANE11-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1<br>
+// SANE11-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0<br>
+// SANE11-NEXT: br i1 [[OVER]], label %[[BAD:.*]], label %[[GOOD:.*]]<br>
+// SANE11: [[BAD]]:<br>
+// SANE11-NEXT: call void @__cxa_bad_array_new_length()<br>
+// SANE11-NEXT: unreachable<br>
+// SANE11: [[GOOD]]:<br>
+// SANE11-NEXT: call noalias i8* @_Znaj(i32 [[SUM]])<br>
+<br>
+// FIXME: There should be a call to generate the std::bad_array_new_length<br>
+// exception in the Microsoft ABI, however, this is not implemented currently.<br>
+// SANE11MS:      [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow<br>
+// SANE11MS-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1<br>
+// SANE11MS-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0<br>
+// SANE11MS-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]<br>
+// SANE11MS-NEXT: call noalias i8* @"\01??_U@YAPAXI@Z"(i32 [[RESULT]])<br>
+}<br>
+<br>
+#if __cplusplus > 199711L<br>
+void *f3() {<br>
+  return new int[0x7FFFFFFF];<br>
+// SANE11: br label %[[BAD:.*]]<br>
+// SANE11: [[BAD]]:<br>
+// SANE11-NEXT: call void @__cxa_bad_array_new_length()<br>
+// SANE11-NEXT: unreachable<br>
+// SANE11: {{.*}}:<br>
+// SANE11-NEXT: call noalias i8* @_Znaj(i32 -1)<br>
+<br>
+// FIXME: There should be a call to generate the std::bad_array_new_length<br>
+// exception in the Microsoft ABI, however, this is not implemented currently.<br>
+// SANE11MS: call noalias i8* @"\01??_U@YAPAXI@Z"(i32 -1)<br>
 }<br>
+#endif<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>