diff --git a/gcc/expr.cc b/gcc/expr.cc
index 10467f82c0d24757cf59f28199ee3822bc1c569b..f684e26cef78089ead787976ab8a960f00f29711 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -11796,6 +11796,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 		&& known_eq (GET_MODE_BITSIZE (DECL_MODE (base)), type_size))
 	      return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base),
 				  target, tmode, modifier);
+	    unsigned align;
 	    if (TYPE_MODE (type) == BLKmode || maybe_lt (offset, 0))
 	      {
 		temp = assign_stack_temp (DECL_MODE (base),
@@ -11804,6 +11805,17 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 		temp = adjust_address (temp, TYPE_MODE (type), offset);
 		if (TYPE_MODE (type) == BLKmode)
 		  set_mem_size (temp, int_size_in_bytes (type));
+		/* When the original ref was misaligned so will be the
+		   access to the stack temporary.  Not all targets handle
+		   this correctly, some will ICE in sanity checking.
+		   Handle this by doing bitfield extraction when necessary.  */
+		else if ((align = get_object_alignment (exp))
+			 < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+		  temp
+		    = expand_misaligned_mem_ref (temp, TYPE_MODE (type),
+						 unsignedp, align,
+						 modifier == EXPAND_STACK_PARM
+						 ? NULL_RTX : target, NULL);
 		return temp;
 	      }
 	    /* When the access is fully outside of the underlying object
diff --git a/gcc/testsuite/gcc.dg/pr118695.c b/gcc/testsuite/gcc.dg/pr118695.c
new file mode 100644
index 0000000000000000000000000000000000000000..55e3b767a21c45a4c742f0e9909276b3264ad02d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr118695.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+void * g(int obj)
+{
+  char *t = (char*)&obj;
+  t -= 1;
+  return *(int**)t;
+}