From: Artyom Skrobov <artyom.skrobov@arm.com>
Date: Fri, 27 Dec 2013 16:29:53 +0000
Subject: [PATCH] Warn when NULL is returned from 'operator new'
 without 'throw()'

---
 include/clang/Basic/DiagnosticGroups.td    |    1 +
 include/clang/Basic/DiagnosticSemaKinds.td |    3 +++
 lib/Sema/SemaStmt.cpp                      |   14 ++++++++++++++
 test/SemaCXX/new-delete.cpp                |    2 +-
 test/SemaCXX/warn-new-overaligned.cpp      |    4 ++--
 5 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index bf77259..e1320be 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -226,6 +226,7 @@ def : DiagGroup<"overflow">;
 def ForwardClassReceiver : DiagGroup<"receiver-forward-class">;
 def MethodAccess : DiagGroup<"objc-method-access">;
 def ObjCReceiver : DiagGroup<"receiver-expr">;
+def OperatorNewReturnsNull : DiagGroup<"new-returns-null">;
 def OverlengthStrings : DiagGroup<"overlength-strings">;
 def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
 def PrivateExtern : DiagGroup<"private-extern">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3a3c93d..9825759 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6003,6 +6003,9 @@ def err_operator_new_delete_too_few_parameters : Error<
   "%0 must have at least one parameter">;
 def err_operator_new_delete_template_too_few_parameters : Error<
   "%0 template must have at least two parameters">;
+def warn_operator_new_returns_null : Warning<
+  "%0 must not return NULL unless it is declared 'throw()'">,
+  InGroup<OperatorNewReturnsNull>;
 
 def err_operator_new_dependent_param_type : Error<
   "%0 cannot take a dependent type as first parameter; "
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index e4fe9c3..27a834d 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -2779,6 +2779,20 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
     if (FD->isNoReturn())
       Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
         << FD->getDeclName();
+
+    OverloadedOperatorKind Op = FD->getOverloadedOperator();
+    if (Op == OO_New || Op == OO_Array_New) {
+      const FunctionProtoType *Proto
+        = FD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
+      llvm::APSInt ReturnValue;
+
+      if (!Proto->isNothrow(Context) &&
+          RetValExp->EvaluateAsInt(ReturnValue, Context,
+                                   Expr::SE_AllowSideEffects) &&
+          ReturnValue == 0)
+        Diag(ReturnLoc, diag::warn_operator_new_returns_null)
+          << FD->getDeclName();
+    }
   } else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
     FnRetType = MD->getResultType();
     if (MD->hasRelatedResultType() && MD->getClassInterface()) {
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 7facd10..59e2574 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -Wno-new-returns-null
 
 #include <stddef.h>
 
diff --git a/test/SemaCXX/warn-new-overaligned.cpp b/test/SemaCXX/warn-new-overaligned.cpp
index 42a4e35..ce08cf0 100644
--- a/test/SemaCXX/warn-new-overaligned.cpp
+++ b/test/SemaCXX/warn-new-overaligned.cpp
@@ -38,7 +38,7 @@ struct Test {
   } __attribute__((aligned(256)));
 
   void* operator new(unsigned long) {
-    return 0;
+    return 0; // expected-warning {{'operator new' must not return NULL unless it is declared 'throw()'}}
   }
 
   SeparateCacheLines<int> high_contention_data[10];
@@ -59,7 +59,7 @@ struct Test {
   } __attribute__((aligned(256)));
 
   void* operator new[](unsigned long) {
-    return 0;
+    return 0; // expected-warning {{'operator new[]' must not return NULL unless it is declared 'throw()'}}
   }
 
   SeparateCacheLines<int> high_contention_data[10];
-- 
1.7.9.5

