diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 37b484df4bcd44f5c534fd45e63f997f508b51b6..70be419535677b6749d5eba1b85c264a8fdaf600 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2005-06-29  Daniel Berlin  <dberlin@dberlin.org>
+
+	Fix PR tree-optimization/22071
+	
+	* tree-ssa-structalias.c (offset_overlaps_with_access): New
+	function.
+	(get_constraint_for_component_ref): Use it.
+
 2005-07-01  Andrew Pinski  <pinskia@physics.uc.edu>
 
 	PR other/22264
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr22071.C b/gcc/testsuite/g++.dg/tree-ssa/pr22071.C
new file mode 100644
index 0000000000000000000000000000000000000000..719aed374507c2340e34508e6521b7c86aef1a43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr22071.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* This code ends up taking the address of part of the structure that is padding, 
+   and because there is no real field there, the structure alias analyzer would 
+   abort.  */
+struct empty_class {};
+struct class1 : empty_class
+{
+  class1() {}
+  empty_class value_;
+};
+struct lambda : class1 { };
+lambda _1;
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 61137aaa63d6952c83cf46cc89169ae9a9602b5a..06adb3ec60202bd7cedbae691868c33aa1267b37 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -1940,6 +1940,25 @@ bitpos_of_field (const tree fdecl)
 }
 
 
+/* Return true if an access to [ACCESSPOS, ACCESSSIZE]
+   overlaps with a field at [FIELDPOS, FIELDSIZE] */
+
+static bool
+offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
+			     const unsigned HOST_WIDE_INT fieldsize,
+			     const unsigned HOST_WIDE_INT accesspos,
+			     const unsigned HOST_WIDE_INT accesssize)
+{
+  if (fieldpos == accesspos && fieldsize == accesssize)
+    return true;
+  if (accesspos >= fieldpos && accesspos <= (fieldpos + fieldsize))
+    return true;
+  if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
+    return true;
+  
+  return false;
+}
+
 /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
 
 static struct constraint_expr
@@ -2000,8 +2019,27 @@ get_constraint_for_component_ref (tree t)
 	 we may have to do something cute here.  */
       
       if (result.offset < get_varinfo (result.var)->fullsize)	
-	result.var = first_vi_for_offset (get_varinfo (result.var), 
-					  result.offset)->id;
+	{
+	  /* It's also not true that the constraint will actually start at the
+	     right offset, it may start in some padding.  We only care about
+	     setting the constraint to the first actual field it touches, so
+	     walk to find it.  */ 
+	  varinfo_t curr;
+	  for (curr = get_varinfo (result.var); curr; curr = curr->next)
+	    {
+	      if (offset_overlaps_with_access (curr->offset, curr->size,
+					       result.offset, bitsize))
+		{
+		  result.var = curr->id;
+		  break;
+
+		}
+	    }
+	  /* assert that we found *some* field there. The user couldn't be
+	     accessing *only* padding.  */
+	     
+	  gcc_assert (curr);
+	}
       else
 	if (dump_file && (dump_flags & TDF_DETAILS))
 	  fprintf (dump_file, "Access to past the end of variable, ignoring\n");