It's ill-formed to inherit a constructor from an indirect base, but we
were failing to catch that for virtual bases, whose binfos look like
direct bases.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit b8d3d6f1932db56d61c522bcdcff5142b307e23c
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jun 29 11:06:06 2017 -0400

            PR c++/81164 - ICE with invalid inherited constructor.
    
            * search.c (binfo_direct_p): New.
            * name-lookup.c (do_class_using_decl): Use it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 946a916..a70b909 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6603,6 +6603,7 @@ extern tree dfs_walk_all (tree, tree (*) (tree, void *),
 extern tree dfs_walk_once (tree, tree (*) (tree, void *),
                           tree (*) (tree, void *), void *);
 extern tree binfo_via_virtual                  (tree, tree);
+extern bool binfo_direct_p                     (tree);
 extern tree build_baselink                     (tree, tree, tree, tree);
 extern tree adjust_result_of_qualified_name_lookup
                                                (tree, tree, tree);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2ca71b6..3eb2c0d 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4172,8 +4172,7 @@ do_class_using_decl (tree scope, tree name)
              return NULL_TREE;
            }
        }
-      else if (name == ctor_identifier
-              && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo)))
+      else if (name == ctor_identifier && !binfo_direct_p (binfo))
        {
          error ("cannot inherit constructors from indirect base %qT", scope);
          return NULL_TREE;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index d7895a0..c37488d 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2973,6 +2973,28 @@ binfo_via_virtual (tree binfo, tree limit)
   return NULL_TREE;
 }
 
+/* BINFO is for a base class in some hierarchy.  Return true iff it is a
+   direct base.  */
+
+bool
+binfo_direct_p (tree binfo)
+{
+  tree d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
+  if (BINFO_INHERITANCE_CHAIN (d_binfo))
+    /* A second inheritance chain means indirect.  */
+    return false;
+  if (!BINFO_VIRTUAL_P (binfo))
+    /* Non-virtual, so only one inheritance chain means direct.  */
+    return true;
+  /* A virtual base looks like a direct base, so we need to look through the
+     direct bases to see if it's there.  */
+  tree b_binfo;
+  for (int i = 0; BINFO_BASE_ITERATE (d_binfo, i, b_binfo); ++i)
+    if (b_binfo == binfo)
+      return true;
+  return false;
+}
+
 /* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
    Find the equivalent binfo within whatever graph HERE is located.
    This is the inverse of original_binfo.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C 
b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
new file mode 100644
index 0000000..90a06c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor28.C
@@ -0,0 +1,7 @@
+// PR c++/81164
+// { dg-do compile { target c++11 } }
+
+struct A {};
+struct B : virtual A {};
+struct C : virtual A {};
+struct D : B,C { using A::A; };        // { dg-error "indirect" }

Reply via email to