bool repeated_base; /* Whether there are repeated bases in the
hierarchy. */
bool want_any; /* Whether we want any matching binfo. */
+ bool require_virtual; /* Whether we require a virtual path. */
};
/* Worker function for lookup_base. See if we've found the desired
if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), data->base))
{
+ const bool via_virtual
+ = binfo_via_virtual (binfo, data->t) != NULL_TREE;
+
+ if (data->require_virtual && !via_virtual)
+ /* Skip this result if we require virtual inheritance
+ and this is not a virtual base. */
+ return dfs_skip_bases;
+
if (!data->binfo)
{
data->binfo = binfo;
- data->via_virtual
- = binfo_via_virtual (data->binfo, data->t) != NULL_TREE;
+ data->via_virtual = via_virtual;
if (!data->repeated_base)
/* If there are no repeated bases, we can stop now. */
}
/* Prefer one via a non-virtual path. */
- if (!binfo_via_virtual (binfo, data->t))
+ if (!via_virtual)
{
data->binfo = binfo;
data->via_virtual = false;
data.repeated_base = (offset == -1) && CLASSTYPE_REPEATED_BASE_P (t);
data.want_any = access == ba_any;
data.offset = offset;
+ data.require_virtual = (access & ba_require_virtual);
dfs_walk_once (t_binfo, dfs_lookup_base, NULL, &data);
binfo = data.binfo;
Top-level cv-qualifications of @var{base_type} and
@var{derived_type} are ignored. For the purposes of this trait, a
class type is considered is own base.
+The trait is @code{true} even if @var{base_type} is an ambiguous or
+inaccessible base class of @var{derived_type}.
Requires: if @code{__is_class (base_type)} and @code{__is_class (derived_type)}
are @code{true} and @var{base_type} and @var{derived_type} are not the same
type (disregarding cv-qualifiers), @var{derived_type} shall be a complete
type. A diagnostic is produced if this requirement is not met.
@enddefbuiltin
+@defbuiltin{bool __builtin_is_virtual_base_of (@var{base_type}, @var{derived_type})}
+If @var{base_type} is a virtual base class of @var{derived_type}
+([class.derived], [class.mi]) then the trait is @code{true},
+otherwise it is @code{false}.
+Top-level cv-qualifications of @var{base_type} and
+@var{derived_type} are ignored.
+The trait is @code{true} even if @var{base_type} is an ambiguous or
+inaccessible virtual base class of @var{derived_type}.
+Requires: if @code{__is_class (base_type)} and @code{__is_class (derived_type)}
+are @code{true}, @var{derived_type} shall be a complete
+type. A diagnostic is produced if this requirement is not met.
+@enddefbuiltin
+
@defbuiltin{bool __is_class (@var{type})}
If @var{type} is a cv-qualified class type, and not a union type
([basic.compound]) the trait is @code{true}, else it is @code{false}.
--- /dev/null
+// { dg-do run }
+#include <cassert>
+
+class A1
+{
+ double a;
+ double b;
+};
+
+class A2
+{
+ double a;
+ double b;
+};
+
+class B
+: private A1 { };
+
+class C
+: private A1, private A2 { };
+
+class VD1
+: public virtual A1 { };
+
+class VD2
+: protected virtual A1 { };
+
+class VD3
+: private virtual A1 { };
+
+class D
+: public B, public VD1 { };
+
+class VDMultiple1
+: public virtual A1, public A2 { };
+
+class VDMultiple2
+: public virtual A1, public virtual A2 { };
+
+template <typename T>
+class VDTemplate : public virtual T { };
+
+// example from from [class.mi]
+namespace class_mi
+{
+class B { int b; };
+class X : virtual public B { int x; };
+class Y : virtual public B { int y; };
+class Z : public B { int z; };
+class AA : public X, public Y, public Z { int aa; };
+}
+
+union U
+{
+ double a;
+ double b;
+};
+
+template<typename T, typename U>
+ bool
+ f()
+ { return __builtin_is_virtual_base_of(T, U); }
+
+template<typename T, typename U>
+ class My
+ {
+ public:
+ bool
+ f()
+ { return !!__builtin_is_virtual_base_of(T, U); }
+ };
+
+template<typename T, typename U>
+ class My2
+ {
+ public:
+ static const bool trait = __builtin_is_virtual_base_of(T, U);
+ };
+
+template<typename T, typename U>
+ const bool My2<T, U>::trait;
+
+template<typename T, typename U, bool b = __builtin_is_virtual_base_of(T, U)>
+ struct My3_help
+ { static const bool trait = b; };
+
+template<typename T, typename U, bool b>
+ const bool My3_help<T, U, b>::trait;
+
+template<typename T, typename U>
+ class My3
+ {
+ public:
+ bool
+ f()
+ { return My3_help<T, U>::trait; }
+ };
+
+#define PTEST(T, U) (__builtin_is_virtual_base_of(T, U) && f<T, U>() \
+ && My<T, U>().f() && My2<T, U>::trait && My3<T, U>().f())
+
+#define NTEST(T, U) (!__builtin_is_virtual_base_of(T, U) && !f<T, U>() \
+ && !My<T, U>().f() && !My2<T, U>::trait && !My3<T, U>().f())
+
+int main()
+{
+ assert (NTEST (int, A1));
+ assert (NTEST (A1, void));
+ assert (NTEST (A1, A1));
+ assert (NTEST (A1*, A1*));
+ assert (NTEST (A1&, A1&));
+ assert (NTEST (A1, B));
+ assert (NTEST (B, A1));
+ assert (NTEST (A1, C));
+ assert (NTEST (A2, C));
+ assert (NTEST (C, A1));
+ assert (NTEST (A1, const B));
+ assert (NTEST (const B, A1));
+ assert (NTEST (A1, volatile C));
+ assert (NTEST (volatile A2, const C));
+ assert (NTEST (const volatile C, A1));
+
+ assert (PTEST (A1, VD1));
+ assert (PTEST (A1, VD2));
+ assert (PTEST (A1, VD3));
+
+ assert (PTEST (A1, const VD1));
+ assert (PTEST (A1, const VD2));
+ assert (PTEST (A1, const VD3));
+
+ assert (PTEST (const A1, VD1));
+ assert (PTEST (const A1, VD2));
+ assert (PTEST (const A1, VD3));
+
+ assert (PTEST (const A1, const VD1));
+ assert (PTEST (const A1, const VD2));
+ assert (PTEST (const A1, const VD3));
+
+ assert (NTEST (A2, VD1));
+ assert (NTEST (A2, VD2));
+ assert (NTEST (A2, VD3));
+
+ assert (PTEST (A1, D));
+
+ assert (PTEST (A1, VDMultiple1));
+ assert (PTEST (A1, VDMultiple2));
+ assert (NTEST (A2, VDMultiple1));
+ assert (PTEST (A2, VDMultiple2));
+
+ assert (PTEST (A1, VDTemplate<A1>));
+ assert (NTEST (A2, VDTemplate<A1>));
+ assert (NTEST (A1, VDTemplate<A2>));
+
+ assert (NTEST (class_mi::B, class_mi::B));
+ assert (PTEST (class_mi::B, class_mi::X));
+ assert (PTEST (class_mi::B, class_mi::Y));
+ assert (NTEST (class_mi::B, class_mi::Z));
+ assert (PTEST (class_mi::B, class_mi::AA));
+
+ assert (NTEST (U, U));
+
+ return 0;
+}