From 634b5df5d5c0ccfaa523ca0f9a737df3c0f28372 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 12 Jan 2009 20:44:33 +0100
Subject: [PATCH] re PR c/32041 (offsetof buglet)

	PR c/32041
	* c-parser.c (c_parser_postfix_expression): Allow `->' in
	offsetof member-designator, handle it as `[0].'.

	* parser.c (cp_parser_builtin_offsetof): Allow `->' in
	offsetof member-designator, handle it as `[0].'.

	* gcc.dg/pr32041.c: New test.
	* g++.dg/parse/offsetof9.C: New test.

From-SVN: r143305
---
 gcc/ChangeLog                          |  6 +++++
 gcc/c-parser.c                         | 15 ++++++++++--
 gcc/cp/ChangeLog                       |  4 ++++
 gcc/cp/parser.c                        | 14 +++++++----
 gcc/testsuite/ChangeLog                |  6 +++++
 gcc/testsuite/g++.dg/parse/offsetof9.C | 32 ++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr32041.c         | 12 ++++++++++
 7 files changed, 83 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/offsetof9.C
 create mode 100644 gcc/testsuite/gcc.dg/pr32041.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a86f0095cc9e..21c58ec6f1d0 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 99c6c187a1e6..5cb1982a5445 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 de7d1ab06846..c81a1e638817 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 f497d664783d..bf742eea079b 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 3a54a665a587..66619662faa8 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 000000000000..efc103837f9d
--- /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 000000000000..60837b204366
--- /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];
+
-- 
GitLab