[clang] 52c8f0b - [clang] Add -fcheck-new support

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 23 22:45:22 PDT 2023


Author: Pedro Falcato
Date: 2023-06-23T22:45:17-07:00
New Revision: 52c8f0bb20eb9e7b1b54ffdddf6da77b53caeb3a

URL: https://github.com/llvm/llvm-project/commit/52c8f0bb20eb9e7b1b54ffdddf6da77b53caeb3a
DIFF: https://github.com/llvm/llvm-project/commit/52c8f0bb20eb9e7b1b54ffdddf6da77b53caeb3a.diff

LOG: [clang] Add -fcheck-new support

Add -fcheck-new and -fno-check-new, from GCC, which make the compiler
not assume pointers returned from operator new are non-null.
Fixes #16931.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D125272

Added: 
    clang/test/CodeGenCXX/fcheck-new.cpp

Modified: 
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Basic/LangOptions.h
    clang/include/clang/Driver/Options.td
    clang/lib/AST/ExprCXX.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/test/Driver/clang_f_opts.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index d4ee06b66d9a5..1cb9b27c7e9eb 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -466,6 +466,8 @@ LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process statements"
         "avoid tearing the Lexer and etc. down). Controlled by "
         "-fincremental-extensions.")
 
+BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NULL")
+
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
 #undef BENIGN_LANGOPT

diff  --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 1c98e28231b57..3ef68ca8af668 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -487,6 +487,10 @@ class LangOptions : public LangOptionsBase {
   /// forward slash (/) elsewhere.
   bool UseTargetPathSeparator = false;
 
+  // Indicates whether we should keep all nullptr checks for pointers
+  // received as a result of a standard operator new (-fcheck-new)
+  bool CheckNew = false;
+
   LangOptions();
 
   /// Set language defaults for the given input language and

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index b90d6763d6f3c..bb3d487886eb7 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5101,7 +5101,11 @@ def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group<clang_ignored_gcc_op
 // ignore it for now to avoid breaking builds that use it.
 def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>;
 
-defm fcheck_new : BooleanFFlag<"check-new">, Group<clang_ignored_f_Group>;
+defm check_new : BoolOption<"f", "check-new",
+  LangOpts<"CheckNew">, DefaultFalse,
+  PosFlag<SetTrue, [], "Do not assume C++ operator new may not return NULL">,
+  NegFlag<SetFalse>, BothFlags<[CC1Option]>>;
+
 defm caller_saves : BooleanFFlag<"caller-saves">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;

diff  --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 09e64b8c82c8e..8c061b0ad9316 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -276,6 +276,8 @@ CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray,
 }
 
 bool CXXNewExpr::shouldNullCheckAllocation() const {
+  if (getOperatorNew()->getLangOpts().CheckNew)
+    return true;
   return !getOperatorNew()->hasAttr<ReturnsNonNullAttr>() &&
          getOperatorNew()
              ->getType()

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 883544b9e37ec..de22ea4455fa7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6157,6 +6157,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                    Triple.hasDefaultEmulatedTLS()))
     CmdArgs.push_back("-femulated-tls");
 
+  Args.addOptInFlag(CmdArgs, options::OPT_fcheck_new,
+                    options::OPT_fno_check_new);
+
   if (Arg *A = Args.getLastArg(options::OPT_fzero_call_used_regs_EQ)) {
     // FIXME: There's no reason for this to be restricted to X86. The backend
     // code needs to be changed to include the appropriate function calls

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 698f57f0245b0..d72d4e097879f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16146,7 +16146,11 @@ void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
   //   indicates failure by returning a null pointer value. Any other allocation
   //   function never returns a null pointer value and indicates failure only by
   //   throwing an exception [...]
-  if (!IsNothrow && !FD->hasAttr<ReturnsNonNullAttr>())
+  //
+  // However, -fcheck-new invalidates this possible assumption, so don't add
+  // NonNull when that is enabled.
+  if (!IsNothrow && !FD->hasAttr<ReturnsNonNullAttr>() &&
+      !getLangOpts().CheckNew)
     FD->addAttr(ReturnsNonNullAttr::CreateImplicit(Context, FD->getLocation()));
 
   // C++2a [basic.stc.dynamic.allocation]p2:

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f2ff924bc7dea..817fd2d2d7d3f 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3157,7 +3157,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
     // Global allocation functions should always be visible.
     Alloc->setVisibleDespiteOwningModule();
 
-    if (HasBadAllocExceptionSpec && getLangOpts().NewInfallible)
+    if (HasBadAllocExceptionSpec && getLangOpts().NewInfallible &&
+        !getLangOpts().CheckNew)
       Alloc->addAttr(
           ReturnsNonNullAttr::CreateImplicit(Context, Alloc->getLocation()));
 

diff  --git a/clang/test/CodeGenCXX/fcheck-new.cpp b/clang/test/CodeGenCXX/fcheck-new.cpp
new file mode 100644
index 0000000000000..d5800cc73bb9a
--- /dev/null
+++ b/clang/test/CodeGenCXX/fcheck-new.cpp
@@ -0,0 +1,30 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -fcheck-new -triple x86_64-linux-gnu -disable-O0-optnone \
+// RUN:   -emit-llvm -o - %s | FileCheck %s
+
+struct A { A(); };
+
+// CHECK-LABEL: @_Z5test0v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CALL:%.*]] = call noalias noundef ptr @_Znwm(i64 noundef 1) #[[ATTR3:[0-9]+]]
+// CHECK-NEXT:    [[NEW_ISNULL:%.*]] = icmp eq ptr [[CALL]], null
+// CHECK-NEXT:    br i1 [[NEW_ISNULL]], label [[NEW_CONT:%.*]], label [[NEW_NOTNULL:%.*]]
+// CHECK:       new.notnull:
+// CHECK-NEXT:    call void @_ZN1AC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[CALL]])
+// CHECK-NEXT:    br label [[NEW_CONT]]
+// CHECK:       new.cont:
+// CHECK-NEXT:    [[TMP0:%.*]] = phi ptr [ [[CALL]], [[NEW_NOTNULL]] ], [ null, [[ENTRY:%.*]] ]
+// CHECK-NEXT:    ret ptr [[TMP0]]
+//
+A *test0() {
+  return new A();
+}
+
+// CHECK-LABEL: @_Z5test1v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CALL:%.*]] = call noalias noundef ptr @_Znwm(i64 noundef 4) #[[ATTR3]]
+// CHECK-NEXT:    ret ptr [[CALL]]
+//
+int *test1() {
+  return new int;
+}

diff  --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index 8060e52d5e8fd..65ba66fa325f5 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -302,7 +302,6 @@
 // RUN:     -fno-reorder-blocks -freorder-blocks                              \
 // RUN:     -fno-schedule-insns2 -fschedule-insns2                            \
 // RUN:     -fno-stack-check                                                  \
-// RUN:     -fno-check-new -fcheck-new                                        \
 // RUN:     -ffriend-injection                                                \
 // RUN:     -fno-implement-inlines -fimplement-inlines                        \
 // RUN:     -fstack-check                                                     \


        


More information about the cfe-commits mailing list