aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-08-01 09:52:43 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2014-08-01 09:52:43 +0200
commit944fa280bc92d197c443e369bb24405f007d46ab (patch)
tree893b88f145db7b629d24315901550a2b349d00ae /gcc/testsuite
parentbbe2542f728dbd46ffc9997537e62228173ffa24 (diff)
downloadgcc-944fa280bc92d197c443e369bb24405f007d46ab.zip
gcc-944fa280bc92d197c443e369bb24405f007d46ab.tar.gz
gcc-944fa280bc92d197c443e369bb24405f007d46ab.tar.bz2
opts.c (common_handle_option): Handle -fsanitize=alignment.
* opts.c (common_handle_option): Handle -fsanitize=alignment. * ubsan.h (enum ubsan_null_ckind): Add UBSAN_CTOR_CALL. (ubsan_expand_bounds_ifn, ubsan_expand_null_ifn): Change return type to bool. * stor-layout.h (min_align_of_type): New prototype. * asan.c (pass_sanopt::execute): Don't perform gsi_next if ubsan_expand* told us not to do it. Remove the extra gsi_end_p check. * ubsan.c: Include builtins.h. (ubsan_expand_bounds_ifn): Change return type to bool, always return true. (ubsan_expand_null_ifn): Change return type to bool, change argument to gimple_stmt_iterator *. Handle both null and alignment sanitization, take type from ckind argument's type rather than first argument. (instrument_member_call): Removed. (instrument_mem_ref): Remove t argument, add mem and base arguments. Handle both null and alignment sanitization, don't say whole struct access is member access. Build 3 argument IFN_UBSAN_NULL call instead of 2 argument. (instrument_null): Adjust instrument_mem_ref caller. Don't instrument calls here. (pass_ubsan::gate, pass_ubsan::execute): Handle SANITIZE_ALIGNMENT like SANITIZE_NULL. * stor-layout.c (min_align_of_type): New function. * flag-types.h (enum sanitize_code): Add SANITIZE_ALIGNMENT. Or it into SANITIZE_UNDEFINED. * doc/invoke.texi (-fsanitize=alignment): Document. cp/ * cp-gimplify.c (cp_genericize_r): For -fsanitize=null and/or -fsanitize=alignment call ubsan_maybe_instrument_reference for casts to REFERENCE_TYPE and ubsan_maybe_instrument_member_call for calls to member functions. c-family/ * c-common.h (min_align_of_type): Removed prototype. * c-common.c (min_align_of_type): Removed. * c-ubsan.h (ubsan_maybe_instrument_reference, ubsan_maybe_instrument_member_call): New prototypes. * c-ubsan.c: Include stor-layout.h and builtins.h. (ubsan_maybe_instrument_reference_or_call, ubsan_maybe_instrument_reference, ubsan_maybe_instrument_call): New functions. testsuite/ * c-c++-common/ubsan/align-1.c: New test. * c-c++-common/ubsan/align-2.c: New test. * c-c++-common/ubsan/align-3.c: New test. * c-c++-common/ubsan/align-4.c: New test. * c-c++-common/ubsan/align-5.c: New test. * c-c++-common/ubsan/attrib-4.c: New test. * g++.dg/ubsan/align-1.C: New test. * g++.dg/ubsan/align-2.C: New test. * g++.dg/ubsan/align-3.C: New test. * g++.dg/ubsan/attrib-1.C: New test. * g++.dg/ubsan/null-1.C: New test. * g++.dg/ubsan/null-2.C: New test. From-SVN: r213406
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/align-1.c41
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/align-2.c56
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/align-3.c66
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/align-4.c14
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/align-5.c15
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/attrib-4.c15
-rw-r--r--gcc/testsuite/g++.dg/ubsan/align-1.C27
-rw-r--r--gcc/testsuite/g++.dg/ubsan/align-2.C45
-rw-r--r--gcc/testsuite/g++.dg/ubsan/align-3.C45
-rw-r--r--gcc/testsuite/g++.dg/ubsan/attrib-1.C27
-rw-r--r--gcc/testsuite/g++.dg/ubsan/null-1.C30
-rw-r--r--gcc/testsuite/g++.dg/ubsan/null-2.C39
13 files changed, 435 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 37b42b3..cf22371 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,18 @@
+2014-08-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/ubsan/align-1.c: New test.
+ * c-c++-common/ubsan/align-2.c: New test.
+ * c-c++-common/ubsan/align-3.c: New test.
+ * c-c++-common/ubsan/align-4.c: New test.
+ * c-c++-common/ubsan/align-5.c: New test.
+ * c-c++-common/ubsan/attrib-4.c: New test.
+ * g++.dg/ubsan/align-1.C: New test.
+ * g++.dg/ubsan/align-2.C: New test.
+ * g++.dg/ubsan/align-3.C: New test.
+ * g++.dg/ubsan/attrib-1.C: New test.
+ * g++.dg/ubsan/null-1.C: New test.
+ * g++.dg/ubsan/null-2.C: New test.
+
2014-08-01 Tom de Vries <tom@codesourcery.com>
* lib/target-supports.exp (check_effective_target_glibc)
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-1.c b/gcc/testsuite/c-c++-common/ubsan/align-1.c
new file mode 100644
index 0000000..2e40e83
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/align-1.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+
+struct S { int a; char b; long long c; short d[10]; };
+struct T { char a; long long b; };
+struct U { char a; int b; int c; long long d; struct S e; struct T f; };
+struct V { long long a; struct S b; struct T c; struct U u; } v;
+
+__attribute__((noinline, noclone)) void
+f1 (int *p, int *q, char *r, long long *s)
+{
+ *p = *q + *r + *s;
+}
+
+
+__attribute__((noinline, noclone)) int
+f2 (struct S *p)
+{
+ return p->a;
+}
+
+__attribute__((noinline, noclone)) long long
+f3 (struct S *p, int i)
+{
+ return p->c + p->d[1] + p->d[i];
+}
+
+__attribute__((noinline, noclone)) long long
+f4 (long long *p)
+{
+ return *p;
+}
+
+int
+main ()
+{
+ f1 (&v.u.b, &v.u.c, &v.u.a, &v.u.d);
+ if (f2 (&v.u.e) + f3 (&v.u.e, 4) + f4 (&v.u.f.b) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-2.c b/gcc/testsuite/c-c++-common/ubsan/align-2.c
new file mode 100644
index 0000000..071de8c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/align-2.c
@@ -0,0 +1,56 @@
+/* Limit this to known non-strict alignment targets. */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-fsanitize=alignment" } */
+
+struct S { int a; char b; long long c; short d[10]; };
+struct T { char a; long long b; };
+struct U { char a; int b; int c; long long d; struct S e; struct T f; } __attribute__((packed));
+struct V { long long a; struct S b; struct T c; struct U u; } v;
+
+__attribute__((noinline, noclone)) void
+f1 (int *p, int *q, char *r, long long *s)
+{
+ *p =
+ *q
+ + *r
+ + *s;
+}
+
+
+__attribute__((noinline, noclone)) int
+f2 (struct S *p)
+{
+ return p->a;
+}
+
+__attribute__((noinline, noclone)) long long
+f3 (struct S *p, int i)
+{
+ return p->c
+ + p->d[1]
+ + p->d[i];
+}
+
+__attribute__((noinline, noclone)) long long
+f4 (long long *p)
+{
+ return *p;
+}
+
+int
+main ()
+{
+ f1 (&v.u.b, &v.u.c, &v.u.a, &v.u.d);
+ if (f2 (&v.u.e) + f3 (&v.u.e, 4) + f4 (&v.u.f.b) != 0)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-output "\.c:(14|15):\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
+/* { dg-output "\.c:16:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:(13|16):\[0-9]*: \[^\n\r]*store to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
+/* { dg-output "\.c:23:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:(29|30):\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:30:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:31:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\.c:37:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-3.c b/gcc/testsuite/c-c++-common/ubsan/align-3.c
new file mode 100644
index 0000000..a509fa9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/align-3.c
@@ -0,0 +1,66 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover" } */
+
+int c;
+
+__attribute__((noinline, noclone)) void
+f1 (int *a, char *b)
+{
+ __builtin_memcpy (a, b, sizeof (*a));
+}
+
+__attribute__((noinline, noclone)) void
+f2 (int *a, char *b)
+{
+ __builtin_memcpy (b, a, sizeof (*a));
+}
+
+__attribute__((noinline, noclone)) void
+f3 (char *b)
+{
+ __builtin_memcpy (&c, b, sizeof (c));
+}
+
+__attribute__((noinline, noclone)) void
+f4 (char *b)
+{
+ __builtin_memcpy (b, &c, sizeof (c));
+}
+
+struct T
+{
+ char a;
+ short b;
+ int c;
+ long d;
+ long long e;
+ short f;
+ float g;
+ double h;
+ long double i;
+} __attribute__((packed));
+
+__attribute__((noinline, noclone)) int
+f5 (struct T *p)
+{
+ return p->a + p->b + p->c + p->d + p->e + p->f + p->g + p->h + p->i;
+}
+
+int
+main ()
+{
+ struct S { int a; char b[sizeof (int) + 1]; } s;
+ s.a = 6;
+ f2 (&s.a, &s.b[1]);
+ f1 (&s.a, &s.b[1]);
+ c = s.a + 1;
+ f4 (&s.b[1]);
+ f3 (&s.b[1]);
+ if (c != 7 || s.a != 6)
+ __builtin_abort ();
+ struct U { long long a; long double b; char c; struct T d; } u;
+ __builtin_memset (&u, 0, sizeof (u));
+ if (f5 (&u.d) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-4.c b/gcc/testsuite/c-c++-common/ubsan/align-4.c
new file mode 100644
index 0000000..3252595
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/align-4.c
@@ -0,0 +1,14 @@
+/* Limit this to known non-strict alignment targets. */
+/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */
+/* { dg-options "-fsanitize=null,alignment" } */
+
+#include "align-2.c"
+
+/* { dg-output "\.c:(14|15):\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:16:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:(13|16):\[0-9]*: \[^\n\r]*store to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:23:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:(29|30):\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:30:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:31:\[0-9]*: \[^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct S', which requires \[48] byte alignment.*" } */
+/* { dg-output "\[^\n\r]*\.c:37:\[0-9]*: \[^\n\r]*load of misaligned address 0x\[0-9a-fA-F]* for type 'long long int', which requires \[48] byte alignment" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/align-5.c b/gcc/testsuite/c-c++-common/ubsan/align-5.c
new file mode 100644
index 0000000..b94e167
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/align-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=null -fsanitize=alignment -O2" } */
+/* Check that when optimizing if we know the alignment is right
+ and we are not doing -fsanitize=null instrumentation we don't
+ instrument the alignment check. */
+
+__attribute__((noinline, noclone)) int
+foo (char *p)
+{
+ p = (char *) __builtin_assume_aligned (p, __alignof__(int));
+ int *q = (int *) p;
+ return *q;
+}
+
+/* { dg-final { scan-assembler-not "__ubsan_handle" } } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/attrib-4.c b/gcc/testsuite/c-c++-common/ubsan/attrib-4.c
new file mode 100644
index 0000000..ba0f00c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/attrib-4.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+/* Test that we don't instrument functions marked with
+ no_sanitize_undefined attribute. */
+
+struct S { int a[16]; };
+
+__attribute__((no_sanitize_undefined)) long long
+foo (int *a, long long *b, struct S *c)
+{
+ return a[1] + *b + c->a[a[0]];
+}
+
+/* { dg-final { scan-assembler-not "__ubsan_handle" } } */
diff --git a/gcc/testsuite/g++.dg/ubsan/align-1.C b/gcc/testsuite/g++.dg/ubsan/align-1.C
new file mode 100644
index 0000000..65b1222
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/align-1.C
@@ -0,0 +1,27 @@
+// { dg-do run }
+// { dg-options "-fsanitize=alignment -Wall -Wno-unused-variable -std=c++11" }
+
+typedef const long int L;
+int a = 1;
+L b = 2;
+
+int
+main (void)
+{
+ int *p = &a;
+ L *l = &b;
+
+ int &r = *p;
+ auto &r2 = *p;
+ L &lr = *l;
+
+ // Try an rvalue reference.
+ auto &&r3 = *p;
+
+ // Don't evaluate the reference initializer twice.
+ int i = 1;
+ int *q = &i;
+ int &qr = ++*q;
+ if (i != 2)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ubsan/align-2.C b/gcc/testsuite/g++.dg/ubsan/align-2.C
new file mode 100644
index 0000000..3e4f548
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/align-2.C
@@ -0,0 +1,45 @@
+// Limit this to known non-strict alignment targets.
+// { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } }
+// { dg-options "-fsanitize=alignment -Wall -Wno-unused-variable -std=c++11" }
+
+typedef const long int L;
+struct S { long int l; char buf[1 + sizeof (int) + sizeof (L)]; } s;
+struct T { char a; int b; long int c; } __attribute__((packed));
+struct U { long int a; struct T b; } u;
+
+int
+main (void)
+{
+ int *p = (int *) &s.buf[1];
+ L *l = (L *) &s.buf[1 + sizeof(int)];
+
+ int &r = *p;
+ auto &r2 = *p;
+ L &lr = *l;
+
+ // Try an rvalue reference.
+ auto &&r3 = *p;
+
+ // Don't evaluate the reference initializer twice.
+ int i = 1;
+ int *q = &i;
+ int &qr = ++*q;
+ if (i != 2)
+ __builtin_abort ();
+
+ int *s = &u.b.b;
+ L *t = &u.b.c;
+ int &r4 = *s;
+ auto &r5 = *s;
+ L &lr2 = *t;
+ auto &&r6 = *s;
+}
+
+// { dg-output "\.C:16:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" }
+// { dg-output "\.C:17:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" }
+// { dg-output "\.C:18:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'const L', which requires \[48] byte alignment.*" }
+// { dg-output "\.C:21:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" }
+// { dg-output "\.C:32:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" }
+// { dg-output "\.C:33:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment.*" }
+// { dg-output "\.C:34:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'const L', which requires \[48] byte alignment.*" }
+// { dg-output "\.C:35:\[0-9]*:\[\^\n\r]*reference binding to misaligned address 0x\[0-9a-fA-F]* for type 'int', which requires 4 byte alignment" }
diff --git a/gcc/testsuite/g++.dg/ubsan/align-3.C b/gcc/testsuite/g++.dg/ubsan/align-3.C
new file mode 100644
index 0000000..1cc40fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/align-3.C
@@ -0,0 +1,45 @@
+// Limit this to known non-strict alignment targets.
+// { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } }
+// { dg-options "-fsanitize=alignment -Wall -Wno-unused-variable -std=c++11" }
+
+#include <new>
+
+struct U
+{
+ int a;
+ void foo () {}
+};
+struct V
+{
+ V () : a (0) {};
+ ~V () { a = 0; };
+ int a;
+ void foo () {}
+ static void bar () {}
+};
+struct S { long int l; char buf[1 + sizeof (U) + 2 * sizeof (V)]; } s;
+
+int
+main (void)
+{
+ U *p = (U *) &s.buf[1];
+ p->foo ();
+ char *q = &s.buf[1 + sizeof (U)];
+ V *u = new (q) V;
+ u->a = 1;
+ u->~V ();
+ V *v = new (&s.buf[1 + sizeof (U) + sizeof (V)]) V;
+ v->foo ();
+ v->bar (); // We don't instrument this right now.
+ v->~V ();
+}
+
+// { dg-output "\.C:26:\[0-9]*:\[\^\n\r]*member call on misaligned address 0x\[0-9a-fA-F]* for type 'struct U', which requires 4 byte alignment.*" }
+// { dg-output "\.C:28:\[0-9]*:\[\^\n\r]*constructor call on misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:14:\[0-9]*:\[\^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:29:\[0-9]*:\[\^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:30:\[0-9]*:\[\^\n\r]*member call on misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:15:\[0-9]*:\[\^\n\r]*member access within misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:31:\[0-9]*:\[\^\n\r]*constructor call on misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:32:\[0-9]*:\[\^\n\r]*member call on misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment.*" }
+// { dg-output "\.C:34:\[0-9]*:\[\^\n\r]*member call on misaligned address 0x\[0-9a-fA-F]* for type 'struct V', which requires 4 byte alignment" }
diff --git a/gcc/testsuite/g++.dg/ubsan/attrib-1.C b/gcc/testsuite/g++.dg/ubsan/attrib-1.C
new file mode 100644
index 0000000..f701d02
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/attrib-1.C
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-fsanitize=undefined -Wall -Wno-unused-variable -std=c++11" }
+
+typedef const long int L;
+
+__attribute__((no_sanitize_undefined)) void
+foo (int *p, L *l)
+{
+ int &r = *p;
+ auto &r2 = *p;
+ L &lr = *l;
+ auto &&r3 = *p;
+}
+
+struct U
+{
+ int a;
+ void foo () {}
+};
+
+__attribute__((no_sanitize_undefined)) void
+bar (U *p)
+{
+ p->foo ();
+}
+
+// { dg-final { scan-assembler-not "__ubsan_handle" } }
diff --git a/gcc/testsuite/g++.dg/ubsan/null-1.C b/gcc/testsuite/g++.dg/ubsan/null-1.C
new file mode 100644
index 0000000..e1524b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/null-1.C
@@ -0,0 +1,30 @@
+// { dg-do run }
+// { dg-options "-fsanitize=null -Wall -Wno-unused-variable -std=c++11" }
+
+typedef const long int L;
+
+int
+main (void)
+{
+ int *p = 0;
+ L *l = 0;
+
+ int &r = *p;
+ auto &r2 = *p;
+ L &lr = *l;
+
+ // Try an rvalue reference.
+ auto &&r3 = *p;
+
+ // Don't evaluate the reference initializer twice.
+ int i = 1;
+ int *q = &i;
+ int &qr = ++*q;
+ if (i != 2)
+ __builtin_abort ();
+}
+
+// { dg-output "reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'const L'(\n|\r\n|\r)" }
+// { dg-output "\[^\n\r]*reference binding to null pointer of type 'int'(\n|\r\n|\r)" }
diff --git a/gcc/testsuite/g++.dg/ubsan/null-2.C b/gcc/testsuite/g++.dg/ubsan/null-2.C
new file mode 100644
index 0000000..88f387e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/null-2.C
@@ -0,0 +1,39 @@
+// Limit this to known non-strict alignment targets.
+// { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } }
+// { dg-options "-fsanitize=null -Wall -Wno-unused-variable -std=c++11" }
+
+#include <new>
+
+struct U
+{
+ int a;
+ void foo () {}
+};
+struct V
+{
+ V () {};
+ ~V () {};
+ int a;
+ void foo () {}
+ static void bar () {}
+};
+struct S { long int l; char buf[1 + sizeof (U) + 2 * sizeof (V)]; } s;
+
+int
+main (void)
+{
+ U *p = 0;
+ p->foo ();
+ char *q = 0;
+ V *u = new (q) V;
+ u->~V ();
+ V *v = new (q) V;
+ v->foo ();
+ v->bar (); // We don't instrument this right now.
+ v->~V ();
+}
+
+// { dg-output "\.C:26:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct U'.*" }
+// { dg-output "\.C:29:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'.*" }
+// { dg-output "\.C:31:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'.*" }
+// { dg-output "\.C:33:\[0-9]*:\[\^\n\r]*member call on null pointer of type 'struct V'" }