We were aborting when build_base_path returned an error because of the
derived class not being complete yet, which wasn't considered by the assert.
Fixed by checking for complete type first.  The semantics.c change avoids
a duplicate error message.

Tested x86_64-pc-linux-gnu, applying to trunk.

        * semantics.c (finish_offsetof): Handle error_mark_node.
        * typeck.c (build_class_member_access_expr): Call
        complete_type_or_maybe_complain before converting to base.
---
 gcc/cp/semantics.c                           |  3 +++
 gcc/cp/typeck.c                              |  8 ++++++++
 gcc/testsuite/g++.dg/ext/builtin-offsetof4.C | 11 +++++++++++
 gcc/testsuite/g++.dg/other/offsetof8.C       |  2 +-
 gcc/cp/ChangeLog                             |  5 +++++
 5 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/builtin-offsetof4.C

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a08a2a57f5f..408675b8099 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4144,6 +4144,9 @@ finish_offsetof (tree object_ptr, tree expr, location_t 
loc)
       return expr;
     }
 
+  if (expr == error_mark_node)
+    return error_mark_node;
+
   if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
     {
       error ("cannot apply %<offsetof%> to destructor %<~%T%>",
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a00b0f48b69..56def144a3e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2474,6 +2474,14 @@ build_class_member_access_expr (cp_expr object, tree 
member,
          tree binfo;
          base_kind kind;
 
+         /* We didn't complain above about a currently open class, but now we
+            must: we don't know how to refer to a base member before layout is
+            complete.  But still don't complain in a template.  */
+         if (!dependent_type_p (object_type)
+             && !complete_type_or_maybe_complain (object_type, object,
+                                                  complain))
+           return error_mark_node;
+
          binfo = lookup_base (access_path ? access_path : object_type,
                               member_scope, ba_unique, &kind, complain);
          if (binfo == error_mark_node)
diff --git a/gcc/testsuite/g++.dg/ext/builtin-offsetof4.C 
b/gcc/testsuite/g++.dg/ext/builtin-offsetof4.C
new file mode 100644
index 00000000000..b30c31dbfa9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-offsetof4.C
@@ -0,0 +1,11 @@
+// PR c++/89331
+
+class A {
+public:
+    char a;
+};
+
+class B : public A {
+public:
+    static const unsigned b = __builtin_offsetof(B, a); // { dg-error 
"incomplete" }
+};
diff --git a/gcc/testsuite/g++.dg/other/offsetof8.C 
b/gcc/testsuite/g++.dg/other/offsetof8.C
index 211c5127026..daca70a6fe4 100644
--- a/gcc/testsuite/g++.dg/other/offsetof8.C
+++ b/gcc/testsuite/g++.dg/other/offsetof8.C
@@ -9,4 +9,4 @@ struct B: virtual A { };
 int a[]  = {
   !&((B*)0)->i,    // { dg-error "invalid access to non-static data member" }
   __builtin_offsetof (B, i)   // { dg-error "invalid access to non-static" }
-};                           // { dg-message "offsetof within 
non-standard-layout type" "" { target *-*-* } .-1 }
+};
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bb719133a97..a224517b566 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2019-04-03  Jason Merrill  <ja...@redhat.com>
 
+       PR c++/89331 - ICE with offsetof in incomplete class.
+       * semantics.c (finish_offsetof): Handle error_mark_node.
+       * typeck.c (build_class_member_access_expr): Call
+       complete_type_or_maybe_complain before converting to base.
+
        PR c++/89917 - ICE with lambda in variadic mem-init.
        * pt.c (make_pack_expansion): Change type_pack_expansion_p to false.
 

base-commit: 9939b2f79bd9b75b99080a17f3d6f1214d543477
-- 
2.20.1

Reply via email to