diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a86f0095cc9e996becd80c6d9515d6dc286867b1..21c58ec6f1d010df03d391abda5dcb040d7925f0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2009-01-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/32041
+	* c-parser.c (c_parser_postfix_expression): Allow `->' in
+	offsetof member-designator, handle it as `[0].'.
+
 2009-01-12  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	* pa.c (pa_asm_output_mi_thunk): Use pc-relative branch to thunk
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 99c6c187a1e6060635e8a8b9e48c442872957f8e..5cb1982a5445f9e96b4f407e9831aacce871ee37 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -5273,10 +5273,21 @@ c_parser_postfix_expression (c_parser *parser)
 		c_parser_consume_token (parser);
 		while (c_parser_next_token_is (parser, CPP_DOT)
 		       || c_parser_next_token_is (parser,
-						  CPP_OPEN_SQUARE))
+						  CPP_OPEN_SQUARE)
+		       || c_parser_next_token_is (parser,
+						  CPP_DEREF))
 		  {
-		    if (c_parser_next_token_is (parser, CPP_DOT))
+		    if (c_parser_next_token_is (parser, CPP_DEREF))
+		      {
+			loc = c_parser_peek_token (parser)->location;
+			offsetof_ref = build_array_ref (offsetof_ref,
+							integer_zero_node,
+							loc);
+			goto do_dot;
+		      }
+		    else if (c_parser_next_token_is (parser, CPP_DOT))
 		      {
+		      do_dot:
 			c_parser_consume_token (parser);
 			if (c_parser_next_token_is_not (parser,
 							CPP_NAME))
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index de7d1ab06846a401375155013eb531c69e3dcf99..c81a1e63881704d9268e6beeba6f63a4e38f10a3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
 2009-01-12  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c/32041
+	* parser.c (cp_parser_builtin_offsetof): Allow `->' in
+	offsetof member-designator, handle it as `[0].'.
+
 	PR c++/38794
 	* decl.c (start_function): If grokdeclarator hasn't returned
 	FUNCTION_DECL nor error_mark_node, issue diagnostics.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f497d664783d2a70dd5d2c654688069481e38a13..bf742eea079bd771c6ed3f9cc6bf34664f84974e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -6627,7 +6627,8 @@ cp_parser_constant_expression (cp_parser* parser,
    offsetof-member-designator:
      id-expression
      | offsetof-member-designator "." id-expression
-     | offsetof-member-designator "[" expression "]"  */
+     | offsetof-member-designator "[" expression "]"
+     | offsetof-member-designator "->" id-expression  */
 
 static tree
 cp_parser_builtin_offsetof (cp_parser *parser)
@@ -6670,11 +6671,16 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 	  expr = cp_parser_postfix_open_square_expression (parser, expr, true);
 	  break;
 
+	case CPP_DEREF:
+	  /* offsetof-member-designator "->" identifier */
+	  expr = grok_array_decl (expr, integer_zero_node);
+	  /* FALLTHRU */
+
 	case CPP_DOT:
 	  /* offsetof-member-designator "." identifier */
 	  cp_lexer_consume_token (parser->lexer);
-	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-							 true, &dummy,
+	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
+							 expr, true, &dummy,
 							 token->location);
 	  break;
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3a54a665a58741e9d7e27eb4b62bfcae8fe2d099..66619662faa8dac32ad4f0d5550b320bad783dcc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-01-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/32041
+	* gcc.dg/pr32041.c: New test.
+	* g++.dg/parse/offsetof9.C: New test.
+
 2009-01-12  Daniel Jacobowitz  <dan@codesourcery.com>
 	    Nathan Froyd  <froydnj@codesourcery.com>
 
diff --git a/gcc/testsuite/g++.dg/parse/offsetof9.C b/gcc/testsuite/g++.dg/parse/offsetof9.C
new file mode 100644
index 0000000000000000000000000000000000000000..efc103837f9d2626894c948d42dd97d0f841cbfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/offsetof9.C
@@ -0,0 +1,32 @@
+/* PR c/32041 */
+/* { dg-do run } */
+
+struct S
+{
+  int c;
+  struct { float f; } sa[2];
+};
+
+char a[__builtin_offsetof (S, sa->f)
+       == __builtin_offsetof (S, sa[0].f) ? 1 : -1];
+
+template <int N>
+struct T
+{
+  int c[N];
+  struct { float f; } sa[N];
+  static int foo () { return __builtin_offsetof (T, sa->f); }
+  static int bar () { return __builtin_offsetof (T, sa[0].f); }
+};
+
+char b[__builtin_offsetof (T<5>, sa->f)
+       == __builtin_offsetof (T<5>, sa[0].f) ? 1 : -1];
+
+int
+main ()
+{
+  if (T<1>::foo () != T<1>::bar ())
+    __builtin_abort ();
+  if (T<7>::foo () != T<7>::bar ())
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr32041.c b/gcc/testsuite/gcc.dg/pr32041.c
new file mode 100644
index 0000000000000000000000000000000000000000..60837b204366910eee91e5d07b3d74e12509e6d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr32041.c
@@ -0,0 +1,12 @@
+/* PR c/32041 */
+/* { dg-do compile } */
+
+struct S
+{
+  int c;
+  struct { float f; } sa[2];
+};
+
+char a[__builtin_offsetof (struct S, sa->f)
+       == __builtin_offsetof (struct S, sa[0].f) ? 1 : -1];
+