Types defined within a __builtin_offsetof argument don't always get
properly recorded as members of their context types, so if they're
anonymous, we may fail to assign them an anon type index for mangling
and ICE.

We shouldn't allow types to be introduced in __builtin_offsetof, I
think, so I've arranged for us to reject them.  Even then, we still
parse the definitions and attempt to assign mangled names to its
member functions, so the ICE remains.  Since we've already reported an
error, we might as well complete the name assignment with an arbitrary
index, thus avoiding the ICE.


Regstrapped on i686- and x86_64-linux-gnu, regressing
g++.dg/parse/semicolon3.C, which defines a (named) struct in
builtin_offsetof.  I suppose this means I should look for another
solution that doesn't involve rejecting these definitions, eh?


for  gcc/cp/ChangeLog

        PR c++/85039
        * parser.c (cp_parser_builtin_offset): Reject type definitions.
        * mangle.c (nested_anon_class_index): Avoid crash returning -1
        if we've seen errors.

for  gcc/testsuite/ChangeLog

        PR c++/85039
        * g++.dg/pr85039-1.C: New.
        * g++.dg/pr85039-2.C: New.
---
 gcc/cp/mangle.c                  |    3 +++
 gcc/cp/parser.c                  |    8 +++++++-
 gcc/testsuite/g++.dg/pr85039-1.C |   17 +++++++++++++++++
 gcc/testsuite/g++.dg/pr85039-2.C |   10 ++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/pr85039-1.C
 create mode 100644 gcc/testsuite/g++.dg/pr85039-2.C

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 94c4bed28486..a7f9d686345d 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1623,6 +1623,9 @@ nested_anon_class_index (tree type)
          ++index;
       }
 
+  if (seen_error ())
+    return -1;
+
   gcc_unreachable ();
 }
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e946d0b72292..135efb7eb2da 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -9833,7 +9833,13 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   parens.require_open (parser);
   /* Parse the type-id.  */
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-  type = cp_parser_type_id (parser);
+  {
+    const char *saved_message = parser->type_definition_forbidden_message;
+    parser->type_definition_forbidden_message
+      = G_("types may not be defined within __builtin_offsetof");
+    type = cp_parser_type_id (parser);
+    parser->type_definition_forbidden_message = saved_message;
+  }
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, RT_COMMA);
   token = cp_lexer_peek_token (parser->lexer);
diff --git a/gcc/testsuite/g++.dg/pr85039-1.C b/gcc/testsuite/g++.dg/pr85039-1.C
new file mode 100644
index 000000000000..f57c8a261dee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr85039-1.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++14 } }
+
+constexpr int a() {
+ return
+  __builtin_offsetof(struct { // { dg-error "types may not be defined" }
+    int i;
+    short b {
+      __builtin_offsetof(struct { // { dg-error "types may not be defined" }
+       int j;
+        struct c { // { dg-error "types may not be defined" }
+          void d() {
+          }
+        };
+      }, j)
+    };
+  }, i);
+}
diff --git a/gcc/testsuite/g++.dg/pr85039-2.C b/gcc/testsuite/g++.dg/pr85039-2.C
new file mode 100644
index 000000000000..e6d16325105b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr85039-2.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+
+struct d {
+  static d *b;
+} * d::b(__builtin_offsetof(struct { // { dg-error "types may not be defined" }
+  int i;
+  struct a { // { dg-error "types may not be defined" }
+    int c() { return .1f; }
+  };
+}, i));


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

Reply via email to