--- gcc/config/bootstrap-ubsan.mk.mp	2013-11-12 13:46:13.345182065 +0100
+++ gcc/config/bootstrap-ubsan.mk	2013-11-12 13:46:49.812314016 +0100
@@ -2,6 +2,6 @@
 
 STAGE2_CFLAGS += -fsanitize=undefined
 STAGE3_CFLAGS += -fsanitize=undefined
-POSTSTAGE1_LDFLAGS += -fsanitize=undefined -static-libubsan -lpthread \
+POSTSTAGE1_LDFLAGS += -fsanitize=undefined -static-libubsan -lpthread -ldl \
 		      -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ubsan/ \
 		      -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ubsan/.libs
--- gcc/gcc/opts.c.mp	2013-11-12 13:46:13.354182104 +0100
+++ gcc/gcc/opts.c	2013-11-12 13:46:49.824314069 +0100
@@ -1446,6 +1446,7 @@ common_handle_option (struct gcc_options
 	      { "unreachable", SANITIZE_UNREACHABLE,
 		sizeof "unreachable" - 1 },
 	      { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 },
+	      { "null", SANITIZE_NULL, sizeof "null" - 1 },
 	      { NULL, 0, 0 }
 	    };
 	    const char *comma;
@@ -1487,6 +1488,10 @@ common_handle_option (struct gcc_options
 	    p = comma + 1;
 	  }
 
+	/* When instrumenting the pointers, we don't want to remove
+	   the null pointer checks.  */
+	if (flag_sanitize & SANITIZE_NULL)
+	  opts->x_flag_delete_null_pointer_checks = 0;
 	break;
       }
 
--- gcc/gcc/c-family/c-ubsan.c.mp	2013-11-12 13:46:13.348182077 +0100
+++ gcc/gcc/c-family/c-ubsan.c	2013-11-12 13:46:49.819314047 +0100
@@ -74,7 +74,8 @@ ubsan_instrument_division (location_t lo
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
   tree data = ubsan_create_data ("__ubsan_overflow_data",
-				 loc, ubsan_type_descriptor (type),
+				 loc, NULL,
+				 ubsan_type_descriptor (type, false),
 				 NULL_TREE);
   data = build_fold_addr_expr_loc (loc, data);
   tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW);
@@ -142,8 +143,10 @@ ubsan_instrument_shift (location_t loc,
      make sure it gets evaluated before the condition.  */
   t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
   tree data = ubsan_create_data ("__ubsan_shift_data",
-				 loc, ubsan_type_descriptor (type0),
-				 ubsan_type_descriptor (type1), NULL_TREE);
+				 loc, NULL,
+				 ubsan_type_descriptor (type0, false),
+				 ubsan_type_descriptor (type1, false),
+				 NULL_TREE);
 
   data = build_fold_addr_expr_loc (loc, data);
 
@@ -167,7 +170,9 @@ ubsan_instrument_vla (location_t loc, tr
 
   t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
   tree data = ubsan_create_data ("__ubsan_vla_data",
-				 loc, ubsan_type_descriptor (type), NULL_TREE);
+				 loc, NULL,
+				 ubsan_type_descriptor (type, false),
+				 NULL_TREE);
   data = build_fold_addr_expr_loc (loc, data);
   tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE);
   tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
--- gcc/gcc/sanitizer.def.mp	2013-11-12 13:46:13.356182114 +0100
+++ gcc/gcc/sanitizer.def	2013-11-12 13:46:49.825314074 +0100
@@ -301,3 +301,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HAN
 		      "__ubsan_handle_vla_bound_not_positive",
 		      BT_FN_VOID_PTR_PTR,
 		      ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH,
+		      "__ubsan_handle_type_mismatch",
+		      BT_FN_VOID_PTR_PTR,
+		      ATTR_COLD_NOTHROW_LEAF_LIST)
--- gcc/gcc/tree-pass.h.mp	2013-11-12 13:46:13.362182138 +0100
+++ gcc/gcc/tree-pass.h	2013-11-12 13:46:49.829314091 +0100
@@ -447,6 +447,8 @@ extern gimple_opt_pass *make_pass_split_
 extern gimple_opt_pass *make_pass_feedback_split_functions (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_strength_reduction (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_vtable_verify (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ubsan (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sanopt (gcc::context *ctxt);
 
 /* IPA Passes */
 extern simple_ipa_opt_pass *make_pass_ipa_lower_emutls (gcc::context *ctxt);
--- gcc/gcc/ubsan.h.mp	2013-11-12 13:46:13.364182146 +0100
+++ gcc/gcc/ubsan.h	2013-11-12 22:28:30.918518781 +0100
@@ -21,9 +21,26 @@ along with GCC; see the file COPYING3.
 #ifndef GCC_UBSAN_H
 #define GCC_UBSAN_H
 
+/* The various kinds of NULL pointer checks.  */
+enum ubsan_null_ckind {
+  UBSAN_LOAD_OF,
+  UBSAN_STORE_OF,
+  UBSAN_REF_BINDING,
+  UBSAN_MEMBER_ACCESS,
+  UBSAN_MEMBER_CALL
+};
+
+/* An extra data used by ubsan pointer checking.  */
+struct ubsan_mismatch_data {
+  tree align;
+  tree ckind;
+};
+
+extern void ubsan_expand_null_ifn (gimple_stmt_iterator);
 extern tree ubsan_instrument_unreachable (location_t);
-extern tree ubsan_create_data (const char *, location_t, ...);
-extern tree ubsan_type_descriptor (tree);
+extern tree ubsan_create_data (const char *, location_t,
+			       const struct ubsan_mismatch_data *, ...);
+extern tree ubsan_type_descriptor (tree, bool);
 extern tree ubsan_encode_value (tree);
 extern bool is_ubsan_builtin_p (tree);
 
--- gcc/gcc/ubsan.c.mp	2013-11-12 13:46:13.363182142 +0100
+++ gcc/gcc/ubsan.c	2013-11-12 22:35:11.362129449 +0100
@@ -23,15 +23,21 @@ along with GCC; see the file COPYING3.
 #include "coretypes.h"
 #include "tree.h"
 #include "cgraph.h"
+#include "tree-pass.h"
 #include "gimple.h"
+#include "gimple-ssa.h"
 #include "hashtab.h"
 #include "pointer-set.h"
 #include "output.h"
 #include "tm_p.h"
 #include "toplev.h"
+#include "cfgloop.h"
 #include "ubsan.h"
 #include "c-family/c-common.h"
 
+/* From trans-mem.c.  */
+#define PROB_VERY_UNLIKELY      (REG_BR_PROB_BASE / 2000 - 1)
+
 /* Map from a tree to a VAR_DECL tree.  */
 
 struct GTY(()) tree_type_map {
@@ -40,9 +46,16 @@ struct GTY(()) tree_type_map {
 };
 
 #define tree_type_map_eq tree_map_base_eq
-#define tree_type_map_hash tree_map_base_hash
 #define tree_type_map_marked_p tree_map_base_marked_p
 
+/* Hash from a tree in a tree_type_map.  */
+
+unsigned int
+tree_type_map_hash (const void *item)
+{
+  return TYPE_UID (((const struct tree_type_map *)item)->type.from);
+}
+
 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
      htab_t decl_tree_for_type;
 
@@ -240,12 +253,14 @@ get_ubsan_type_info_for_type (tree type)
 }
 
 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
-   descriptor.  It first looks into the pointer map; if not found,
-   create the VAR_DECL, put it into the pointer map and return the
-   ADDR_EXPR of it.  TYPE describes a particular type.  */
+   descriptor.  It first looks into the hash table; if not found,
+   create the VAR_DECL, put it into the hash table and return the
+   ADDR_EXPR of it.  TYPE describes a particular type.  WANT_POINTER_TYPE_P
+   means whether we are interested in the pointer type and not the pointer
+   itself.  */
 
 tree
-ubsan_type_descriptor (tree type)
+ubsan_type_descriptor (tree type, bool want_pointer_type_p)
 {
   /* See through any typedefs.  */
   type = TYPE_MAIN_VARIANT (type);
@@ -255,33 +270,73 @@ ubsan_type_descriptor (tree type)
     return decl;
 
   tree dtype = ubsan_type_descriptor_type ();
-  const char *tname;
+  tree type2 = type;
+  const char *tname = NULL;
+  char *pretty_name;
+  unsigned char deref_depth = 0;
   unsigned short tkind, tinfo;
 
-  /* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work.
-     For e.g. type_unsigned_for (type) or bit-fields, the TYPE_NAME
-     would be NULL.  */
-  if (TYPE_NAME (type) != NULL)
+  /* Get the name of the type, or the name of the pointer type.  */
+  if (want_pointer_type_p)
     {
-      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-	tname = IDENTIFIER_POINTER (TYPE_NAME (type));
+      gcc_assert (POINTER_TYPE_P (type));
+      type2 = TREE_TYPE (type);
+
+      /* Remove any '*' operators from TYPE.  */
+      while (POINTER_TYPE_P (type2))
+        deref_depth++, type2 = TREE_TYPE (type2);
+
+      if (TREE_CODE (type2) == METHOD_TYPE)
+        type2 = TYPE_METHOD_BASETYPE (type2);
+    }
+
+  if (TYPE_NAME (type2) != NULL)
+    {
+      if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
+	tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
       else
-	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
     }
-  else
+
+  if (tname == NULL)
+    /* We weren't able to determine the type name.  */
     tname = "<unknown>";
 
-  if (TREE_CODE (type) == INTEGER_TYPE)
+  /* Decorate the type name with '', '*', "struct", or "union".  */
+  pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
+  if (want_pointer_type_p)
     {
-      /* For INTEGER_TYPE, this is 0x0000.  */
-      tkind = 0x000;
-      tinfo = get_ubsan_type_info_for_type (type);
-    }
-  else if (TREE_CODE (type) == REAL_TYPE)
-    /* We don't have float support yet.  */
-    gcc_unreachable ();
+      int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
+			 TYPE_VOLATILE (type2) ? "volatile " : "",
+			 TYPE_READONLY (type2) ? "const " : "",
+			 TYPE_RESTRICT (type2) ? "restrict " : "",
+			 TYPE_ATOMIC (type2) ? "_Atomic " : "",
+			 TREE_CODE (type2) == RECORD_TYPE
+			 ? "struct "
+			 : TREE_CODE (type2) == UNION_TYPE
+			   ? "union " : "", tname,
+			 deref_depth == 0 ? "" : " ");
+      while (deref_depth-- > 0)
+        pretty_name[pos++] = '*';
+      pretty_name[pos++] = '\'';
+      pretty_name[pos] = '\0';
+    }
   else
-    gcc_unreachable ();
+    sprintf (pretty_name, "'%s'", tname);
+
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:
+      tkind = 0x0000;
+      break;
+    case REAL_TYPE:
+      tkind = 0x0001;
+      break;
+    default:
+      tkind = 0xffff;
+      break;
+    }
+  tinfo = get_ubsan_type_info_for_type (type);
 
   /* Create a new VAR_DECL of type descriptor.  */
   char tmp_name[32];
@@ -295,8 +350,8 @@ ubsan_type_descriptor (tree type)
   DECL_IGNORED_P (decl) = 1;
   DECL_EXTERNAL (decl) = 0;
 
-  size_t len = strlen (tname);
-  tree str = build_string (len + 1, tname);
+  size_t len = strlen (pretty_name);
+  tree str = build_string (len + 1, pretty_name);
   TREE_TYPE (str) = build_array_type (char_type_node,
 				      build_index_type (size_int (len)));
   TREE_READONLY (str) = 1;
@@ -311,7 +366,7 @@ ubsan_type_descriptor (tree type)
   DECL_INITIAL (decl) = ctor;
   rest_of_decl_compilation (decl, 1, 0);
 
-  /* Save the address of the VAR_DECL into the pointer map.  */
+  /* Save the address of the VAR_DECL into the hash table.  */
   decl = build_fold_addr_expr (decl);
   decl_for_type_insert (type, decl);
 
@@ -320,10 +375,12 @@ ubsan_type_descriptor (tree type)
 
 /* Create a structure for the ubsan library.  NAME is a name of the new
    structure.  The arguments in ... are of __ubsan_type_descriptor type
-   and there are at most two of them.  */
+   and there are at most two of them.  MISMATCH are data used by ubsan
+   pointer checking.  */
 
 tree
-ubsan_create_data (const char *name, location_t loc, ...)
+ubsan_create_data (const char *name, location_t loc,
+		   const struct ubsan_mismatch_data *mismatch, ...)
 {
   va_list args;
   tree ret, t;
@@ -346,12 +403,12 @@ ubsan_create_data (const char *name, loc
       i++;
     }
 
-  va_start (args, loc);
+  va_start (args, mismatch);
   for (t = va_arg (args, tree); t != NULL_TREE;
        i++, t = va_arg (args, tree))
     {
       gcc_checking_assert (i < 3);
-      /* Save the tree argument for later use.  */
+      /* Save the tree arguments for later use.  */
       vec_safe_push (saved_args, t);
       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
 			      td_type);
@@ -359,10 +416,27 @@ ubsan_create_data (const char *name, loc
       if (i)
 	DECL_CHAIN (fields[i - 1]) = fields[i];
     }
+  va_end (args);
+
+  if (mismatch != NULL)
+    {
+      /* We have to add two more decls.  */
+      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
+				pointer_sized_int_node);
+      DECL_CONTEXT (fields[i]) = ret;
+      DECL_CHAIN (fields[i - 1]) = fields[i];
+      i++;
+
+      fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
+			      unsigned_char_type_node);
+      DECL_CONTEXT (fields[i]) = ret;
+      DECL_CHAIN (fields[i - 1]) = fields[i];
+      i++;
+    }
+
   TYPE_FIELDS (ret) = fields[0];
   TYPE_NAME (ret) = get_identifier (name);
   layout_type (ret);
-  va_end (args);
 
   /* Now, fill in the type.  */
   char tmp_name[32];
@@ -391,6 +465,13 @@ ubsan_create_data (const char *name, loc
       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
     }
 
+  if (mismatch != NULL)
+    {
+      /* Append the pointer data.  */
+      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->align);
+      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->ckind);
+    }
+
   TREE_CONSTANT (ctor) = 1;
   TREE_STATIC (ctor) = 1;
   DECL_INITIAL (var) = ctor;
@@ -405,7 +486,8 @@ ubsan_create_data (const char *name, loc
 tree
 ubsan_instrument_unreachable (location_t loc)
 {
-  tree data = ubsan_create_data ("__ubsan_unreachable_data", loc, NULL_TREE);
+  tree data = ubsan_create_data ("__ubsan_unreachable_data", loc, NULL,
+				 NULL_TREE);
   tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
   return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
 }
@@ -420,4 +502,199 @@ is_ubsan_builtin_p (tree t)
 		  "__builtin___ubsan_", 18) == 0;
 }
 
+/* Expand UBSAN_NULL internal call.  */
+
+void
+ubsan_expand_null_ifn (gimple_stmt_iterator gsi)
+{
+  gimple stmt = gsi_stmt (gsi);
+  location_t loc = gimple_location (stmt);
+  gcc_assert (gimple_call_num_args (stmt) == 2);
+  tree ptr = gimple_call_arg (stmt, 0);
+  tree ckind = gimple_call_arg (stmt, 1);
+
+  basic_block cur_bb = gsi_bb (gsi);
+
+  /* Split the original block holding the pointer dereference.  */
+  edge e = split_block (cur_bb, stmt);
+
+  /* Get a hold on the 'condition block', the 'then block' and the
+     'else block'.  */
+  basic_block cond_bb = e->src;
+  basic_block fallthru_bb = e->dest;
+  basic_block then_bb = create_empty_bb (cond_bb);
+  if (current_loops)
+    {
+      add_bb_to_loop (then_bb, cond_bb->loop_father);
+      loops_state_set (LOOPS_NEED_FIXUP);
+    }
+
+  /* Make an edge coming from the 'cond block' into the 'then block';
+     this edge is unlikely taken, so set up the probability accordingly.  */
+  e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
+  e->probability = PROB_VERY_UNLIKELY;
+
+  /* Connect 'then block' with the 'else block'.  This is needed
+     as the ubsan routines we call in the 'then block' are not noreturn.
+     The 'then block' only has one outcoming edge.  */
+  make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
+
+  /* Set up the fallthrough basic block.  */
+  e = find_edge (cond_bb, fallthru_bb);
+  e->flags = EDGE_FALSE_VALUE;
+  e->count = cond_bb->count;
+  e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
+
+  /* Update dominance info for the newly created then_bb; note that
+     fallthru_bb's dominance info has already been updated by
+     split_bock.  */
+  if (dom_info_available_p (CDI_DOMINATORS))
+    set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
+
+  /* Put the ubsan builtin call into the newly created BB.  */
+  tree fn = builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH);
+  const struct ubsan_mismatch_data m
+    = { build_zero_cst (pointer_sized_int_node), ckind };
+  tree data = ubsan_create_data ("__ubsan_null_data",
+				 loc, &m,
+				 ubsan_type_descriptor (TREE_TYPE (ptr), true),
+				 NULL_TREE);
+  data = build_fold_addr_expr_loc (loc, data);
+  gimple g = gimple_build_call (fn, 2, data,
+				build_zero_cst (pointer_sized_int_node));
+  gimple_set_location (g, loc);
+  gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
+  gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
+
+  /* Unlink the UBSAN_NULLs vops before replacing it.  */
+  unlink_stmt_vdef (stmt);
+
+  g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
+			 NULL_TREE, NULL_TREE);
+  gimple_set_location (g, loc);
+
+  /* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
+  gsi_replace (&gsi, g, false);
+}
+
+/* Instrument a member call.  We check whether 'this' is NULL.  */
+
+static void
+instrument_member_call (gimple_stmt_iterator *iter)
+{
+  tree this_parm = gimple_call_arg (gsi_stmt (*iter), 0);
+  tree kind = build_int_cst (unsigned_char_type_node, UBSAN_MEMBER_CALL);
+  gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 2, this_parm, kind);
+  gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
+  gsi_insert_before (iter, g, GSI_SAME_STMT);
+}
+
+/* Instrument a memory reference.  T is the pointer, IS_LHS says
+   whether the pointer is on the left hand side of the assignment.  */
+
+static void
+instrument_mem_ref (tree t, gimple_stmt_iterator *iter, bool is_lhs)
+{
+  enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
+  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
+    ikind = UBSAN_MEMBER_ACCESS;
+  tree kind = build_int_cst (unsigned_char_type_node, ikind);
+  gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 2, t, kind);
+  gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
+  gsi_insert_before (iter, g, GSI_SAME_STMT);
+}
+
+/* Callback function for the pointer instrumentation.  */
+
+static tree
+instrument_null (tree *tp, int * /*walk_subtree*/, void *data)
+{
+  tree t = *tp;
+  const enum tree_code code = TREE_CODE (t);
+  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+
+  if (code == MEM_REF
+      && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME)
+    instrument_mem_ref (TREE_OPERAND (t, 0), &wi->gsi, wi->is_lhs);
+  else if (code == ADDR_EXPR
+	   && POINTER_TYPE_P (TREE_TYPE (t))
+	   && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == METHOD_TYPE)
+    instrument_member_call (&wi->gsi);
+
+  return NULL_TREE;
+}
+
+/* Gate and execute functions for ubsan pass.  */
+
+static unsigned int
+ubsan_pass (void)
+{
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+
+  FOR_EACH_BB (bb)
+    {
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+	{
+	  struct walk_stmt_info wi;
+	  gimple stmt = gsi_stmt (gsi);
+	  if (is_gimple_debug (stmt))
+	    {
+	      gsi_next (&gsi);
+	      continue;
+	    }
+
+	  memset (&wi, 0, sizeof (wi));
+	  wi.gsi = gsi;
+	  walk_gimple_op (stmt, instrument_null, &wi);
+	  gsi_next (&gsi);
+	}
+    }
+  return 0;
+}
+
+static bool
+gate_ubsan (void)
+{
+  return flag_sanitize & SANITIZE_NULL;
+}
+
+namespace {
+
+const pass_data pass_data_ubsan =
+{
+  GIMPLE_PASS, /* type */
+  "ubsan", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_TREE_UBSAN, /* tv_id */
+  ( PROP_cfg | PROP_ssa ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_update_ssa, /* todo_flags_finish */
+};
+
+class pass_ubsan : public gimple_opt_pass
+{
+public:
+  pass_ubsan (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_ubsan, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_ubsan (); }
+  unsigned int execute () { return ubsan_pass (); }
+
+}; // class pass_ubsan
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_ubsan (gcc::context *ctxt)
+{
+  return new pass_ubsan (ctxt);
+}
+
 #include "gt-ubsan.h"
--- gcc/gcc/flag-types.h.mp	2013-11-12 13:46:13.350182085 +0100
+++ gcc/gcc/flag-types.h	2013-11-12 13:46:49.821314055 +0100
@@ -211,8 +211,9 @@ enum sanitize_code {
   SANITIZE_DIVIDE = 1 << 3,
   SANITIZE_UNREACHABLE = 1 << 4,
   SANITIZE_VLA = 1 << 5,
+  SANITIZE_NULL = 1 << 6,
   SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
-		       | SANITIZE_VLA
+		       | SANITIZE_VLA | SANITIZE_NULL
 };
 
 /* flag_vtable_verify initialization levels. */
--- gcc/gcc/internal-fn.c.mp	2013-11-12 13:46:13.351182089 +0100
+++ gcc/gcc/internal-fn.c	2013-11-12 13:46:49.822314059 +0100
@@ -139,6 +139,14 @@ expand_GOMP_SIMD_LAST_LANE (gimple stmt
   gcc_unreachable ();
 }
 
+/* This should get expanded in the sanopt pass.  */
+
+static void
+expand_UBSAN_NULL (gimple stmt ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 /* Routines to expand each internal function, indexed by function number.
    Each routine has the prototype:
 
--- gcc/gcc/passes.def.mp	2013-11-12 13:46:13.355182109 +0100
+++ gcc/gcc/passes.def	2013-11-12 13:46:49.825314074 +0100
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.
       NEXT_PASS (pass_init_datastructures);
 
       NEXT_PASS (pass_build_ssa);
+      NEXT_PASS (pass_ubsan);
       NEXT_PASS (pass_early_warn_uninitialized);
       NEXT_PASS (pass_rebuild_cgraph_edges);
       NEXT_PASS (pass_inline_parameters);
@@ -309,6 +310,7 @@ along with GCC; see the file COPYING3.
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_asan_O0);
   NEXT_PASS (pass_tsan_O0);
+  NEXT_PASS (pass_sanopt);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
   NEXT_PASS (pass_nrv);
--- gcc/gcc/cgraphunit.c.mp	2013-11-12 13:46:13.349182081 +0100
+++ gcc/gcc/cgraphunit.c	2013-11-12 13:46:49.819314047 +0100
@@ -825,7 +825,8 @@ varpool_finalize_decl (tree decl)
     varpool_analyze_node (node);
   /* Some frontends produce various interface variables after compilation
      finished.  */
-  if (cgraph_state == CGRAPH_STATE_FINISHED)
+  if (cgraph_state == CGRAPH_STATE_FINISHED
+      || (!flag_toplevel_reorder && cgraph_state == CGRAPH_STATE_EXPANSION))
     varpool_assemble_decl (node);
 }
 
--- gcc/gcc/internal-fn.def.mp	2013-11-12 13:46:13.353182099 +0100
+++ gcc/gcc/internal-fn.def	2013-11-12 16:11:39.394626260 +0100
@@ -44,3 +44,4 @@ DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOV
 DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW)
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-6.c.mp	2013-11-12 20:53:32.328616378 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-6.c	2013-11-12 20:58:57.540848964 +0100
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+main (void)
+{
+  unsigned long int *p = 0;
+  *p = 42;
+  return 0;
+}
+
+/* { dg-output "store to null pointer of type 'long unsigned int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c.mp	2013-11-12 13:46:13.358182122 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c	2013-11-12 13:46:49.826314079 +0100
@@ -16,6 +16,6 @@ main (void)
   return 0;
 }
 
-/* { dg-output "division of -2147483648 by -1 cannot be represented in type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type int(\n|\r\n|\r)" } */
+/* { dg-output "division of -2147483648 by -1 cannot be represented in type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type 'int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-10.c.mp	2013-11-12 21:09:50.462378790 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-10.c	2013-11-12 21:23:04.421294921 +0100
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+main (void)
+{
+  short *p = 0, *u;
+  *(u + *p) = 23;
+  return  0;
+}
+
+/* { dg-output "load of null pointer of type 'short int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-4.c.mp	2013-11-12 20:19:42.514234257 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-4.c	2013-11-12 20:23:40.610106000 +0100
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+main (void)
+{
+  _Complex double *p = 0;
+  if (p[0])
+    return 42;
+  return 0;
+}
+
+/* { dg-output "load of null pointer of type 'complex double'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-8.c.mp	2013-11-12 21:07:21.276742012 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-8.c	2013-11-12 21:08:48.751120378 +0100
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+struct S {
+  int i;
+};
+
+int
+main (void)
+{
+  struct S *s = 0;
+  return s->i;
+}
+
+/* { dg-output "member access within null pointer of type 'struct S'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-9.c.mp	2013-11-12 21:09:02.733171909 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-9.c	2013-11-12 21:09:29.331286963 +0100
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+union U {
+  int i;
+};
+
+int
+main (void)
+{
+  union U *u = 0;
+  return u->i;
+}
+
+/* { dg-output "member access within null pointer of type 'union U'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-11.c.mp	2013-11-12 21:40:24.277303514 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-11.c	2013-11-12 21:41:38.642575471 +0100
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+struct S {
+  int i;
+};
+
+int
+main (void)
+{
+  struct S **s = 0;
+  return (*s)->i;
+}
+
+/* { dg-output "load of null pointer of type 'struct S \\*'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-7.c.mp	2013-11-12 20:59:18.131924558 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-7.c	2013-11-12 21:03:38.636874389 +0100
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int *
+gao (void)
+{
+  return 0;
+}
+
+int
+main (void)
+{
+  return *gao ();
+}
+
+/* { dg-output "load of null pointer of type 'int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-5.c.mp	2013-11-12 20:25:46.755617396 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-5.c	2013-11-12 20:53:10.085525041 +0100
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+typedef volatile const _Complex float *T;
+
+int
+main (void)
+{
+  T t = 0;
+  if (*t)
+    return 42;
+  return 0;
+}
+
+/* { dg-output "load of null pointer of type 'volatile const complex float'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-1.c.mp	2013-11-12 15:37:15.204806063 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-1.c	2013-11-12 19:02:55.500951377 +0100
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+main (void)
+{
+  int *p = 0;
+  return *p;
+}
+
+/* { dg-output "load of null pointer of type 'int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/shift-1.c.mp	2013-11-12 13:46:13.359182126 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/shift-1.c	2013-11-12 13:46:49.827314083 +0100
@@ -23,9 +23,9 @@ main (void)
 
   return 0;
 }
-/* { dg-output "shift exponent 152 is too large for \[^\n\r]*-bit type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*shift exponent 153 is too large for \[^\n\r]*-bit type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*shift exponent 154 is too large for \[^\n\r]*-bit type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*shift exponent 524 is too large for \[^\n\r]*-bit type long long unsigned int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*shift exponent 370 is too large for \[^\n\r]*-bit type int(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*shift exponent 402 is too large for \[^\n\r]*-bit type long int(\n|\r\n|\r)" } */
+/* { dg-output "shift exponent 152 is too large for \[^\n\r]*-bit type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 153 is too large for \[^\n\r]*-bit type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 154 is too large for \[^\n\r]*-bit type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 524 is too large for \[^\n\r]*-bit type 'long long unsigned int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 370 is too large for \[^\n\r]*-bit type 'int'(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*shift exponent 402 is too large for \[^\n\r]*-bit type 'long int'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-3.c.mp	2013-11-12 19:49:30.552505623 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-3.c	2013-11-12 20:17:23.093674131 +0100
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+foo (int *p)
+{
+  return *p;
+}
+
+int
+main (void)
+{
+  int **p = 0;
+  return foo (*p);
+}
+
+/* { dg-output "load of null pointer of type 'int \\*'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/c-c++-common/ubsan/null-2.c.mp	2013-11-12 16:46:44.795566860 +0100
+++ gcc/gcc/testsuite/c-c++-common/ubsan/null-2.c	2013-11-12 19:08:06.356208894 +0100
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=null -w" } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+
+int
+main (void)
+{
+  int ***ppp = 0;
+  return ***ppp;
+}
+
+/* { dg-output "load of null pointer of type 'int \\*\\*'(\n|\r\n|\r)" } */
--- gcc/gcc/testsuite/gcc.dg/ubsan/c99-shift-2.c.mp	2013-11-12 13:46:13.360182130 +0100
+++ gcc/gcc/testsuite/gcc.dg/ubsan/c99-shift-2.c	2013-11-12 13:46:49.827314083 +0100
@@ -7,4 +7,4 @@ main (void)
   int a = 1;
   a <<= 31;
 }
-/* { dg-output "left shift of 1 by 31 places cannot be represented in type int" } */
+/* { dg-output "left shift of 1 by 31 places cannot be represented in type 'int'" } */
--- gcc/gcc/asan.c.mp	2013-11-12 13:46:13.347182073 +0100
+++ gcc/gcc/asan.c	2013-11-12 20:09:49.424056584 +0100
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.
 #include "alloc-pool.h"
 #include "cfgloop.h"
 #include "gimple-builder.h"
+#include "ubsan.h"
 
 /* AddressSanitizer finds out-of-bounds and use-after-free bugs
    with <2x slowdown on average.
@@ -2365,4 +2366,87 @@ make_pass_asan_O0 (gcc::context *ctxt)
   return new pass_asan_O0 (ctxt);
 }
 
+/* Perform optimization of sanitize functions.  */
+
+static unsigned int
+execute_sanopt (void)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	{
+	  gimple stmt = gsi_stmt (gsi);
+
+	  if (gimple_code (stmt) != GIMPLE_CALL)
+	    continue;
+
+	  if (gimple_call_internal_p (stmt))
+	    switch (gimple_call_internal_fn (stmt))
+	      {
+	      case IFN_UBSAN_NULL:
+		ubsan_expand_null_ifn (gsi);
+		break;
+	      default:
+		break;
+	      }
+
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    {
+	      fprintf (dump_file, "Optimized\n  ");
+	      print_gimple_stmt (dump_file, stmt, 0, dump_flags);
+	      fprintf (dump_file, "\n");
+	    }
+	}
+    }
+  return 0;
+}
+
+static bool
+gate_sanopt (void)
+{
+  return flag_sanitize;
+}
+
+namespace {
+
+const pass_data pass_data_sanopt =
+{
+  GIMPLE_PASS, /* type */
+  "sanopt", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  true, /* has_gate */
+  true, /* has_execute */
+  TV_NONE, /* tv_id */
+  ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  ( TODO_verify_flow | TODO_verify_stmts
+    | TODO_update_ssa ), /* todo_flags_finish */
+};
+
+class pass_sanopt : public gimple_opt_pass
+{
+public:
+  pass_sanopt (gcc::context *ctxt)
+    : gimple_opt_pass (pass_data_sanopt, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  bool gate () { return gate_sanopt (); }
+  unsigned int execute () { return execute_sanopt (); }
+
+}; // class pass_sanopt
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_sanopt (gcc::context *ctxt)
+{
+  return new pass_sanopt (ctxt);
+}
+
 #include "gt-asan.h"
--- gcc/gcc/timevar.def.mp	2013-11-12 13:46:13.361182134 +0100
+++ gcc/gcc/timevar.def	2013-11-12 13:46:49.828314087 +0100
@@ -261,6 +261,7 @@ DEFTIMEVAR (TV_PLUGIN_INIT           , "
 DEFTIMEVAR (TV_PLUGIN_RUN            , "plugin execution")
 DEFTIMEVAR (TV_GIMPLE_SLSR           , "straight-line strength reduction")
 DEFTIMEVAR (TV_VTABLE_VERIFICATION   , "vtable verification")
+DEFTIMEVAR (TV_TREE_UBSAN            , "tree ubsan")
 
 /* Everything else in rest_of_compilation not included above.  */
 DEFTIMEVAR (TV_EARLY_LOCAL	     , "early local passes")
