Merge remote-tracking branch 'origin/swift-4.0-branch' into stable
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 6ffffae..4e025a8 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -38,7 +38,7 @@
 const char *TypeCheckKinds[] = {
     "load of", "store to", "reference binding to", "member access within",
     "member call on", "constructor call on", "downcast of", "downcast of",
-    "upcast of", "cast to virtual base of"};
+    "upcast of", "cast to virtual base of", "_Nonnull binding to"};
 }
 
 static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
@@ -472,7 +472,8 @@
   Die();
 }
 
-static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) {
+static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts,
+                                bool IsAttr) {
   SourceLocation Loc = Data->Loc.acquire();
   ErrorType ET = ErrorType::InvalidNullReturn;
 
@@ -484,21 +485,35 @@
   Diag(Loc, DL_Error, "null pointer returned from function declared to never "
                       "return null");
   if (!Data->AttrLoc.isInvalid())
-    Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here");
+    Diag(Data->AttrLoc, DL_Note, "%0 specified here")
+        << (IsAttr ? "returns_nonnull attribute"
+                   : "_Nonnull return type annotation");
 }
 
 void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) {
   GET_REPORT_OPTIONS(false);
-  handleNonNullReturn(Data, Opts);
+  handleNonNullReturn(Data, Opts, true);
 }
 
 void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
   GET_REPORT_OPTIONS(true);
-  handleNonNullReturn(Data, Opts);
+  handleNonNullReturn(Data, Opts, true);
   Die();
 }
 
-static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) {
+void __ubsan::__ubsan_handle_nullability_return(NonNullReturnData *Data) {
+  GET_REPORT_OPTIONS(false);
+  handleNonNullReturn(Data, Opts, false);
+}
+
+void __ubsan::__ubsan_handle_nullability_return_abort(NonNullReturnData *Data) {
+  GET_REPORT_OPTIONS(true);
+  handleNonNullReturn(Data, Opts, false);
+  Die();
+}
+
+static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
+                             bool IsAttr) {
   SourceLocation Loc = Data->Loc.acquire();
   ErrorType ET = ErrorType::InvalidNullArgument;
 
@@ -507,20 +522,34 @@
 
   ScopedReport R(Opts, Loc, ET);
 
-  Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to "
-       "never be null") << Data->ArgIndex;
+  Diag(Loc, DL_Error,
+       "null pointer passed as argument %0, which is declared to "
+       "never be null")
+      << Data->ArgIndex;
   if (!Data->AttrLoc.isInvalid())
-    Diag(Data->AttrLoc, DL_Note, "nonnull attribute specified here");
+    Diag(Data->AttrLoc, DL_Note, "%0 specified here")
+        << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation");
 }
 
 void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
   GET_REPORT_OPTIONS(false);
-  handleNonNullArg(Data, Opts);
+  handleNonNullArg(Data, Opts, true);
 }
 
 void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
   GET_REPORT_OPTIONS(true);
-  handleNonNullArg(Data, Opts);
+  handleNonNullArg(Data, Opts, true);
+  Die();
+}
+
+void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) {
+  GET_REPORT_OPTIONS(false);
+  handleNonNullArg(Data, Opts, false);
+}
+
+void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) {
+  GET_REPORT_OPTIONS(true);
+  handleNonNullArg(Data, Opts, false);
   Die();
 }
 
diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h
index 350eb91..5857bc2 100644
--- a/lib/ubsan/ubsan_handlers.h
+++ b/lib/ubsan/ubsan_handlers.h
@@ -136,8 +136,10 @@
   SourceLocation AttrLoc;
 };
 
-/// \brief Handle returning null from function with returns_nonnull attribute.
+/// \brief Handle returning null from function with the returns_nonnull
+/// attribute, or a return type annotated with _Nonnull.
 RECOVERABLE(nonnull_return, NonNullReturnData *Data)
+RECOVERABLE(nullability_return, NonNullReturnData *Data)
 
 struct NonNullArgData {
   SourceLocation Loc;
@@ -145,8 +147,10 @@
   int ArgIndex;
 };
 
-/// \brief Handle passing null pointer to function with nonnull attribute.
+/// \brief Handle passing null pointer to a function parameter with the nonnull
+/// attribute, or a _Nonnull type annotation.
 RECOVERABLE(nonnull_arg, NonNullArgData *Data)
+RECOVERABLE(nullability_arg, NonNullArgData *Data)
 
 /// \brief Known CFI check kinds.
 /// Keep in sync with the enum of the same name in CodeGenFunction.h
diff --git a/test/ubsan/TestCases/Misc/nullability.c b/test/ubsan/TestCases/Misc/nullability.c
new file mode 100644
index 0000000..37b8ddc
--- /dev/null
+++ b/test/ubsan/TestCases/Misc/nullability.c
@@ -0,0 +1,64 @@
+// RUN: %clang -w -fsanitize=nullability-arg,nullability-assign,nullability-return %s -O3 -o %t
+// RUN: %run %t foo 2>&1 | count 0
+// RUN: %run %t 2>&1 | FileCheck %s
+
+// CHECK: nullability.c:[[@LINE+2]]:51: runtime error: null pointer returned from function declared to never return null
+// CHECK-NEXT: nullability.c:[[@LINE+1]]:6: note: _Nonnull return type annotation specified here
+int *_Nonnull nonnull_retval1(int *p) { return p; }
+
+// CHECK: nullability.c:1001:19: runtime error: null pointer passed as argument 1, which is declared to never be null
+// CHECK-NEXT: nullability.c:[[@LINE+3]]:36: note: _Nonnull type annotation specified here
+// CHECK: nullability.c:1001:22: runtime error: null pointer passed as argument 2, which is declared to never be null
+// CHECK-NEXT: nullability.c:[[@LINE+1]]:56: note: _Nonnull type annotation specified here
+int *_Nonnull nonnull_retval2(int *_Nonnull arg1, int *_Nonnull arg2,
+                              int *_Nullable arg3, int *arg4, int arg5, ...) {
+  return arg1;
+}
+
+// CHECK: nullability.c:1002:15: runtime error: null pointer passed as argument 1, which is declared to never be null
+// CHECK-NEXT: nullability.c:[[@LINE+1]]:23: note: _Nonnull type annotation specified here
+void nonnull_arg(int *_Nonnull p) {}
+
+void nonnull_assign1(int *p) {
+  int *_Nonnull local;
+// CHECK: nullability.c:[[@LINE+1]]:9: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+  local = p;
+}
+
+void nonnull_assign2(int *p) {
+  int *_Nonnull arr[1];
+  // CHECK: nullability.c:[[@LINE+1]]:10: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+  arr[0] = p;
+}
+
+struct S1 {
+  int *_Nonnull mptr;
+};
+
+void nonnull_assign3(int *p) {
+  struct S1 s;
+  // CHECK: nullability.c:[[@LINE+1]]:10: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+  s.mptr = p;
+}
+
+// CHECK: nullability.c:[[@LINE+1]]:52: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+void nonnull_init1(int *p) { int *_Nonnull local = p; }
+
+// CHECK: nullability.c:[[@LINE+2]]:53: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+// CHECK: nullability.c:[[@LINE+1]]:56: runtime error: _Nonnull binding to null pointer of type 'int * _Nonnull'
+void nonnull_init2(int *p) { int *_Nonnull arr[] = {p, p}; }
+
+int main(int argc, char **argv) {
+  int *p = (argc > 1) ? &argc : ((int *)0);
+
+#line 1000
+  nonnull_retval1(p);
+  nonnull_retval2(p, p, p, p, 0, 0, 0, 0);
+  nonnull_arg(p);
+  nonnull_assign1(p);
+  nonnull_assign2(p);
+  nonnull_assign3(p);
+  nonnull_init1(p);
+  nonnull_init2(p);
+  return 0;
+}