manojgupta updated this revision to Diff 155891.
manojgupta added a comment.

Added helper text, updated tests.


Repository:
  rC Clang

https://reviews.llvm.org/D47894

Files:
  docs/ClangCommandLineReference.rst
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGCall.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/delete-null-pointer-checks.c
  test/CodeGen/nonnull.c
  test/CodeGen/vla.c
  test/CodeGenCXX/address-space-ref.cpp
  test/CodeGenCXX/constructors.cpp
  test/CodeGenCXX/temporaries.cpp
  test/Driver/clang_f_opts.c
  test/Sema/nonnull.c

Index: test/Sema/nonnull.c
===================================================================
--- test/Sema/nonnull.c
+++ test/Sema/nonnull.c
@@ -1,5 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 // rdar://9584012
+//
+// Verify All warnings are still issued with the option -fno-delete-null-pointer-checks
+// if nullptr is passed to function with nonnull attribute.
+// RUN: %clang_cc1 -fsyntax-only -fno-delete-null-pointer-checks -verify %s
 
 typedef struct {
 	char *str;
Index: test/Driver/clang_f_opts.c
===================================================================
--- test/Driver/clang_f_opts.c
+++ test/Driver/clang_f_opts.c
@@ -348,7 +348,6 @@
 // RUN: -fwhole-program                                                       \
 // RUN: -fcaller-saves                                                        \
 // RUN: -freorder-blocks                                                      \
-// RUN: -fdelete-null-pointer-checks                                          \
 // RUN: -ffat-lto-objects                                                     \
 // RUN: -fmerge-constants                                                     \
 // RUN: -finline-small-functions                                              \
@@ -414,7 +413,6 @@
 // CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported
 // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported
-// CHECK-WARNING-DAG: optimization flag '-fdelete-null-pointer-checks' is not supported
 // CHECK-WARNING-DAG: optimization flag '-ffat-lto-objects' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported
 // CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported
@@ -526,3 +524,10 @@
 // RUN: %clang -### -S -fno-merge-all-constants -fmerge-all-constants %s 2>&1 | FileCheck -check-prefix=CHECK-MERGE-ALL-CONSTANTS %s
 // CHECK-NO-MERGE-ALL-CONSTANTS-NOT: "-fmerge-all-constants"
 // CHECK-MERGE-ALL-CONSTANTS: "-fmerge-all-constants"
+
+// RUN: %clang -### -S -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fdelete-null-pointer-checks -fno-delete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NO-NULL-POINTER-CHECKS %s
+// RUN: %clang -### -S -fno-delete-null-pointer-checks -fdelete-null-pointer-checks %s 2>&1 | FileCheck -check-prefix=CHECK-NULL-POINTER-CHECKS %s
+// CHECK-NO-NULL-POINTER-CHECKS: "-fno-delete-null-pointer-checks"
+// CHECK-NULL-POINTER-CHECKS-NOT: "-fno-delete-null-pointer-checks"
Index: test/CodeGenCXX/temporaries.cpp
===================================================================
--- test/CodeGenCXX/temporaries.cpp
+++ test/CodeGenCXX/temporaries.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID
 
 namespace PR16263 {
   const unsigned int n = 1234;
@@ -347,7 +348,8 @@
   struct D;
   D& zed(B);
   void foobar() {
-    // CHECK: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
+    // NULL-INVALID: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
+    // NULL-VALID: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
     zed(foo);
   }
 }
Index: test/CodeGenCXX/constructors.cpp
===================================================================
--- test/CodeGenCXX/constructors.cpp
+++ test/CodeGenCXX/constructors.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s --implicit-check-not=should_not_appear_in_output --check-prefixes=CHECK,NULL-VALID
 
 struct Member { int x; Member(); Member(int); Member(const Member &); };
 struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); };
@@ -21,10 +22,12 @@
 A::A(struct Undeclared &ref) : mem(0) {}
 
 // Check that delegation works.
-// CHECK-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1AC2ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
 // CHECK: call void @_ZN6MemberC1Ei(
 
-// CHECK-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1AC1ER10Undeclared(%struct.A* %this, %struct.Undeclared* %ref) unnamed_addr
 // CHECK: call void @_ZN1AC2ER10Undeclared(
 
 A::A(ValueClass v) : mem(v.y - v.x) {}
@@ -43,11 +46,13 @@
 
 B::B(struct Undeclared &ref) : A(ref), mem(1) {}
 
-// CHECK-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1BC2ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
 // CHECK: call void @_ZN1AC2ER10Undeclared(
 // CHECK: call void @_ZN6MemberC1Ei(
 
-// CHECK-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-INVALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* nonnull %ref) unnamed_addr
+// NULL-VALID-LABEL: define void @_ZN1BC1ER10Undeclared(%struct.B* %this, %struct.Undeclared* %ref) unnamed_addr
 // CHECK: call void @_ZN1BC2ER10Undeclared(
 
 
Index: test/CodeGenCXX/address-space-ref.cpp
===================================================================
--- test/CodeGenCXX/address-space-ref.cpp
+++ test/CodeGenCXX/address-space-ref.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fno-delete-null-pointer-checks -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID
 
 // For a reference to a complete type, output the dereferenceable attribute (in
 // any address space).
@@ -29,6 +30,7 @@
   return x;
 }
 
-// CHECK: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y)
+// NULL-INVALID: define nonnull %class.bc* @_Z4bar2R2bcS0_(%class.bc* nonnull %x, %class.bc* nonnull %y)
+// NULL-VALID: define %class.bc* @_Z4bar2R2bcS0_(%class.bc* %x, %class.bc* %y)
 
 
Index: test/CodeGen/vla.c
===================================================================
--- test/CodeGen/vla.c
+++ test/CodeGen/vla.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,NULL-INVALID
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -fno-delete-null-pointer-checks -o - | FileCheck %s -check-prefixes=CHECK,NULL-VALID
 
 int b(char* x);
 
@@ -202,5 +203,6 @@
 // CHECK: define void @test8(i32* dereferenceable(12) %a)
 
 void test9(int n, int a[static n]) { }
-// CHECK: define void @test9(i32 %n, i32* nonnull %a)
+// NULL-INVALID: define void @test9(i32 %n, i32* nonnull %a)
+// NULL-VALID: define void @test9(i32 %n, i32* %a)
 
Index: test/CodeGen/nonnull.c
===================================================================
--- test/CodeGen/nonnull.c
+++ test/CodeGen/nonnull.c
@@ -1,32 +1,39 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck -check-prefix=NULL-INVALID %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -fno-delete-null-pointer-checks < %s | FileCheck -check-prefix=NULL-VALID %s
 
-// CHECK: define void @foo(i32* nonnull %x)
+// NULL-INVALID: define void @foo(i32* nonnull %x)
+// NULL-VALID: define void @foo(i32* %x)
 void foo(int * __attribute__((nonnull)) x) {
   *x = 0;
 }
 
-// CHECK: define void @bar(i32* nonnull %x)
+// NULL-INVALID: define void @bar(i32* nonnull %x)
+// NULL-VALID: define void @bar(i32* %x)
 void bar(int * x) __attribute__((nonnull(1)))  {
   *x = 0;
 }
 
-// CHECK: define void @bar2(i32* %x, i32* nonnull %y)
+// NULL-INVALID: define void @bar2(i32* %x, i32* nonnull %y)
+// NULL-VALID: define void @bar2(i32* %x, i32* %y)
 void bar2(int * x, int * y) __attribute__((nonnull(2)))  {
   *x = 0;
 }
 
 static int a;
-// CHECK: define nonnull i32* @bar3()
+// NULL-INVALID: define nonnull i32* @bar3()
+// NULL-VALID: define i32* @bar3()
 int * bar3() __attribute__((returns_nonnull))  {
   return &a;
 }
 
-// CHECK: define i32 @bar4(i32 %n, i32* nonnull %p)
+// NULL-INVALID: define i32 @bar4(i32 %n, i32* nonnull %p)
+// NULL-VALID: define i32 @bar4(i32 %n, i32* %p)
 int bar4(int n, int *p) __attribute__((nonnull)) {
   return n + *p;
 }
 
-// CHECK: define i32 @bar5(i32 %n, i32* nonnull %p)
+// NULL-INVALID: define i32 @bar5(i32 %n, i32* nonnull %p)
+// NULL-VALID: define i32 @bar5(i32 %n, i32* %p)
 int bar5(int n, int *p) __attribute__((nonnull(1, 2))) {
   return n + *p;
 }
@@ -37,15 +44,18 @@
   double d;
 } TransparentUnion __attribute__((transparent_union));
 
-// CHECK: define i32 @bar6(i64 %
+// NULL-INVALID: define i32 @bar6(i64 %
+// NULL-VALID: define i32 @bar6(i64 %
 int bar6(TransparentUnion tu) __attribute__((nonnull(1))) {
   return *tu.p;
 }
 
-// CHECK: define void @bar7(i32* nonnull %a, i32* nonnull %b)
+// NULL-INVALID: define void @bar7(i32* nonnull %a, i32* nonnull %b)
+// NULL-VALID: define void @bar7(i32* %a, i32* %b)
 void bar7(int *a, int *b) __attribute__((nonnull(1)))
 __attribute__((nonnull(2))) {}
 
-// CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
+// NULL-INVALID: define void @bar8(i32* nonnull %a, i32* nonnull %b)
+// NULL-VALID: define void @bar8(i32* %a, i32* %b)
 void bar8(int *a, int *b) __attribute__((nonnull))
 __attribute__((nonnull(1))) {}
Index: test/CodeGen/delete-null-pointer-checks.c
===================================================================
--- /dev/null
+++ test/CodeGen/delete-null-pointer-checks.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s | FileCheck -check-prefix=NULL-POINTER-INVALID  %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -O2 -o - %s -fno-delete-null-pointer-checks | FileCheck -check-prefix=NULL-POINTER-VALID  %s
+
+// Test that clang does not remove the null pointer check with
+// -fno-delete-null-pointer-checks.
+int null_check(int *P) {
+// NULL-POINTER-VALID: %[[TOBOOL:.*]] = icmp eq i32* %P, null
+// NULL-POINTER-INVALID-NOT: icmp eq
+// NULL-POINTER-VALID: %[[SEL:.*]] = select i1 %[[TOBOOL:.*]], i32* null, i32*
+// NULL-POINTER-INVALID-NOT: select i1
+// NULL-POINTER-VALID: load i32, i32* %[[SEL:.*]]
+  int *Q = P;
+  if (P) {
+    Q = P + 2;
+  }
+  return *Q;
+}
+
+// NULL-POINTER-INVALID-NOT: attributes #0 = {{.*}} "null-pointer-is-valid"="true"
+// NULL-POINTER-VALID: attributes #0 = {{.*}} "null-pointer-is-valid"="true"
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -746,6 +746,8 @@
 
   Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
 
+  Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks);
+
   Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate);
 
   Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -3344,6 +3344,10 @@
                    options::OPT_fno_merge_all_constants, false))
     CmdArgs.push_back("-fmerge-all-constants");
 
+  if (Args.hasFlag(options::OPT_fno_delete_null_pointer_checks,
+                   options::OPT_fdelete_null_pointer_checks, false))
+    CmdArgs.push_back("-fno-delete-null-pointer-checks");
+
   // LLVM Code Generator Options.
 
   if (Args.hasArg(options::OPT_frewrite_map_file) ||
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1734,6 +1734,8 @@
     FuncAttrs.addAttribute("less-precise-fpmad",
                            llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
 
+    if (CodeGenOpts.NullPointerIsValid)
+      FuncAttrs.addAttribute("null-pointer-is-valid", "true");
     if (!CodeGenOpts.FPDenormalMode.empty())
       FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode);
 
@@ -1867,7 +1869,8 @@
     }
     if (TargetDecl->hasAttr<RestrictAttr>())
       RetAttrs.addAttribute(llvm::Attribute::NoAlias);
-    if (TargetDecl->hasAttr<ReturnsNonNullAttr>())
+    if (TargetDecl->hasAttr<ReturnsNonNullAttr>() &&
+        !CodeGenOpts.NullPointerIsValid)
       RetAttrs.addAttribute(llvm::Attribute::NonNull);
     if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
       FuncAttrs.addAttribute("no_caller_saved_registers");
@@ -1974,7 +1977,8 @@
     if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
       RetAttrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
                                         .getQuantity());
-    else if (getContext().getTargetAddressSpace(PTy) == 0)
+    else if (getContext().getTargetAddressSpace(PTy) == 0 &&
+             !CodeGenOpts.NullPointerIsValid)
       RetAttrs.addAttribute(llvm::Attribute::NonNull);
   }
 
@@ -2083,7 +2087,8 @@
       if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
         Attrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
                                        .getQuantity());
-      else if (getContext().getTargetAddressSpace(PTy) == 0)
+      else if (getContext().getTargetAddressSpace(PTy) == 0 &&
+               !CodeGenOpts.NullPointerIsValid)
         Attrs.addAttribute(llvm::Attribute::NonNull);
     }
 
@@ -2343,7 +2348,8 @@
 
         if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
           if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(),
-                             PVD->getFunctionScopeIndex()))
+                             PVD->getFunctionScopeIndex()) &&
+              !CGM.getCodeGenOpts().NullPointerIsValid)
             AI->addAttr(llvm::Attribute::NonNull);
 
           QualType OTy = PVD->getOriginalType();
@@ -2362,7 +2368,8 @@
                 Attrs.addDereferenceableAttr(
                   getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
                 AI->addAttrs(Attrs);
-              } else if (getContext().getTargetAddressSpace(ETy) == 0) {
+              } else if (getContext().getTargetAddressSpace(ETy) == 0 &&
+                         !CGM.getCodeGenOpts().NullPointerIsValid) {
                 AI->addAttr(llvm::Attribute::NonNull);
               }
             }
@@ -2372,7 +2379,8 @@
             // we can't use the dereferenceable attribute, but in addrspace(0)
             // we know that it must be nonnull.
             if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
-                !getContext().getTargetAddressSpace(ArrTy->getElementType()))
+                !getContext().getTargetAddressSpace(ArrTy->getElementType()) &&
+                !CGM.getCodeGenOpts().NullPointerIsValid)
               AI->addAttr(llvm::Attribute::NonNull);
           }
 
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -130,6 +130,7 @@
 CODEGENOPT(NoImplicitFloat   , 1, 0) ///< Set when -mno-implicit-float is enabled.
 CODEGENOPT(NoInfsFPMath      , 1, 0) ///< Assume FP arguments, results not +-Inf.
 CODEGENOPT(NoSignedZeros     , 1, 0) ///< Allow ignoring the signedness of FP zero
+CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined.
 CODEGENOPT(Reassociate       , 1, 0) ///< Allow reassociation of FP math ops
 CODEGENOPT(ReciprocalMath    , 1, 0) ///< Allow FP divisions to be reassociated.
 CODEGENOPT(NoTrappingMath    , 1, 0) ///< Set when -fno-trapping-math is enabled.
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1076,6 +1076,13 @@
   Flags<[CC1Option]>;
 def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group<f_Group>;
 
+def fdelete_null_pointer_checks : Flag<["-"],
+  "fdelete-null-pointer-checks">, Group<f_Group>,
+  HelpText<"Assume that null pointers can not be dereferenced safely, and remove useless null checks">;
+def fno_delete_null_pointer_checks : Flag<["-"],
+  "fno-delete-null-pointer-checks">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Assume that it may be possible to safely dereference null pointers">;
+
 def frewrite_map_file : Separate<["-"], "frewrite-map-file">,
                         Group<f_Group>,
                         Flags<[ DriverOption, CC1Option ]>;
@@ -2843,8 +2850,6 @@
 defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
 defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm delete_null_pointer_checks : BooleanFFlag<"delete-null-pointer-checks">,
-    Group<clang_ignored_gcc_optimization_f_Group>;
 defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm friend_injection : BooleanFFlag<"friend-injection">, Group<clang_ignored_f_Group>;
Index: docs/ClangCommandLineReference.rst
===================================================================
--- docs/ClangCommandLineReference.rst
+++ docs/ClangCommandLineReference.rst
@@ -1543,6 +1543,10 @@
 
 Disable implicit builtin knowledge of a specific function
 
+.. option:: -fdelete-null-pointer-checks, -fno-delete-null-pointer-checks
+
+Assume that null pointers cannot be dereferenced safely and any code/data cannot reside at address zero.
+
 .. option:: -fno-elide-type
 
 Do not elide types when printing diagnostics
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to