public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Intrinsics for N2965: Type traits and base classes
       [not found] <20110913154324.4be22faf@shotwell>
@ 2011-09-26 16:24 ` Mike Spertus
  2011-09-26 18:40   ` Jason Merrill
                     ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Mike Spertus @ 2011-09-26 16:24 UTC (permalink / raw)
  To: Benjamin Kosnik, gcc-patches, Jason Merrill; +Cc: Mike Spertus

This patch consists intrinsics to properly create the bases and 
direct_bases of a class in the correct order (including multiple nested 
ambiguous virtual and non-virtual classes) for N2965 
(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html). 
This allows you to create type traits for giving the base classes of the 
class:

template<typename _Tp>
struct bases
{
   typedef tuple<__bases(_Tp)...> type;
};

I didn't modify the standard library to include the above type trait in 
the patch because it is not yet clear what type it should return (e.g., 
a tuple, a "typelist," something satisfying the requirements of a 
boost::mpl sequence, or a generalization of parameter packs). I have 
(cursorily) tested it with the above type trait and the corresponding 
direct_bases trait.

Thanks to Jason Merrill and Benjamin Kosnik for all their help,

Mike

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c    (revision 178892)
+++ gcc/c-family/c-common.c    (working copy)
@@ -423,6 +423,7 @@
    { "__asm__",        RID_ASM,    0 },
    { "__attribute",    RID_ATTRIBUTE,    0 },
    { "__attribute__",    RID_ATTRIBUTE,    0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
    { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
    { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
    { "__builtin_offsetof", RID_OFFSETOF, 0 },
@@ -433,6 +434,7 @@
    { "__const",        RID_CONST,    0 },
    { "__const__",    RID_CONST,    0 },
    { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
    { "__extension__",    RID_EXTENSION,    0 },
    { "__func__",        RID_C99_FUNCTION_NAME, 0 },
    { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h    (revision 178892)
+++ gcc/c-family/c-common.h    (working copy)
@@ -139,7 +139,8 @@
    RID_IS_LITERAL_TYPE,         RID_IS_POD,
    RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
    RID_IS_TRIVIAL,              RID_IS_UNION,
-  RID_UNDERLYING_TYPE,
+  RID_UNDERLYING_TYPE,         RID_BASES,
+  RID_DIRECT_BASES,

    /* C++0x */
    RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, 
RID_STATIC_ASSERT,
Index: gcc/tree.h
===================================================================
--- gcc/tree.h    (revision 178892)
+++ gcc/tree.h    (working copy)
@@ -21,7 +21,6 @@

  #ifndef GCC_TREE_H
  #define GCC_TREE_H
-
  #include "hashtab.h"
  #include "machmode.h"
  #include "input.h"
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c    (revision 178892)
+++ gcc/cp/pt.c    (working copy)
@@ -2976,6 +2976,10 @@
          }
        break;

+    case BASES:
+    case DIRECT_BASES:
+      parameter_pack_p = true;
+      break;
      default:
        /* Not a parameter pack.  */
        break;
@@ -9123,6 +9127,16 @@
        tree arg_pack = NULL_TREE;
        tree orig_arg = NULL_TREE;

+      if (TREE_CODE (parm_pack) == BASES)
+        {
+          return calculate_bases(tsubst_expr(BASES_TYPE(parm_pack),
+                                 args, complain, in_decl, false));
+        }
+      if (TREE_CODE (parm_pack) == DIRECT_BASES)
+        {
+          return 
calculate_direct_bases(tsubst_expr(DIRECT_BASES_TYPE(parm_pack),
+                                        args, complain, in_decl, false));
+        }
        if (TREE_CODE (parm_pack) == PARM_DECL)
      {
        if (!cp_unevaluated_operand)
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c    (revision 178892)
+++ gcc/cp/semantics.c    (working copy)
@@ -3407,6 +3407,155 @@
    return underlying_type;
  }

+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector;
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    {
+      return bases_vec;
+    }
+  /* Virtual bases are initialized first */
+  vector = VEC_copy (tree, gc, CLASSTYPE_VBASECLASSES (type));
+
+  base_binfos = BINFO_BASE_BINFOS(TYPE_BINFO (complete_type 
(TYPE_MAIN_VARIANT (type))));
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      /* Now the non-virtual bases */
+      if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, vector, binfo);
+    }
+    }
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, 
vector, i));
+    }
+  return bases_vec;
+}
+
+tree
+finish_direct_bases (tree type)
+{
+  tree direct_bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("__direct_bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  direct_bases = cxx_make_type (DIRECT_BASES);
+  DIRECT_BASES_TYPE (direct_bases) = type;
+  SET_TYPE_STRUCTURAL_EQUALITY (direct_bases);
+
+  return direct_bases;
+
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, void *data_)
+{
+  (void)data_;
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  unsigned i;
+  VEC(tree,gc) *vbases;
+  tree binfo;
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC_safe_splice (tree, gc, vector, calculate_bases_helper 
(BINFO_TYPE (binfo)));
+    }
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (complete_type (TYPE_MAIN_VARIANT (type))),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, 
&vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector;
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    {
+      return bases_vec;
+    }
+
+  vector = calculate_bases_helper (type);
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    }
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
  /* Perform C++-specific checks for __builtin_offsetof before calling
     fold_offsetof.  */

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c    (revision 178892)
+++ gcc/cp/parser.c    (working copy)
@@ -7295,6 +7295,12 @@
      case RID_UNDERLYING_TYPE:
        kind = CPTK_UNDERLYING_TYPE;
        break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
      default:
        gcc_unreachable ();
      }
@@ -7339,9 +7345,17 @@

    /* Complete the trait expression, which may mean either processing
       the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1);
+    case CPTK_DIRECT_BASES:
+      return finish_direct_bases (type1);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
  }

  /* Lambdas that appear in variable initializer or default argument scope
@@ -12010,6 +12024,7 @@
    parser->integral_constant_expression_p = false;
    saved_non_ice_p = parser->non_integral_constant_expression_p;
    parser->non_integral_constant_expression_p = false;
+
    /* Parse the arguments.  */
    do
      {
@@ -12826,7 +12841,9 @@
        return type;

      case RID_UNDERLYING_TYPE:
-      type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);

        if (decl_specs)
      cp_parser_set_decl_spec_type (decl_specs, type,
@@ -20534,7 +20551,7 @@
  }

  /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
     return value.  */

  static tree
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def    (revision 178892)
+++ gcc/cp/cp-tree.def    (working copy)
@@ -461,6 +461,14 @@
     UNDERLYING_TYPE_TYPE is the type in question.  */
  DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)

+/* A type designated by `__bases (type)'.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
+/* A type designated by `__direct_bases (type)'.
+   DIRECT_BASES_TYPE is the type in question.  */
+DEFTREECODE (DIRECT_BASES, "direct_bases", tcc_type, 0)
+
  /* Used to represent the template information stored by template
     specializations.
     The accessors are:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h    (revision 178892)
+++ gcc/cp/cp-tree.h    (working copy)
@@ -578,7 +578,9 @@
    CPTK_IS_STD_LAYOUT,
    CPTK_IS_TRIVIAL,
    CPTK_IS_UNION,
-  CPTK_UNDERLYING_TYPE
+  CPTK_UNDERLYING_TYPE,
+  CPTK_BASES,
+  CPTK_DIRECT_BASES
  } cp_trait_kind;

  /* The types that we are processing.  */
@@ -3416,6 +3418,14 @@
  #define UNDERLYING_TYPE_TYPE(NODE) \
    (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))

+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+/* The type in question for DIRECT_BASES.  */
+#define DIRECT_BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (DIRECT_BASES_CHECK (NODE)))
+
  /* The expression in question for a DECLTYPE_TYPE.  */
  #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK 
(NODE)))

@@ -5430,6 +5440,10 @@
                                                   location_t);
  extern tree finish_typeof            (tree);
  extern tree finish_underlying_type            (tree);
+extern tree calculate_bases                (tree);
+extern tree finish_bases                (tree);
+extern tree calculate_direct_bases            (tree);
+extern tree finish_direct_bases                (tree);
  extern tree finish_offsetof            (tree);
  extern void finish_decl_cleanup            (tree, tree);
  extern void finish_eh_cleanup            (tree);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-26 16:24 ` Intrinsics for N2965: Type traits and base classes Mike Spertus
@ 2011-09-26 18:40   ` Jason Merrill
  2011-09-28  6:43   ` Benjamin Kosnik
  2011-10-18  8:23   ` Eric Botcazou
  2 siblings, 0 replies; 25+ messages in thread
From: Jason Merrill @ 2011-09-26 18:40 UTC (permalink / raw)
  To: Mike Spertus; +Cc: Benjamin Kosnik, gcc-patches

On 09/26/2011 11:50 AM, Mike Spertus wrote:
> This patch consists intrinsics to properly create the bases and direct_bases of a class

Looks pretty good.  Some comments:

>   #define GCC_TREE_H
> -
>   #include "hashtab.h"

I don't see any reason to remove this blank line.

> +      if (TREE_CODE (parm_pack) == BASES)
> +        {
> +          return calculate_bases(tsubst_expr(BASES_TYPE(parm_pack),
> +                                 args, complain, in_decl, false));
> +        }
> +      if (TREE_CODE (parm_pack) == DIRECT_BASES)
> +        {
> +          return calculate_direct_bases(tsubst_expr(DIRECT_BASES_TYPE(parm_pack),
> +                                        args, complain, in_decl, false));
> +        }

Need spaces before '(' in C code.  And we usually don't put braces 
around a single statement.

> +/* Implement the __direct_bases keyword: Return the direct base classes
> +   of type */
> +tree

Add a blank line between comment and return type.

> +  if (!NON_UNION_CLASS_TYPE_P (type))
> +    {
> +      return bases_vec;
> +    }

More braces.

> +  /* Virtual bases are initialized first */
> +  vector = VEC_copy (tree, gc, CLASSTYPE_VBASECLASSES (type));

This will get you indirect virtual bases as well as direct.

> +  base_binfos = BINFO_BASE_BINFOS(TYPE_BINFO (complete_type (TYPE_MAIN_VARIANT (type))));

Another missing space.  And you don't need either complete_type or 
TYPE_MAIN_VARIANT here; all variants get completed together by the 
complete_type earlier in the function, and TYPE_BINFO is the same for 
all variants.

> +  /* First go through virtual base classes */
> +  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
> +       VEC_iterate (tree, vbases, i, binfo); i++)
> +    {
> +      VEC_safe_splice (tree, gc, vector, calculate_bases_helper (BINFO_TYPE (binfo)));
> +    }

Looks like you'll get duplicates if a virtual base itself has virtual bases.

Let's release_tree_vector the returned vector after we've spliced it on.

> +  dfs_walk_all (TYPE_BINFO (complete_type (TYPE_MAIN_VARIANT (type))),

Again, TYPE_BINFO (type) should be enough.

> +DEFTREECODE (BASES, "bases", tcc_type, 0)
> +DEFTREECODE (DIRECT_BASES, "direct_bases", tcc_type, 0)

Instead of two tree codes, let's use one and a flag.  Also combine 
finish_bases and finish_direct_bases.

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-26 16:24 ` Intrinsics for N2965: Type traits and base classes Mike Spertus
  2011-09-26 18:40   ` Jason Merrill
@ 2011-09-28  6:43   ` Benjamin Kosnik
  2011-09-28  6:49     ` Benjamin Kosnik
  2011-09-28  7:08     ` Michael Spertus
  2011-10-18  8:23   ` Eric Botcazou
  2 siblings, 2 replies; 25+ messages in thread
From: Benjamin Kosnik @ 2011-09-28  6:43 UTC (permalink / raw)
  To: Mike Spertus; +Cc: gcc-patches, Jason Merrill, libstdc++

[-- Attachment #1: Type: text/plain, Size: 1114 bytes --]


> This patch consists intrinsics to properly create the bases and 
> direct_bases of a class in the correct order (including multiple
> nested ambiguous virtual and non-virtual classes) for N2965 
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html). 
> This allows you to create type traits for giving the base classes of
> the class:
> 
> template<typename _Tp>
> struct bases
> {
>    typedef tuple<__bases(_Tp)...> type;
> };

Cool! So glad to see this.
 
> I didn't modify the standard library to include the above type trait
> in the patch because it is not yet clear what type it should return
> (e.g., a tuple, a "typelist," something satisfying the requirements
> of a boost::mpl sequence, or a generalization of parameter packs). I
> have (cursorily) tested it with the above type trait and the
> corresponding direct_bases trait.

OK.

Here's a patch for the above. What's wrong with tuple? I kind of like
it.... seems simple. It's what's in N2965, so let's start there.

Since it's the first TR2 header, I did the build bits for you. 

Also, I cc'd the library list. 

best,
benjamin

[-- Attachment #2: 20110927-4.patch --]
[-- Type: text/x-patch, Size: 5074 bytes --]

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a59a0b6..e1176ee 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,14 @@
 2011-09-27  Benjamin Kosnik  <bkoz@redhat.com>
 
+	* doc/Makefile.am: Add tr2 support.
+	* doc/Makefile.in: Regenerate.
+
+2011-09-27  Mike Spertus  <mike_spertus@symantec.com>
+
+	* include/tr2/type_traits (bases, direct_bases): New.
+
+2011-09-27  Benjamin Kosnik  <bkoz@redhat.com>
+
 	* doc/html/*: Regenerate.
 
 	* doc/Makefile.am: Un-nest the ext output directory.
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 4016882..9fdaa8d 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -604,6 +604,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -887,7 +892,7 @@ endif
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1002,6 +1007,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1245,6 +1255,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1291,7 +1304,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 58dbfc4..5ad5932 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -854,6 +854,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -1125,7 +1130,7 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS)
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1402,6 +1407,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1630,6 +1640,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1673,7 +1686,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28  6:43   ` Benjamin Kosnik
@ 2011-09-28  6:49     ` Benjamin Kosnik
  2011-09-28  7:08     ` Michael Spertus
  1 sibling, 0 replies; 25+ messages in thread
From: Benjamin Kosnik @ 2011-09-28  6:49 UTC (permalink / raw)
  To: Benjamin Kosnik; +Cc: Mike Spertus, gcc-patches, Jason Merrill, libstdc++

[-- Attachment #1: Type: text/plain, Size: 43 bytes --]


Oops, this is the right patch. 

-benjamin

[-- Attachment #2: 20110927-5.patch --]
[-- Type: text/x-patch, Size: 7200 bytes --]

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a59a0b6..e1176ee 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,14 @@
 2011-09-27  Benjamin Kosnik  <bkoz@redhat.com>
 
+	* doc/Makefile.am: Add tr2 support.
+	* doc/Makefile.in: Regenerate.
+
+2011-09-27  Mike Spertus  <mike_spertus@symantec.com>
+
+	* include/tr2/type_traits (bases, direct_bases): New.
+
+2011-09-27  Benjamin Kosnik  <bkoz@redhat.com>
+
 	* doc/html/*: Regenerate.
 
 	* doc/Makefile.am: Un-nest the ext output directory.
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 4016882..9fdaa8d 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -604,6 +604,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -887,7 +892,7 @@ endif
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1002,6 +1007,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1245,6 +1255,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1291,7 +1304,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 58dbfc4..5ad5932 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -854,6 +854,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -1125,7 +1130,7 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS)
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1402,6 +1407,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1630,6 +1640,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1673,7 +1686,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
new file mode 100644
index 0000000..580466b
--- /dev/null
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -0,0 +1,67 @@
+// C++ type_traits intended for TR2 -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <bits/c++0x_warning.h>
+#else
+
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+
+  /**
+   * @addtogroup metaprogramming
+   * @{
+   */
+
+  /// N2965 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html
+  template<typename _Tp>
+  struct bases
+  {
+    typedef tuple<__bases(_Tp)...> 		type;
+  };
+
+  template<typename _Tp>
+  struct direct_bases
+  {
+    typedef tuple<__direct_bases(_Tp)...> 	type;
+  };
+  // @} group metaprogramming
+
+} // namespace tr2
+} // namespace std
+
+#endif  // _GLIBCXX_TR2_TYPE_TRAITS

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28  6:43   ` Benjamin Kosnik
  2011-09-28  6:49     ` Benjamin Kosnik
@ 2011-09-28  7:08     ` Michael Spertus
  2011-09-28  9:33       ` Jonathan Wakely
  1 sibling, 1 reply; 25+ messages in thread
From: Michael Spertus @ 2011-09-28  7:08 UTC (permalink / raw)
  To: Benjamin Kosnik; +Cc: gcc-patches, Jason Merrill, libstdc++

Benjamin,
I think tuple is wrong both for performance reasons (I believe these are likely to be serious enough to depress use due to inordinately long compiles) and because it prematurely locks us into a rigid choice of how our typelists are implemented. 

My inclination is to make it type-independent by returning an unspecified type that can have a sequence of types extracted from it (this is the approach taken by boost::mpl and has loads of experience that shows it is a good approach to metaprogramming). In other words, first<bases<A>>::type would be the first base of A, etc. 

I've coded this up, and it seems to work very well without committing us to any particular typelist implementation. I don't think it has any downsides relative to tuple. I'll do a little benchmarking to compare it to tuple (I suspect it will be far faster) and then send to the library list,

Mike

Sent from my iPhone

On Sep 27, 2011, at 9:59 PM, "Benjamin Kosnik" <bkoz@redhat.com> wrote:

> 
>> This patch consists intrinsics to properly create the bases and 
>> direct_bases of a class in the correct order (including multiple
>> nested ambiguous virtual and non-virtual classes) for N2965 
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html). 
>> This allows you to create type traits for giving the base classes of
>> the class:
>> 
>> template<typename _Tp>
>> struct bases
>> {
>>   typedef tuple<__bases(_Tp)...> type;
>> };
> 
> Cool! So glad to see this.
> 
>> I didn't modify the standard library to include the above type trait
>> in the patch because it is not yet clear what type it should return
>> (e.g., a tuple, a "typelist," something satisfying the requirements
>> of a boost::mpl sequence, or a generalization of parameter packs). I
>> have (cursorily) tested it with the above type trait and the
>> corresponding direct_bases trait.
> 
> OK.
> 
> Here's a patch for the above. What's wrong with tuple? I kind of like
> it.... seems simple. It's what's in N2965, so let's start there.
> 
> Since it's the first TR2 header, I did the build bits for you. 
> 
> Also, I cc'd the library list. 
> 
> best,
> benjamin
> <20110927-4.patch>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28  7:08     ` Michael Spertus
@ 2011-09-28  9:33       ` Jonathan Wakely
  2011-09-28 12:49         ` Mike Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Jonathan Wakely @ 2011-09-28  9:33 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, gcc-patches, Jason Merrill, libstdc++

On 28 September 2011 04:22, Michael Spertus wrote:
> Benjamin,
> I think tuple is wrong both for performance reasons (I believe these are likely to be serious enough to depress use due to inordinately long compiles) and because it prematurely locks us into a rigid choice of how our typelists are implemented.
>
> My inclination is to make it type-independent by returning an unspecified type that can have a sequence of types extracted from it (this is the approach taken by boost::mpl and has loads of experience that shows it is a good approach to metaprogramming). In other words, first<bases<A>>::type would be the first base of A, etc.

Citing Boost MPL as a good way to avoid inordinately long compiles ...
interesting!  Have you ever tried to reduce a GCC bug report from 20k
lines to 20, because most Boost libs include every MPL header?!

I hope we can get a simple typelist _without_ needing everything else
in MPL, such as the apply and lambda metafunctions (and maybe a lot of
that could be massively simplified using variadic templates anyway.)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28  9:33       ` Jonathan Wakely
@ 2011-09-28 12:49         ` Mike Spertus
  2011-09-28 13:57           ` Mike Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Mike Spertus @ 2011-09-28 12:49 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Benjamin Kosnik, gcc-patches, Jason Merrill, libstdc++

Don't worry, I'm not suggesting including boost::mpl at all, just 
leaving the return type of the bases trait unspecified. IMO, your 
example illustrates my point that without performance tuning, compiling 
metaprograms can be prohibitively expensive, so I want to avoid running 
the tuple metaprogram that creates the fields when we never need to 
instantiate the type. Benchmarks soon.

Mike

On 9/28/2011 2:53 AM, Jonathan Wakely wrote:
> On 28 September 2011 04:22, Michael Spertus wrote:
>    
>> Benjamin,
>> I think tuple is wrong both for performance reasons (I believe these are likely to be serious enough to depress use due to inordinately long compiles) and because it prematurely locks us into a rigid choice of how our typelists are implemented.
>>
>> My inclination is to make it type-independent by returning an unspecified type that can have a sequence of types extracted from it (this is the approach taken by boost::mpl and has loads of experience that shows it is a good approach to metaprogramming). In other words, first<bases<A>>::type would be the first base of A, etc.
>>      
> Citing Boost MPL as a good way to avoid inordinately long compiles ...
> interesting!  Have you ever tried to reduce a GCC bug report from 20k
> lines to 20, because most Boost libs include every MPL header?!
>
> I hope we can get a simple typelist _without_ needing everything else
> in MPL, such as the apply and lambda metafunctions (and maybe a lot of
> that could be massively simplified using variadic templates anyway.)
>
> .
>
>    

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28 12:49         ` Mike Spertus
@ 2011-09-28 13:57           ` Mike Spertus
  2011-09-29 19:42             ` Benjamin Kosnik
  0 siblings, 1 reply; 25+ messages in thread
From: Mike Spertus @ 2011-09-28 13:57 UTC (permalink / raw)
  To: Mike Spertus
  Cc: Jonathan Wakely, Benjamin Kosnik, gcc-patches, Jason Merrill,
	libstdc++,
	Mike Spertus

OK. Here are some simple benchmarks. I simulated heavy use of reflection 
with 1000 classes that each had about a thousand base classes. I also 
created a super-simple typelist class

template<typename... T> struct typelist {}; // Variadic templates rock

If bases returns a typelist, the program takes about 4 sec.
If bases returns a tuple, the program takes about 4 min.

If I make the program any bigger, the tuple case fails to compile with 
spurious error messages, while the typelist version stays quick.

Given that metaprograms typically create large class hierarchies (look 
at Alexandrescu's CreateScatterHierarchy that he uses to implement 
factory in the Modern C++ design book) and that compile times are an 
enormous obstacle to metaprogramming, I don't think these tests are at 
all ridiculous.

I think this shows we need to return a typelist instead of a tuple.

As I mentioned earlier, I could just return the typelist, or hide it by 
returning an unspecified type (which would actually be a typelist) that 
you would apply a first<> and a rest<> template to walk through. This 
would give us more flexibility for the future (e.g., if a standard 
typelist type is adopted. Likewise, we would be covered if wanted to 
change bases implementation in the future to return an associative 
container. For example, if using size<grep<A, bases<E>::type>>::value to 
count the number of occurrences of A as a base class of E turns out to 
be useful).

Thanks,

Mike

On 9/28/2011 6:54 AM, Mike Spertus wrote:
> Don't worry, I'm not suggesting including boost::mpl at all, just 
> leaving the return type of the bases trait unspecified. IMO, your 
> example illustrates my point that without performance tuning, 
> compiling metaprograms can be prohibitively expensive, so I want to 
> avoid running the tuple metaprogram that creates the fields when we 
> never need to instantiate the type. Benchmarks soon.
>
> Mike
>
> On 9/28/2011 2:53 AM, Jonathan Wakely wrote:
>> On 28 September 2011 04:22, Michael Spertus wrote:
>>> Benjamin,
>>> I think tuple is wrong both for performance reasons (I believe these 
>>> are likely to be serious enough to depress use due to inordinately 
>>> long compiles) and because it prematurely locks us into a rigid 
>>> choice of how our typelists are implemented.
>>>
>>> My inclination is to make it type-independent by returning an 
>>> unspecified type that can have a sequence of types extracted from it 
>>> (this is the approach taken by boost::mpl and has loads of 
>>> experience that shows it is a good approach to metaprogramming). In 
>>> other words, first<bases<A>>::type would be the first base of A, etc.
>> Citing Boost MPL as a good way to avoid inordinately long compiles ...
>> interesting!  Have you ever tried to reduce a GCC bug report from 20k
>> lines to 20, because most Boost libs include every MPL header?!
>>
>> I hope we can get a simple typelist _without_ needing everything else
>> in MPL, such as the apply and lambda metafunctions (and maybe a lot of
>> that could be massively simplified using variadic templates anyway.)
>>
>> .
>>
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-28 13:57           ` Mike Spertus
@ 2011-09-29 19:42             ` Benjamin Kosnik
  2011-10-03  1:55               ` Michael Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Benjamin Kosnik @ 2011-09-29 19:42 UTC (permalink / raw)
  To: Mike Spertus; +Cc: Jonathan Wakely, gcc-patches, Jason Merrill, libstdc++


> OK. Here are some simple benchmarks. I simulated heavy use of
> reflection with 1000 classes that each had about a thousand base
> classes. I also created a super-simple typelist class
> 
> template<typename... T> struct typelist {}; // Variadic templates rock
> 
> If bases returns a typelist, the program takes about 4 sec.
> If bases returns a tuple, the program takes about 4 min.
> 
> If I make the program any bigger, the tuple case fails to compile
> with spurious error messages, while the typelist version stays quick.
> 
> Given that metaprograms typically create large class hierarchies
> (look at Alexandrescu's CreateScatterHierarchy that he uses to
> implement factory in the Modern C++ design book) and that compile
> times are an enormous obstacle to metaprogramming, I don't think
> these tests are at all ridiculous.
> 
> I think this shows we need to return a typelist instead of a tuple.

Yes, compelling.
 
> As I mentioned earlier, I could just return the typelist, or hide it
> by returning an unspecified type (which would actually be a typelist)
> that you would apply a first<> and a rest<> template to walk through.

The interface is still simple, I like it.

> This would give us more flexibility for the future (e.g., if a
> standard typelist type is adopted. Likewise, we would be covered if
> wanted to change bases implementation in the future to return an
> associative container. For example, if using size<grep<A,
> bases<E>::type>>::value to count the number of occurrences of A as a
> base class of E turns out to be useful).

This plan sounds excellent to me.

-benjamin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: Intrinsics for N2965: Type traits and base classes
  2011-09-29 19:42             ` Benjamin Kosnik
@ 2011-10-03  1:55               ` Michael Spertus
  2011-10-03 13:08                 ` Jason Merrill
                                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Michael Spertus @ 2011-10-03  1:55 UTC (permalink / raw)
  To: Benjamin Kosnik
  Cc: Jonathan Wakely, gcc-patches, Jason Merrill, libstdc++, Michael Spertus

OK. Here is a new diff that hopefully takes into account all of Jason's and Benjamin's comments. Benjamin's TR2 build patch is not repeated (or tested!) here. Benjamin, I'd really appreciate if you wouldn't mind confirming I handled that correctly in tr2/type_traits (Including the inclusion of std/type_traits).

Thanks,

Mike


Index: libstdc++-v3/include/tr2/type_traits
===================================================================
--- libstdc++-v3/include/tr2/type_traits	(revision 0)
+++ libstdc++-v3/include/tr2/type_traits	(revision 0)
@@ -0,0 +1,96 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header. 
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements> struct typelist;
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      struct first
+      {
+        typedef _First type;
+      };
+
+      struct rest
+      {
+        typedef typelist<_Rest...> type;
+      };
+
+      typedef std::false_type empty;
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename T> struct first : public T::first {};
+  template<typename T> struct rest : public T::rest {};
+  template<typename T> struct empty : public T::empty {};
+
+
+  template<typename T>
+    struct bases
+    {
+	  typedef typelist<__bases(T)...> type;
+    };
+
+  template<typename T>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(T)...> type;
+    };
+	
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 178892)
+++ gcc/c-family/c-common.c	(working copy)
@@ -423,6 +423,7 @@
   { "__asm__",		RID_ASM,	0 },
   { "__attribute",	RID_ATTRIBUTE,	0 },
   { "__attribute__",	RID_ATTRIBUTE,	0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
@@ -433,6 +434,7 @@
   { "__const",		RID_CONST,	0 },
   { "__const__",	RID_CONST,	0 },
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME, 0 },
   { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 178892)
+++ gcc/c-family/c-common.h	(working copy)
@@ -139,7 +139,8 @@
   RID_IS_LITERAL_TYPE,         RID_IS_POD,
   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
   RID_IS_TRIVIAL,              RID_IS_UNION,
-  RID_UNDERLYING_TYPE,
+  RID_UNDERLYING_TYPE,         RID_BASES,
+  RID_DIRECT_BASES,
 
   /* C++0x */
   RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 178892)
+++ gcc/cp/pt.c	(working copy)
@@ -2976,6 +2976,9 @@
         }
       break;
 
+    case BASES:
+      parameter_pack_p = true;
+      break;
     default:
       /* Not a parameter pack.  */
       break;
@@ -9123,6 +9126,15 @@
       tree arg_pack = NULL_TREE;
       tree orig_arg = NULL_TREE;
 
+      if (TREE_CODE (parm_pack) == BASES)
+	{
+	  if (BASES_DIRECT (parm_pack))
+	    return calculate_direct_bases (tsubst_expr(BASES_TYPE(parm_pack),
+                                           args, complain, in_decl, false));
+	  else
+	    return calculate_bases (tsubst_expr(BASES_TYPE(parm_pack),
+                                args, complain, in_decl, false));
+	}
       if (TREE_CODE (parm_pack) == PARM_DECL)
 	{
 	  if (!cp_unevaluated_operand)
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 178892)
+++ gcc/cp/semantics.c	(working copy)
@@ -3407,6 +3407,150 @@
   return underlying_type;
 }
 
+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return bases_vec;
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+	{
+	  VEC_safe_push (tree, gc, vector, binfo);
+	}
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+	{
+	  VEC_safe_push (tree, gc, vector, binfo);
+	}
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    } 
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, void *data_)
+{
+  (void)data_;
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+  
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return bases_vec;
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    } 
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 178892)
+++ gcc/cp/parser.c	(working copy)
@@ -7295,6 +7295,12 @@
     case RID_UNDERLYING_TYPE:
       kind = CPTK_UNDERLYING_TYPE;
       break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7339,9 +7345,17 @@
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1, false);
+    case CPTK_DIRECT_BASES:
+      return finish_bases (type1, true);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
 }
 
 /* Lambdas that appear in variable initializer or default argument scope
@@ -12010,6 +12024,7 @@
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
   parser->non_integral_constant_expression_p = false;
+
   /* Parse the arguments.  */
   do
     {
@@ -12826,7 +12841,9 @@
       return type;
 
     case RID_UNDERLYING_TYPE:
-      type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);
 
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
@@ -20534,7 +20551,7 @@
 }
 
 /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
    return value.  */
 
 static tree
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def	(revision 178892)
+++ gcc/cp/cp-tree.def	(working copy)
@@ -461,6 +461,10 @@
    UNDERLYING_TYPE_TYPE is the type in question.  */
 DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)
 
+/* A type designated by one of the bases type traits.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
 /* Used to represent the template information stored by template
    specializations.
    The accessors are:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 178892)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -578,7 +578,9 @@
   CPTK_IS_STD_LAYOUT,
   CPTK_IS_TRIVIAL,
   CPTK_IS_UNION,
-  CPTK_UNDERLYING_TYPE
+  CPTK_UNDERLYING_TYPE,
+  CPTK_BASES,
+  CPTK_DIRECT_BASES
 } cp_trait_kind;
 
 /* The types that we are processing.  */
@@ -3416,6 +3418,13 @@
 #define UNDERLYING_TYPE_TYPE(NODE) \
   (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
 
+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+  TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
 /* The expression in question for a DECLTYPE_TYPE.  */
 #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
 
@@ -5430,6 +5439,9 @@
                                                  location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_underlying_type	        (tree);
+extern tree calculate_bases	        	(tree);
+extern tree finish_bases	        	(tree, bool);
+extern tree calculate_direct_bases        	(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
 extern void finish_eh_cleanup			(tree);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-03  1:55               ` Michael Spertus
@ 2011-10-03 13:08                 ` Jason Merrill
  2011-10-03 15:51                 ` Jonathan Wakely
  2011-10-04  4:41                 ` Benjamin Kosnik
  2 siblings, 0 replies; 25+ messages in thread
From: Jason Merrill @ 2011-10-03 13:08 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++

The code looks good, though you are still missing some spaces before 
'('.  The main thing left is some testcases.

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-03  1:55               ` Michael Spertus
  2011-10-03 13:08                 ` Jason Merrill
@ 2011-10-03 15:51                 ` Jonathan Wakely
  2011-10-04  4:41                 ` Benjamin Kosnik
  2 siblings, 0 replies; 25+ messages in thread
From: Jonathan Wakely @ 2011-10-03 15:51 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, gcc-patches, Jason Merrill, libstdc++

On 3 October 2011 02:55, Michael Spertus wrote:
> Index: gcc/c-family/c-common.h
> ===================================================================
> --- gcc/c-family/c-common.h     (revision 178892)
> +++ gcc/c-family/c-common.h     (working copy)
> @@ -139,7 +139,8 @@
>   RID_IS_LITERAL_TYPE,         RID_IS_POD,
>   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
>   RID_IS_TRIVIAL,              RID_IS_UNION,
> -  RID_UNDERLYING_TYPE,
> +  RID_UNDERLYING_TYPE,         RID_BASES,
> +  RID_DIRECT_BASES,


Should that be kept in alphabetical order?

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-03  1:55               ` Michael Spertus
  2011-10-03 13:08                 ` Jason Merrill
  2011-10-03 15:51                 ` Jonathan Wakely
@ 2011-10-04  4:41                 ` Benjamin Kosnik
  2011-10-04  5:04                   ` Benjamin Kosnik
  2 siblings, 1 reply; 25+ messages in thread
From: Benjamin Kosnik @ 2011-10-04  4:41 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Jonathan Wakely, gcc-patches, Jason Merrill, libstdc++

[-- Attachment #1: Type: text/plain, Size: 748 bytes --]


> OK. Here is a new diff that hopefully takes into account all of
> Jason's and Benjamin's comments. Benjamin's TR2 build patch is not
> repeated (or tested!) here. Benjamin, I'd really appreciate if you
> wouldn't mind confirming I handled that correctly in tr2/type_traits
> (Including the inclusion of std/type_traits).

Hey! Here is a preliminary test suite. Just the basics on this one.
There's a bit of an issue with fundamental types, ICEs, but seems
fixable.

From here on in, just populate the testsuite/tr2/* directories with .cc
files. They will be tested by the testsuite machinery.

Your typelist interface looks pretty good. We should start here for the
interface, and can embellish it after it goes in.

-benjamin

[-- Attachment #2: 20111003-1.patch --]
[-- Type: text/x-patch, Size: 15575 bytes --]

diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
new file mode 100644
index 0000000..94aebf0
--- /dev/null
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -0,0 +1,102 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements> 
+    struct typelist;
+
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type 			empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      typedef std::false_type 			empty;
+
+      struct first
+      {
+	typedef _First 				type;
+      };
+
+      struct rest
+      {
+	typedef typelist<_Rest...> 		type;
+      };
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename _Tp>
+    struct first : public _Tp::first { };
+
+  template<typename _Tp>
+    struct rest : public _Tp::rest { };
+
+  template<typename _Tp>
+    struct empty : public _Tp::empty { };
+
+
+  template<typename _Tp>
+    struct bases
+    {
+      typedef typelist<__bases(_Tp)...> 	type;
+    };
+
+  template<typename _Tp>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(_Tp)...> 	type;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index f4a0bcd..a427eef 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -32,7 +32,7 @@ cd $srcdir
 # This is the ugly version of "everything but the current directory".  It's
 # what has to happen when find(1) doesn't support -mindepth, or -xtype.
 dlist=`echo [0-9][0-9]*`
-dlist="$dlist abi backward ext performance tr1 decimal"
+dlist="$dlist abi backward ext performance tr1 tr2 decimal"
 find $dlist "(" -type f -o -type l ")" -name "*.cc" -print > $tmp.01
 find $dlist "(" -type f -o -type l ")" -name "*.c" -print > $tmp.02
 cat  $tmp.01 $tmp.02 | sort > $tmp.1
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 8642eb7..19fa0e2 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -58,6 +58,7 @@ if {[info exists tests_file] && [file exists $tests_file]} {
     lappend subdirs "$srcdir/ext"
     lappend subdirs "$srcdir/performance"
     lappend subdirs "$srcdir/tr1"
+    lappend subdirs "$srcdir/tr2"
     lappend subdirs "$srcdir/decimal"
     verbose "subdirs are $subdirs"
 
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..ddd6d6f
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+  namespace tr2
+  {
+    typedef short test_type;
+    template struct bases<test_type>;
+  }
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
new file mode 100644
index 0000000..a62acff
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::tr2::bases<int>            test_type;
+  typedef test_type::type            value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/value.cc b/libstdc++-v3/testsuite/tr2/bases/value.cc
new file mode 100644
index 0000000..415e974
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/value.cc
@@ -0,0 +1,97 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+  bool test __attribute__((unused)) = true;
+
+  // 1
+  {
+    typedef std::tr2::bases<A>::type tl;
+    static_assert(tl::empty::value, "error");
+  }
+
+  // 2
+  {
+    typedef std::tr2::bases<B1>::type tl1;
+    typedef std::tr2::bases<B2>::type tl2;
+
+    // Sanity check w/ runtime.
+    bool eq = typeid(tl1) == typeid(tl2);
+    if (!eq)
+      throw std::logic_error("typelist not equal");
+
+    // Sanity check.
+    static_assert(tl1::empty::value != std::true_type::value, "!empty");
+    static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+    typedef tl1::first::type		tl1_first;
+    typedef tl1::rest::type		tl1_rest;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl2_rest;
+
+    eq = typeid(tl1_first) == typeid(tl2_first);
+    if (!eq)
+      throw std::logic_error("base not equal");
+
+    static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+    static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+  }
+
+  // 3
+  {
+    typedef std::tr2::bases<C>::type tl;
+
+    // Sanity check.
+    static_assert(tl::empty::value != std::true_type::value, "!empty");
+  
+    typedef tl::first::type		tl1_first;
+    typedef tl::rest::type		tl2;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl3;
+    typedef tl3::first::type		tl3_first;
+    typedef tl3::rest::type		tl4;
+
+    bool eq = typeid(tl1_first) == typeid(tl2_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    eq = typeid(tl2_first) == typeid(tl3_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    static_assert(tl4::empty::value == std::true_type::value, "empty");
+  }
+
+}
+
+int main()
+{
+  test();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..d7fb96a
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+  namespace tr2
+  {
+    typedef short test_type;
+    template struct direct_bases<test_type>;
+  }
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
new file mode 100644
index 0000000..7d219ea
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::tr2::direct_bases<int>            test_type;
+  typedef test_type::type            value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/value.cc b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
new file mode 100644
index 0000000..81d0269
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+  bool test __attribute__((unused)) = true;
+
+  // 1
+  {
+    typedef std::tr2::direct_bases<A>::type tl;
+    static_assert(tl::empty::value, "error");
+  }
+
+  // 2
+  {
+    typedef std::tr2::direct_bases<B1>::type tl1;
+    typedef std::tr2::direct_bases<B2>::type tl2;
+
+    // Sanity check w/ runtime.
+    bool eq = typeid(tl1) == typeid(tl2);
+    if (!eq)
+      throw std::logic_error("typelist not equal");
+
+    // Sanity check.
+    static_assert(tl1::empty::value != std::true_type::value, "!empty");
+    static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+    typedef tl1::first::type		tl1_first;
+    typedef tl1::rest::type		tl1_rest;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl2_rest;
+
+    eq = typeid(tl1_first) == typeid(tl2_first);
+    if (!eq)
+      throw std::logic_error("base not equal");
+
+    static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+    static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+  }
+
+  // 3
+  {
+    typedef std::tr2::direct_bases<C>::type tl;
+
+    // Sanity check.
+    static_assert(tl::empty::value != std::true_type::value, "!empty");
+  
+    typedef tl::first::type		tl1_first;
+    typedef tl::rest::type		tl2;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl3;
+
+    bool eq = typeid(tl1_first) == typeid(tl2_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    static_assert(tl3::empty::value == std::true_type::value, "empty");
+  }
+
+}
+
+int main()
+{
+  test();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-04  4:41                 ` Benjamin Kosnik
@ 2011-10-04  5:04                   ` Benjamin Kosnik
  2011-10-09 19:31                     ` Michael Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Benjamin Kosnik @ 2011-10-04  5:04 UTC (permalink / raw)
  To: Benjamin Kosnik
  Cc: Michael Spertus, Jonathan Wakely, gcc-patches, Jason Merrill, libstdc++

[-- Attachment #1: Type: text/plain, Size: 206 bytes --]


> Hey! Here is a preliminary test suite. Just the basics on this one.
> There's a bit of an issue with fundamental types, ICEs, but seems
> fixable.

here's the pre-processed sources for the ICE

-benjamin

[-- Attachment #2: ice-reflection-1.ii.bz2 --]
[-- Type: application/x-bzip, Size: 5363 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: Intrinsics for N2965: Type traits and base classes
  2011-10-04  5:04                   ` Benjamin Kosnik
@ 2011-10-09 19:31                     ` Michael Spertus
  2011-10-09 19:38                       ` Jason Merrill
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Spertus @ 2011-10-09 19:31 UTC (permalink / raw)
  To: Benjamin Kosnik
  Cc: Jonathan Wakely, gcc-patches, Jason Merrill, libstdc++, Michael Spertus

Here is a new diff that works for non-class types (fixing Benjamin's failing test), fixes some spacing and alphabetization, and doesn't inadvertently break the __underlying_type trait.

Index: libstdc++-v3/include/tr2/type_traits
===================================================================
--- libstdc++-v3/include/tr2/type_traits	(revision 0)
+++ libstdc++-v3/include/tr2/type_traits	(revision 0)
@@ -0,0 +1,96 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header. 
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements> struct typelist;
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      struct first
+      {
+        typedef _First type;
+      };
+
+      struct rest
+      {
+        typedef typelist<_Rest...> type;
+      };
+
+      typedef std::false_type empty;
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename T> struct first : public T::first {};
+  template<typename T> struct rest : public T::rest {};
+  template<typename T> struct empty : public T::empty {};
+
+
+  template<typename T>
+    struct bases
+    {
+	  typedef typelist<__bases(T)...> type;
+    };
+
+  template<typename T>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(T)...> type;
+    };
+	
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 178892)
+++ gcc/c-family/c-common.c	(working copy)
@@ -423,6 +423,7 @@
   { "__asm__",		RID_ASM,	0 },
   { "__attribute",	RID_ATTRIBUTE,	0 },
   { "__attribute__",	RID_ATTRIBUTE,	0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
@@ -433,6 +434,7 @@
   { "__const",		RID_CONST,	0 },
   { "__const__",	RID_CONST,	0 },
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME, 0 },
   { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 178892)
+++ gcc/c-family/c-common.h	(working copy)
@@ -129,12 +129,13 @@
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
   /* C++ extensions */
+  RID_BASES,		       RID_DIRECT_BASES,
   RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
   RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
   RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
   RID_HAS_TRIVIAL_DESTRUCTOR,  RID_HAS_VIRTUAL_DESTRUCTOR,
   RID_IS_ABSTRACT,             RID_IS_BASE_OF,
-  RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
+  RID_IS_CLASS,                RID_IS_CONVERTIBLE_TO,      
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_LITERAL_TYPE,         RID_IS_POD,
   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 178892)
+++ gcc/cp/pt.c	(working copy)
@@ -2976,6 +2976,9 @@
         }
       break;
 
+    case BASES:
+      parameter_pack_p = true;
+      break;
     default:
       /* Not a parameter pack.  */
       break;
@@ -9123,6 +9126,15 @@
       tree arg_pack = NULL_TREE;
       tree orig_arg = NULL_TREE;
 
+      if (TREE_CODE (parm_pack) == BASES)
+	{
+	  if (BASES_DIRECT (parm_pack))
+	    return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                        args, complain, in_decl, false));
+	  else
+	    return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                 args, complain, in_decl, false));
+	}
       if (TREE_CODE (parm_pack) == PARM_DECL)
 	{
 	  if (!cp_unevaluated_operand)
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 178892)
+++ gcc/cp/semantics.c	(working copy)
@@ -3407,6 +3407,150 @@
   return underlying_type;
 }
 
+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+	{
+	  VEC_safe_push (tree, gc, vector, binfo);
+	}
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+	{
+	  VEC_safe_push (tree, gc, vector, binfo);
+	}
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    } 
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, void *data_)
+{
+  (void)data_;
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+  
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    } 
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 178892)
+++ gcc/cp/parser.c	(working copy)
@@ -7295,6 +7295,12 @@
     case RID_UNDERLYING_TYPE:
       kind = CPTK_UNDERLYING_TYPE;
       break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7339,9 +7345,17 @@
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1, false);
+    case CPTK_DIRECT_BASES:
+      return finish_bases (type1, true);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
 }
 
 /* Lambdas that appear in variable initializer or default argument scope
@@ -12010,6 +12024,7 @@
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
   parser->non_integral_constant_expression_p = false;
+
   /* Parse the arguments.  */
   do
     {
@@ -12827,7 +12842,6 @@
 
     case RID_UNDERLYING_TYPE:
       type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
@@ -12835,6 +12849,14 @@
 
       return type;
 
+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);
+      if (decl_specs)
+	cp_parser_set_decl_spec_type (decl_specs, type,
+				      token->location,
+				      /*type_definition_p=*/false);
+      return type;
     default:
       break;
     }
@@ -20534,7 +20556,7 @@
 }
 
 /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
    return value.  */
 
 static tree
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def	(revision 178892)
+++ gcc/cp/cp-tree.def	(working copy)
@@ -461,6 +461,10 @@
    UNDERLYING_TYPE_TYPE is the type in question.  */
 DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)
 
+/* A type designated by one of the bases type traits.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
 /* Used to represent the template information stored by template
    specializations.
    The accessors are:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 178892)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -558,6 +558,8 @@
 
 typedef enum cp_trait_kind
 {
+  CPTK_BASES,
+  CPTK_DIRECT_BASES,
   CPTK_HAS_NOTHROW_ASSIGN,
   CPTK_HAS_NOTHROW_CONSTRUCTOR,
   CPTK_HAS_NOTHROW_COPY,
@@ -3416,6 +3418,13 @@
 #define UNDERLYING_TYPE_TYPE(NODE) \
   (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
 
+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+  TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
 /* The expression in question for a DECLTYPE_TYPE.  */
 #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
 
@@ -5430,6 +5439,9 @@
                                                  location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_underlying_type	        (tree);
+extern tree calculate_bases	        	(tree);
+extern tree finish_bases	        	(tree, bool);
+extern tree calculate_direct_bases        	(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
 extern void finish_eh_cleanup			(tree);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-09 19:31                     ` Michael Spertus
@ 2011-10-09 19:38                       ` Jason Merrill
  2011-10-11  0:12                         ` Benjamin Kosnik
  2011-10-13 18:16                         ` Michael Spertus
  0 siblings, 2 replies; 25+ messages in thread
From: Jason Merrill @ 2011-10-09 19:38 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++

On 10/09/2011 08:13 PM, Michael Spertus wrote:
> +dfs_calculate_bases_pre (tree binfo, void *data_)
> +{
> +  (void)data_;

You can use ATTRIBUTE_UNUSED to mark an unused parameter.

I'd still like to see some testcases for the intrinsic, independent of 
the library.

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-09 19:38                       ` Jason Merrill
@ 2011-10-11  0:12                         ` Benjamin Kosnik
  2011-10-13 18:16                         ` Michael Spertus
  1 sibling, 0 replies; 25+ messages in thread
From: Benjamin Kosnik @ 2011-10-11  0:12 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Michael Spertus, Jonathan Wakely, gcc-patches, libstdc++


This is looking pretty good, from the libstdc++ side. This latest round
of gcc hacking fixes the previous testsuite fixes, so once you get
the gcc bits OK'd by Jason you can check in.

> I'd still like to see some testcases for the intrinsic, independent
> of the library.

Seems like some simple test case along the lines of 

gcc/testsuite/g++.dg/ext/is_base_of.C

will suffice. 

-benjamin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: Intrinsics for N2965: Type traits and base classes
  2011-10-09 19:38                       ` Jason Merrill
  2011-10-11  0:12                         ` Benjamin Kosnik
@ 2011-10-13 18:16                         ` Michael Spertus
  2011-10-14 16:23                           ` Jason Merrill
  1 sibling, 1 reply; 25+ messages in thread
From: Michael Spertus @ 2011-10-13 18:16 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++

Addressing Jason's comments:

Index: libstdc++-v3/include/tr2/type_traits
===================================================================
--- libstdc++-v3/include/tr2/type_traits        (revision 0)
+++ libstdc++-v3/include/tr2/type_traits        (revision 0)
@@ -0,0 +1,96 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements> struct typelist;
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      struct first
+      {
+        typedef _First type;
+      };
+
+      struct rest
+      {
+        typedef typelist<_Rest...> type;
+      };
+
+      typedef std::false_type empty;
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename T> struct first : public T::first {};
+  template<typename T> struct rest : public T::rest {};
+  template<typename T> struct empty : public T::empty {};
+
+
+  template<typename T>
+    struct bases
+    {
+         typedef typelist<__bases(T)...> type;
+    };
+
+  template<typename T>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(T)...> type;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c     (revision 178892)
+++ gcc/c-family/c-common.c     (working copy)
@@ -423,6 +423,7 @@
   { "__asm__",         RID_ASM,        0 },
   { "__attribute",     RID_ATTRIBUTE,  0 },
   { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
@@ -433,6 +434,7 @@
   { "__const",         RID_CONST,      0 },
   { "__const__",       RID_CONST,      0 },
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
   { "__extension__",   RID_EXTENSION,  0 },
   { "__func__",                RID_C99_FUNCTION_NAME, 0 },
   { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h     (revision 178892)
+++ gcc/c-family/c-common.h     (working copy)
@@ -129,12 +129,13 @@
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,

   /* C++ extensions */
+  RID_BASES,                  RID_DIRECT_BASES,
   RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
   RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
   RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
   RID_HAS_TRIVIAL_DESTRUCTOR,  RID_HAS_VIRTUAL_DESTRUCTOR,
   RID_IS_ABSTRACT,             RID_IS_BASE_OF,
-  RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
+  RID_IS_CLASS,                RID_IS_CONVERTIBLE_TO,
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_LITERAL_TYPE,         RID_IS_POD,
   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
Index: gcc/testsuite/g++.dg/ext/bases.C
===================================================================
--- gcc/testsuite/g++.dg/ext/bases.C    (revision 0)
+++ gcc/testsuite/g++.dg/ext/bases.C    (revision 0)
@@ -0,0 +1,29 @@
+// { dg-do run }
+#include<typeinfo>
+#include<cassert>
+// A simple typelist
+template<typename... _Elements> struct types {};
+
+// Simple bases implementation
+template<typename T> struct b {
+  typedef types<__bases(T)...> type;
+};
+
+// Simple direct_bases implementation
+template<typename T> struct db {
+  typedef types<__direct_bases(T)...> type;
+};
+struct A {};
+struct C : virtual A {};
+struct D : public C {};
+struct B : D, virtual A {};
+struct E : C, virtual D, B {};
+struct  F : A, B, E {};
+
+int main() {
+  assert(typeid(b<F>::type)
+         == typeid(types<A,C,D,A,C,D,B,C,C,D,B,E>));
+  assert(typeid(db<F>::type) == typeid(types<A,B,E>));
+  assert(typeid(db<int>::type) == typeid(types<>));
+  return 0;
+}
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 178892)
+++ gcc/cp/pt.c (working copy)
@@ -2976,6 +2976,9 @@
         }
       break;

+    case BASES:
+      parameter_pack_p = true;
+      break;
     default:
       /* Not a parameter pack.  */
       break;
@@ -9123,6 +9126,15 @@
       tree arg_pack = NULL_TREE;
       tree orig_arg = NULL_TREE;

+      if (TREE_CODE (parm_pack) == BASES)
+       {
+         if (BASES_DIRECT (parm_pack))
+           return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                        args, complain, in_decl, false));
+         else
+           return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                 args, complain, in_decl, false));
+       }
       if (TREE_CODE (parm_pack) == PARM_DECL)
        {
          if (!cp_unevaluated_operand)
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c  (revision 178892)
+++ gcc/cp/semantics.c  (working copy)
@@ -3407,6 +3407,149 @@
   return underlying_type;
 }

+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    }
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    }
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 178892)
+++ gcc/cp/parser.c     (working copy)
@@ -7295,6 +7295,12 @@
     case RID_UNDERLYING_TYPE:
       kind = CPTK_UNDERLYING_TYPE;
       break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7339,9 +7345,17 @@

   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1, false);
+    case CPTK_DIRECT_BASES:
+      return finish_bases (type1, true);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
 }

 /* Lambdas that appear in variable initializer or default argument scope
@@ -12010,6 +12024,7 @@
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
   parser->non_integral_constant_expression_p = false;
+
   /* Parse the arguments.  */
   do
     {
@@ -12827,7 +12842,6 @@

     case RID_UNDERLYING_TYPE:
       type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
                                      token->location,
@@ -12835,6 +12849,14 @@

       return type;

+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*type_definition_p=*/false);
+      return type;
     default:
       break;
     }
@@ -20534,7 +20556,7 @@
 }

 /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
    return value.  */

 static tree
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def  (revision 178892)
+++ gcc/cp/cp-tree.def  (working copy)
@@ -461,6 +461,10 @@
    UNDERLYING_TYPE_TYPE is the type in question.  */
 DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)

+/* A type designated by one of the bases type traits.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
 /* Used to represent the template information stored by template
    specializations.
    The accessors are:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h    (revision 178892)
+++ gcc/cp/cp-tree.h    (working copy)
@@ -558,6 +558,8 @@

 typedef enum cp_trait_kind
 {
+  CPTK_BASES,
+  CPTK_DIRECT_BASES,
   CPTK_HAS_NOTHROW_ASSIGN,
   CPTK_HAS_NOTHROW_CONSTRUCTOR,
   CPTK_HAS_NOTHROW_COPY,
@@ -3416,6 +3418,13 @@
 #define UNDERLYING_TYPE_TYPE(NODE) \
   (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))

+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+  TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
 /* The expression in question for a DECLTYPE_TYPE.  */
 #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))

@@ -5430,6 +5439,9 @@
                                                  location_t);
 extern tree finish_typeof                      (tree);
 extern tree finish_underlying_type             (tree);
+extern tree calculate_bases                    (tree);
+extern tree finish_bases                       (tree, bool);
+extern tree calculate_direct_bases             (tree);
 extern tree finish_offsetof                    (tree);
 extern void finish_decl_cleanup                        (tree, tree);
 extern void finish_eh_cleanup                  (tree);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-13 18:16                         ` Michael Spertus
@ 2011-10-14 16:23                           ` Jason Merrill
  2011-10-14 20:23                             ` Michael Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Jason Merrill @ 2011-10-14 16:23 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++

On 10/13/2011 01:35 PM, Michael Spertus wrote:
> +int main() {
> +  assert(typeid(b<F>::type)
> +         == typeid(types<A,C,D,A,C,D,B,C,C,D,B,E>));
> +  assert(typeid(db<F>::type) == typeid(types<A,B,E>));
> +  assert(typeid(db<int>::type) == typeid(types<>));
> +  return 0;
> +}

Let's make this a compile-time test using something like

template <class,class> struct assert_same_type;
template <class T> struct assert_same_type<T,T> {};

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: Intrinsics for N2965: Type traits and base classes
  2011-10-14 16:23                           ` Jason Merrill
@ 2011-10-14 20:23                             ` Michael Spertus
  2011-10-14 20:28                               ` Jason Merrill
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Spertus @ 2011-10-14 20:23 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++,
	Michael Spertus

Redo test to run at compile-time per Jason's suggestion

Index: libstdc++-v3/include/tr2/type_traits
===================================================================
--- libstdc++-v3/include/tr2/type_traits        (revision 0)
+++ libstdc++-v3/include/tr2/type_traits        (revision 0)
@@ -0,0 +1,96 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements> struct typelist;
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      struct first
+      {
+        typedef _First type;
+      };
+
+      struct rest
+      {
+        typedef typelist<_Rest...> type;
+      };
+
+      typedef std::false_type empty;
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename T> struct first : public T::first {};
+  template<typename T> struct rest : public T::rest {};
+  template<typename T> struct empty : public T::empty {};
+
+
+  template<typename T>
+    struct bases
+    {
+         typedef typelist<__bases(T)...> type;
+    };
+
+  template<typename T>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(T)...> type;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c     (revision 178892)
+++ gcc/c-family/c-common.c     (working copy)
@@ -423,6 +423,7 @@
   { "__asm__",         RID_ASM,        0 },
   { "__attribute",     RID_ATTRIBUTE,  0 },
   { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
@@ -433,6 +434,7 @@
   { "__const",         RID_CONST,      0 },
   { "__const__",       RID_CONST,      0 },
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
   { "__extension__",   RID_EXTENSION,  0 },
   { "__func__",                RID_C99_FUNCTION_NAME, 0 },
   { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h     (revision 178892)
+++ gcc/c-family/c-common.h     (working copy)
@@ -129,12 +129,13 @@
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,

   /* C++ extensions */
+  RID_BASES,                  RID_DIRECT_BASES,
   RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
   RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
   RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
   RID_HAS_TRIVIAL_DESTRUCTOR,  RID_HAS_VIRTUAL_DESTRUCTOR,
   RID_IS_ABSTRACT,             RID_IS_BASE_OF,
-  RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
+  RID_IS_CLASS,                RID_IS_CONVERTIBLE_TO,
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_LITERAL_TYPE,         RID_IS_POD,
   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
Index: gcc/testsuite/g++.dg/ext/bases.C
===================================================================
--- gcc/testsuite/g++.dg/ext/bases.C    (revision 0)
+++ gcc/testsuite/g++.dg/ext/bases.C    (revision 0)
@@ -0,0 +1,32 @@
+// { dg-do run }
+#include<typeinfo>
+#include<cassert>
+// A simple typelist
+template<typename... _Elements> struct types {};
+
+// Simple bases implementation
+template<typename T> struct b {
+  typedef types<__bases(T)...> type;
+};
+
+// Simple direct_bases implementation
+template<typename T> struct db {
+  typedef types<__direct_bases(T)...> type;
+};
+
+template <class,class> struct assert_same_type;
+template <class T> struct assert_same_type<T,T> {};
+
+struct A {};
+struct C : virtual A {};
+struct D : public C {};
+struct B : D, virtual A {};
+struct E : C, virtual D, B {};
+struct  F : A, B, E {};
+
+int main() {
+  assert_same_type<b<F>::type, types<A,C,D,A,C,D,B,C,C,D,B,E>>();
+  assert_same_type<db<F>::type, types<A,B,E>>();
+  assert_same_type<db<int>::type, types<>>();
+  return 0;
+}
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 178892)
+++ gcc/cp/pt.c (working copy)
@@ -2976,6 +2976,9 @@
         }
       break;

+    case BASES:
+      parameter_pack_p = true;
+      break;
     default:
       /* Not a parameter pack.  */
       break;
@@ -9123,6 +9126,15 @@
       tree arg_pack = NULL_TREE;
       tree orig_arg = NULL_TREE;

+      if (TREE_CODE (parm_pack) == BASES)
+       {
+         if (BASES_DIRECT (parm_pack))
+           return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                        args, complain, in_decl, false));
+         else
+           return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                 args, complain, in_decl, false));
+       }
       if (TREE_CODE (parm_pack) == PARM_DECL)
        {
          if (!cp_unevaluated_operand)
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c  (revision 178892)
+++ gcc/cp/semantics.c  (working copy)
@@ -3407,6 +3407,149 @@
   return underlying_type;
 }

+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    }
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    }
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 178892)
+++ gcc/cp/parser.c     (working copy)
@@ -7295,6 +7295,12 @@
     case RID_UNDERLYING_TYPE:
       kind = CPTK_UNDERLYING_TYPE;
       break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7339,9 +7345,17 @@

   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1, false);
+    case CPTK_DIRECT_BASES:
+      return finish_bases (type1, true);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
 }

 /* Lambdas that appear in variable initializer or default argument scope
@@ -12010,6 +12024,7 @@
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
   parser->non_integral_constant_expression_p = false;
+
   /* Parse the arguments.  */
   do
     {
@@ -12827,7 +12842,6 @@

     case RID_UNDERLYING_TYPE:
       type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
                                      token->location,
@@ -12835,6 +12849,14 @@

       return type;

+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*type_definition_p=*/false);
+      return type;
     default:
       break;
     }
@@ -20534,7 +20556,7 @@
 }

 /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
    return value.  */

 static tree
Index: gcc/cp/cp-tree.def
===================================================================
--- gcc/cp/cp-tree.def  (revision 178892)
+++ gcc/cp/cp-tree.def  (working copy)
@@ -461,6 +461,10 @@
    UNDERLYING_TYPE_TYPE is the type in question.  */
 DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)

+/* A type designated by one of the bases type traits.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
 /* Used to represent the template information stored by template
    specializations.
    The accessors are:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h    (revision 178892)
+++ gcc/cp/cp-tree.h    (working copy)
@@ -558,6 +558,8 @@

 typedef enum cp_trait_kind
 {
+  CPTK_BASES,
+  CPTK_DIRECT_BASES,
   CPTK_HAS_NOTHROW_ASSIGN,
   CPTK_HAS_NOTHROW_CONSTRUCTOR,
   CPTK_HAS_NOTHROW_COPY,
@@ -3416,6 +3418,13 @@
 #define UNDERLYING_TYPE_TYPE(NODE) \
   (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))

+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+  TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
 /* The expression in question for a DECLTYPE_TYPE.  */
 #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))

@@ -5430,6 +5439,9 @@
                                                  location_t);
 extern tree finish_typeof                      (tree);
 extern tree finish_underlying_type             (tree);
+extern tree calculate_bases                    (tree);
+extern tree finish_bases                       (tree, bool);
+extern tree calculate_direct_bases             (tree);
 extern tree finish_offsetof                    (tree);
 extern void finish_decl_cleanup                        (tree, tree);
 extern void finish_eh_cleanup                  (tree);

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-14 20:23                             ` Michael Spertus
@ 2011-10-14 20:28                               ` Jason Merrill
  2011-10-14 20:36                                 ` Michael Spertus
  0 siblings, 1 reply; 25+ messages in thread
From: Jason Merrill @ 2011-10-14 20:28 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++

Looks good, thanks.  I'll let Benjamin check this in.

Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* RE: Intrinsics for N2965: Type traits and base classes
  2011-10-14 20:28                               ` Jason Merrill
@ 2011-10-14 20:36                                 ` Michael Spertus
  2011-10-18  7:19                                   ` Benjamin Kosnik
  0 siblings, 1 reply; 25+ messages in thread
From: Michael Spertus @ 2011-10-14 20:36 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Benjamin Kosnik, Jonathan Wakely, gcc-patches, libstdc++,
	Michael Spertus

:)

> -----Original Message-----
> From: Jason Merrill [mailto:jason@redhat.com]
> Sent: Friday, October 14, 2011 2:41 PM
> To: Michael Spertus
> Cc: Benjamin Kosnik; Jonathan Wakely; gcc-patches@gcc.gnu.org;
> libstdc++@gcc.gnu.org
> Subject: Re: Intrinsics for N2965: Type traits and base classes
> 
> Looks good, thanks.  I'll let Benjamin check this in.
> 
> Jason

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-14 20:36                                 ` Michael Spertus
@ 2011-10-18  7:19                                   ` Benjamin Kosnik
  0 siblings, 0 replies; 25+ messages in thread
From: Benjamin Kosnik @ 2011-10-18  7:19 UTC (permalink / raw)
  To: Michael Spertus; +Cc: Jason Merrill, Jonathan Wakely, gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 106 bytes --]


This is now in, thanks everybody for playing! Attached is the final
diff.

tested x86_64/linux

-benjamin

[-- Attachment #2: 20111017-1.patch --]
[-- Type: text/x-patch, Size: 35609 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ddc5149..6c73404 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-17  Michael Spertus  <mike_spertus@symantec.com>
+
+	* gcc/c-family/c-common.c (c_common_reswords): Add __bases,
+	__direct_bases.
+	* gcc/c-family/c-common.h: Add RID_BASES and RID_DIRECT_BASES.
+
 2011-10-17  Simon Baldwin  <simonb@google.com>
 	    Ian Lance Taylor  <iant@google.com>
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0aa0fef..9d20d80 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -423,6 +423,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__asm__",		RID_ASM,	0 },
   { "__attribute",	RID_ATTRIBUTE,	0 },
   { "__attribute__",	RID_ATTRIBUTE,	0 },
+  { "__bases",          RID_BASES, D_CXXONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
   { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, D_CONLY },
@@ -434,6 +435,7 @@ const struct c_common_resword c_common_reswords[] =
   { "__const",		RID_CONST,	0 },
   { "__const__",	RID_CONST,	0 },
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__direct_bases",   RID_DIRECT_BASES, D_CXXONLY },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME, 0 },
   { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 8996eef..9818c9c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -128,12 +128,13 @@ enum rid
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
   /* C++ extensions */
+  RID_BASES,                  RID_DIRECT_BASES,
   RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
   RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
   RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
   RID_HAS_TRIVIAL_DESTRUCTOR,  RID_HAS_VIRTUAL_DESTRUCTOR,
   RID_IS_ABSTRACT,             RID_IS_BASE_OF,
-  RID_IS_CONVERTIBLE_TO,       RID_IS_CLASS,
+  RID_IS_CLASS,                RID_IS_CONVERTIBLE_TO,
   RID_IS_EMPTY,                RID_IS_ENUM,
   RID_IS_LITERAL_TYPE,         RID_IS_POD,
   RID_IS_POLYMORPHIC,          RID_IS_STD_LAYOUT,
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ed7d832..2a4bdbb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2011-10-17  Michael Spertus  <mike_spertus@symantec.com>
+
+	* cp-tree.def: Add BASES as a new tree code.
+	* cp-tree.h (enum cp_trait_kind): Add CPTK_BASES, CPTK_DIRECT_BASES.
+	(BASES_TYPE, BASES_DIRECT): Define.
+	(calculate_bases, finish_bases, calculate_direct_bases): Declare.
+	* parser.c (cp_parser_trait_expr, cp_parser_template_argument_list,
+	(cp_parser_simple_type_specifier, cp_parser_save_nsdmi): Use them.
+	* pt.c (find_parameter_packs_r, tsubst_pack_expansion): Likewise.
+	* semantics.c (calculate_bases, finish_bases, calculate_direct_bases,
+	dfs_calculate_bases_pre, dfs_calculate_bases_post,
+	calculate_bases_helper): Define.
+
 2011-10-17  Jason Merrill  <jason@redhat.com>
 
 	PR c++/50736
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index be29870..4eec9f9 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -462,6 +462,10 @@ DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
    UNDERLYING_TYPE_TYPE is the type in question.  */
 DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)
 
+/* A type designated by one of the bases type traits.
+   BASES_TYPE is the type in question.  */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
 /* Used to represent the template information stored by template
    specializations.
    The accessors are:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 88f7fbd..bda18d9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -564,6 +564,8 @@ struct GTY (()) tree_argument_pack_select {
 
 typedef enum cp_trait_kind
 {
+  CPTK_BASES,
+  CPTK_DIRECT_BASES,
   CPTK_HAS_NOTHROW_ASSIGN,
   CPTK_HAS_NOTHROW_CONSTRUCTOR,
   CPTK_HAS_NOTHROW_COPY,
@@ -3433,6 +3435,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define UNDERLYING_TYPE_TYPE(NODE) \
   (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
 
+/* The type in question for BASES.  */
+#define BASES_TYPE(NODE) \
+  (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+  TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
 /* The expression in question for a DECLTYPE_TYPE.  */
 #define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
 
@@ -5462,6 +5471,9 @@ extern tree finish_id_expression		(tree, tree, tree,
                                                  location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_underlying_type	        (tree);
+extern tree calculate_bases                     (tree);
+extern tree finish_bases                        (tree, bool);
+extern tree calculate_direct_bases              (tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
 extern void finish_eh_cleanup			(tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bf362f2..c0e9001 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7304,6 +7304,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_UNDERLYING_TYPE:
       kind = CPTK_UNDERLYING_TYPE;
       break;
+    case RID_BASES:
+      kind = CPTK_BASES;
+      break;
+    case RID_DIRECT_BASES:
+      kind = CPTK_DIRECT_BASES;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7348,9 +7354,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return kind != CPTK_UNDERLYING_TYPE
-    ? finish_trait_expr (kind, type1, type2)
-    : finish_underlying_type (type1);
+  switch(kind)
+    {
+    case CPTK_UNDERLYING_TYPE:
+      return finish_underlying_type (type1);
+    case CPTK_BASES:
+      return finish_bases (type1, false);
+    case CPTK_DIRECT_BASES:
+      return finish_bases (type1, true);
+    default:
+      return finish_trait_expr (kind, type1, type2);
+    }
 }
 
 /* Lambdas that appear in variable initializer or default argument scope
@@ -12040,6 +12054,7 @@ cp_parser_template_argument_list (cp_parser* parser)
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
   parser->non_integral_constant_expression_p = false;
+
   /* Parse the arguments.  */
   do
     {
@@ -12857,7 +12872,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
     case RID_UNDERLYING_TYPE:
       type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
 				      token->location,
@@ -12865,6 +12879,14 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       return type;
 
+    case RID_BASES:
+    case RID_DIRECT_BASES:
+      type = cp_parser_trait_expr (parser, token->keyword);
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*type_definition_p=*/false);
+      return type;
     default:
       break;
     }
@@ -20652,7 +20674,7 @@ cp_parser_save_nsdmi (cp_parser* parser)
 
 
 /* Parse a template-argument-list, as well as the trailing ">" (but
-   not the opening ">").  See cp_parser_template_argument_list for the
+   not the opening "<").  See cp_parser_template_argument_list for the
    return value.  */
 
 static tree
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bbe1139..6fc60d5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2980,6 +2980,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
         }
       break;
 
+    case BASES:
+      parameter_pack_p = true;
+      break;
     default:
       /* Not a parameter pack.  */
       break;
@@ -9127,6 +9130,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       tree arg_pack = NULL_TREE;
       tree orig_arg = NULL_TREE;
 
+      if (TREE_CODE (parm_pack) == BASES)
+       {
+         if (BASES_DIRECT (parm_pack))
+           return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                        args, complain, in_decl, false));
+         else
+           return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+                                                 args, complain, in_decl, false));
+       }
       if (TREE_CODE (parm_pack) == PARM_DECL)
 	{
 	  if (!cp_unevaluated_operand)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1efe579..3e847fa 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3394,6 +3394,149 @@ finish_underlying_type (tree type)
   return underlying_type;
 }
 
+/* Implement the __direct_bases keyword: Return the direct base classes
+   of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  VEC(tree, none) *base_binfos;
+  tree binfo;
+  unsigned i;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+  /* Virtual bases are initialized first */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+  /* Now non-virtuals */
+  for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+    {
+      if (!BINFO_VIRTUAL_P (binfo))
+       {
+         VEC_safe_push (tree, gc, vector, binfo);
+       }
+    }
+
+
+  bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+  for (i = 0; i < VEC_length (tree, vector); ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+    }
+  return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+   of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+  /* Don't walk bases of virtual bases */
+  return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+  VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+  if (!BINFO_VIRTUAL_P (binfo))
+    {
+      VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+    }
+  return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+
+  /* Now add non-virtual base classes in order of construction */
+  dfs_walk_all (TYPE_BINFO (type),
+                dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+  return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+  VEC(tree, gc) *vector = make_tree_vector();
+  tree bases_vec = NULL_TREE;
+  unsigned i;
+  VEC(tree, gc) *vbases;
+  VEC(tree, gc) *nonvbases;
+  tree binfo;
+
+  complete_type (type);
+
+  if (!NON_UNION_CLASS_TYPE_P (type))
+    return make_tree_vec (0);
+
+  /* First go through virtual base classes */
+  for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+       VEC_iterate (tree, vbases, i, binfo); i++)
+    {
+      VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+      VEC_safe_splice (tree, gc, vector, vbase_bases);
+      release_tree_vector (vbase_bases);
+    }
+
+  /* Now for the non-virtual bases */
+  nonvbases = calculate_bases_helper (type);
+  VEC_safe_splice (tree, gc, vector, nonvbases);
+  release_tree_vector (nonvbases);
+
+  /* Last element is entire class, so don't copy */
+  bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+  for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+    {
+      TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+    }
+  release_tree_vector (vector);
+  return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+  tree bases = NULL_TREE;
+
+  if (!processing_template_decl)
+    {
+      /* Parameter packs can only be used in templates */
+      error ("Parameter pack __bases only valid in template declaration");
+      return error_mark_node;
+    }
+
+  bases = cxx_make_type (BASES);
+  BASES_TYPE (bases) = type;
+  BASES_DIRECT (bases) = direct;
+  SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+  return bases;
+}
+
 /* Perform C++-specific checks for __builtin_offsetof before calling
    fold_offsetof.  */
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 500c142..39efdcc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-10-17  Michael Spertus  <mike_spertus@symantec.com>
+
+	* g++.dg/ext/bases.C: New test.
+
 2011-10-17  David S. Miller  <davem@davemloft.net>
 
 	* gcc.target/sparc/fand.c: Remove __LP64__ ifdefs and expect
diff --git a/gcc/testsuite/g++.dg/ext/bases.C b/gcc/testsuite/g++.dg/ext/bases.C
new file mode 100644
index 0000000..0582f72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/bases.C
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++0x -w" }
+// { dg-do run }
+
+#include<typeinfo>
+#include<cassert>
+
+// A simple typelist
+template<typename... _Elements> struct types {};
+
+// Simple bases implementation
+template<typename T> struct b {
+  typedef types<__bases(T)...> type;
+};
+
+// Simple direct_bases implementation
+template<typename T> struct db {
+  typedef types<__direct_bases(T)...> type;
+};
+
+template <class,class> struct assert_same_type;
+template <class T> struct assert_same_type<T,T> {};
+
+struct A {};
+struct C : virtual A {};
+struct D : public C {};
+struct B : D, virtual A {};
+struct E : C, virtual D, B {};
+struct  F : A, B, E {};
+
+int main() {
+  assert_same_type<b<F>::type, types<A,C,D,A,C,D,B,C,C,D,B,E>>();
+  assert_same_type<db<F>::type, types<A,B,E>>();
+  assert_same_type<db<int>::type, types<>>();
+  return 0;
+}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index e8a621a..3baca8c 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,23 @@
+2011-10-17  Michael Spertus  <mike_spertus@symantec.com>
+
+	* include/tr2/type_traits (bases, direct_bases, typelist): New.
+
+2011-10-17  Benjamin Kosnik  <bkoz@redhat.com>
+
+	* libstdc++-v3/include/Makefile.am: Add tr2 directory and includes.
+	* libstdc++-v3/include/Makefile.in: Regenerate.
+
+	* scripts/create_testsuite_files: Search tr2 directory.
+	* testsuite/libstdc++-dg/conformance.exp: Same.
+
+	* testsuite/tr2/bases/requirements/explicit_instantiation.cc: New.
+	* testsuite/tr2/bases/requirements/typedefs.cc: New.
+	* testsuite/tr2/bases/value.cc: New.
+	* testsuite/tr2/direct_bases/requirements/
+	explicit_instantiation.cc: New.
+	* testsuite/tr2/direct_bases/requirements/typedefs.cc: New.
+	* testsuite/tr2/direct_bases/value.cc: New.
+
 2011-10-17  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
 	PR bootstrap/50715
@@ -194,7 +214,7 @@
 	* testsuite/23_containers/deque/modifiers/erase/3.cc: Adjust.
 
 2011-09-25  Benjamin Kosnik  <bkoz@redhat.com>
-            Jonathan Wakely  <jwakely.gcc@gmail.com>
+	    Jonathan Wakely  <jwakely.gcc@gmail.com>
 
 	PR libstdc++/48698
 	* acinclude.m4 (GLIBCXX_ENABLE_SYMVERS): Set libtool_VERSION here.
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 4016882..9fdaa8d 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -604,6 +604,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -887,7 +892,7 @@ endif
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1002,6 +1007,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1245,6 +1255,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1291,7 +1304,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 58dbfc4..5ad5932 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -854,6 +854,11 @@ tr1_headers = \
 	${tr1_srcdir}/wchar.h \
 	${tr1_srcdir}/wctype.h
 
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+	${tr2_srcdir}/type_traits
+
 decimal_srcdir = ${glibcxx_srcdir}/include/decimal
 decimal_builddir = ./decimal
 decimal_headers = \
@@ -1125,7 +1130,7 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS)
 # CLEANFILES and all-local are kept up-to-date.
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
-	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
 	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
 	stamp-host 
 
@@ -1402,6 +1407,11 @@ stamp-tr1: ${tr1_headers}
 	@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-tr1
 
+stamp-tr2: ${tr2_headers}
+	@-mkdir -p ${tr2_builddir}
+	@-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-tr2
+
 stamp-decimal: ${decimal_headers}
 	@-mkdir -p ${decimal_builddir}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1630,6 +1640,9 @@ install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
 	for file in ${tr1_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+	for file in ${tr2_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1673,7 +1686,7 @@ clean-local:
 # developer tries to create them via make in the include build
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
 	   $(decimal_headers) $(ext_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
new file mode 100644
index 0000000..e860ad7
--- /dev/null
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -0,0 +1,102 @@
+// TR2 type_traits -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ *  This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup metaprogramming Type Traits
+   * @ingroup utilities
+   *
+   * Compile time type transformation and information.
+   * @{
+   */
+
+  template<typename... _Elements>
+    struct typelist;
+
+  template<>
+    struct typelist<>
+    {
+      typedef std::true_type 			empty;
+    };
+
+  template<typename _First, typename... _Rest>
+    struct typelist<_First, _Rest...>
+    {
+      typedef std::false_type 			empty;
+
+      struct first
+      {
+	typedef _First 				type;
+      };
+
+      struct rest
+      {
+	typedef typelist<_Rest...> 		type;
+      };
+    };
+
+  // Sequence abstraction metafunctions default to looking in the type
+  template<typename _Tp>
+    struct first : public _Tp::first { };
+
+  template<typename _Tp>
+    struct rest : public _Tp::rest { };
+
+  template<typename _Tp>
+    struct empty : public _Tp::empty { };
+
+
+  template<typename _Tp>
+    struct bases
+    {
+      typedef typelist<__bases(_Tp)...> 	type;
+    };
+
+  template<typename _Tp>
+    struct direct_bases
+    {
+      typedef typelist<__direct_bases(_Tp)...> 	type;
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index f4a0bcd..a427eef 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -32,7 +32,7 @@ cd $srcdir
 # This is the ugly version of "everything but the current directory".  It's
 # what has to happen when find(1) doesn't support -mindepth, or -xtype.
 dlist=`echo [0-9][0-9]*`
-dlist="$dlist abi backward ext performance tr1 decimal"
+dlist="$dlist abi backward ext performance tr1 tr2 decimal"
 find $dlist "(" -type f -o -type l ")" -name "*.cc" -print > $tmp.01
 find $dlist "(" -type f -o -type l ")" -name "*.c" -print > $tmp.02
 cat  $tmp.01 $tmp.02 | sort > $tmp.1
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 8642eb7..19fa0e2 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -58,6 +58,7 @@ if {[info exists tests_file] && [file exists $tests_file]} {
     lappend subdirs "$srcdir/ext"
     lappend subdirs "$srcdir/performance"
     lappend subdirs "$srcdir/tr1"
+    lappend subdirs "$srcdir/tr2"
     lappend subdirs "$srcdir/decimal"
     verbose "subdirs are $subdirs"
 
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..ddd6d6f
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+  namespace tr2
+  {
+    typedef short test_type;
+    template struct bases<test_type>;
+  }
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
new file mode 100644
index 0000000..a62acff
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::tr2::bases<int>            test_type;
+  typedef test_type::type            value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/value.cc b/libstdc++-v3/testsuite/tr2/bases/value.cc
new file mode 100644
index 0000000..415e974
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/value.cc
@@ -0,0 +1,97 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+  bool test __attribute__((unused)) = true;
+
+  // 1
+  {
+    typedef std::tr2::bases<A>::type tl;
+    static_assert(tl::empty::value, "error");
+  }
+
+  // 2
+  {
+    typedef std::tr2::bases<B1>::type tl1;
+    typedef std::tr2::bases<B2>::type tl2;
+
+    // Sanity check w/ runtime.
+    bool eq = typeid(tl1) == typeid(tl2);
+    if (!eq)
+      throw std::logic_error("typelist not equal");
+
+    // Sanity check.
+    static_assert(tl1::empty::value != std::true_type::value, "!empty");
+    static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+    typedef tl1::first::type		tl1_first;
+    typedef tl1::rest::type		tl1_rest;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl2_rest;
+
+    eq = typeid(tl1_first) == typeid(tl2_first);
+    if (!eq)
+      throw std::logic_error("base not equal");
+
+    static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+    static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+  }
+
+  // 3
+  {
+    typedef std::tr2::bases<C>::type tl;
+
+    // Sanity check.
+    static_assert(tl::empty::value != std::true_type::value, "!empty");
+  
+    typedef tl::first::type		tl1_first;
+    typedef tl::rest::type		tl2;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl3;
+    typedef tl3::first::type		tl3_first;
+    typedef tl3::rest::type		tl4;
+
+    bool eq = typeid(tl1_first) == typeid(tl2_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    eq = typeid(tl2_first) == typeid(tl3_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    static_assert(tl4::empty::value == std::true_type::value, "empty");
+  }
+
+}
+
+int main()
+{
+  test();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
new file mode 100644
index 0000000..d7fb96a
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+  namespace tr2
+  {
+    typedef short test_type;
+    template struct direct_bases<test_type>;
+  }
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
new file mode 100644
index 0000000..7d219ea
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+  // Check for required typedefs
+  typedef std::tr2::direct_bases<int>            test_type;
+  typedef test_type::type            value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/value.cc b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
new file mode 100644
index 0000000..81d0269
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+  bool test __attribute__((unused)) = true;
+
+  // 1
+  {
+    typedef std::tr2::direct_bases<A>::type tl;
+    static_assert(tl::empty::value, "error");
+  }
+
+  // 2
+  {
+    typedef std::tr2::direct_bases<B1>::type tl1;
+    typedef std::tr2::direct_bases<B2>::type tl2;
+
+    // Sanity check w/ runtime.
+    bool eq = typeid(tl1) == typeid(tl2);
+    if (!eq)
+      throw std::logic_error("typelist not equal");
+
+    // Sanity check.
+    static_assert(tl1::empty::value != std::true_type::value, "!empty");
+    static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+    typedef tl1::first::type		tl1_first;
+    typedef tl1::rest::type		tl1_rest;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl2_rest;
+
+    eq = typeid(tl1_first) == typeid(tl2_first);
+    if (!eq)
+      throw std::logic_error("base not equal");
+
+    static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+    static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+  }
+
+  // 3
+  {
+    typedef std::tr2::direct_bases<C>::type tl;
+
+    // Sanity check.
+    static_assert(tl::empty::value != std::true_type::value, "!empty");
+  
+    typedef tl::first::type		tl1_first;
+    typedef tl::rest::type		tl2;
+    typedef tl2::first::type		tl2_first;
+    typedef tl2::rest::type		tl3;
+
+    bool eq = typeid(tl1_first) == typeid(tl2_first);
+    if (eq)
+      throw std::logic_error("bases are not equal");
+
+    static_assert(tl3::empty::value == std::true_type::value, "empty");
+  }
+
+}
+
+int main()
+{
+  test();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-09-26 16:24 ` Intrinsics for N2965: Type traits and base classes Mike Spertus
  2011-09-26 18:40   ` Jason Merrill
  2011-09-28  6:43   ` Benjamin Kosnik
@ 2011-10-18  8:23   ` Eric Botcazou
  2011-10-19 22:48     ` Benjamin Kosnik
  2 siblings, 1 reply; 25+ messages in thread
From: Eric Botcazou @ 2011-10-18  8:23 UTC (permalink / raw)
  To: Mike Spertus; +Cc: gcc-patches, Benjamin Kosnik, Jason Merrill

> This patch consists intrinsics to properly create the bases and
> direct_bases of a class in the correct order (including multiple nested
> ambiguous virtual and non-virtual classes) for N2965
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2965.html).
> This allows you to create type traits for giving the base classes of the
> class:

Please post a ChangeLog entry with a patch.  Someone added one for you:

2011-10-17  Michael Spertus  <mike_spertus@symantec.com>

	* gcc/c-family/c-common.c (c_common_reswords): Add __bases,
	__direct_bases.
	* gcc/c-family/c-common.h: Add RID_BASES and RID_DIRECT_BASES.

but it is in the wrong file (c-family has its own ChangeLog) and shouldn't 
contain the gcc/c-family prefix (paths are relative to the directory).

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Intrinsics for N2965: Type traits and base classes
  2011-10-18  8:23   ` Eric Botcazou
@ 2011-10-19 22:48     ` Benjamin Kosnik
  0 siblings, 0 replies; 25+ messages in thread
From: Benjamin Kosnik @ 2011-10-19 22:48 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Mike Spertus, gcc-patches, Jason Merrill


> Please post a ChangeLog entry with a patch.  Someone added one for
> you:
> 
> 2011-10-17  Michael Spertus  <mike_spertus@symantec.com>
> 
> 	* gcc/c-family/c-common.c (c_common_reswords): Add __bases,
> 	__direct_bases.
> 	* gcc/c-family/c-common.h: Add RID_BASES and RID_DIRECT_BASES.
> 
> but it is in the wrong file (c-family has its own ChangeLog) and
> shouldn't contain the gcc/c-family prefix (paths are relative to the
> directory).

Sorry Eric, this was my fault. I see that Paolo has already fixed this
up. 

Thanks Paolo!

best,
benjamin

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2011-10-19 22:22 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20110913154324.4be22faf@shotwell>
2011-09-26 16:24 ` Intrinsics for N2965: Type traits and base classes Mike Spertus
2011-09-26 18:40   ` Jason Merrill
2011-09-28  6:43   ` Benjamin Kosnik
2011-09-28  6:49     ` Benjamin Kosnik
2011-09-28  7:08     ` Michael Spertus
2011-09-28  9:33       ` Jonathan Wakely
2011-09-28 12:49         ` Mike Spertus
2011-09-28 13:57           ` Mike Spertus
2011-09-29 19:42             ` Benjamin Kosnik
2011-10-03  1:55               ` Michael Spertus
2011-10-03 13:08                 ` Jason Merrill
2011-10-03 15:51                 ` Jonathan Wakely
2011-10-04  4:41                 ` Benjamin Kosnik
2011-10-04  5:04                   ` Benjamin Kosnik
2011-10-09 19:31                     ` Michael Spertus
2011-10-09 19:38                       ` Jason Merrill
2011-10-11  0:12                         ` Benjamin Kosnik
2011-10-13 18:16                         ` Michael Spertus
2011-10-14 16:23                           ` Jason Merrill
2011-10-14 20:23                             ` Michael Spertus
2011-10-14 20:28                               ` Jason Merrill
2011-10-14 20:36                                 ` Michael Spertus
2011-10-18  7:19                                   ` Benjamin Kosnik
2011-10-18  8:23   ` Eric Botcazou
2011-10-19 22:48     ` Benjamin Kosnik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).