Intrinsics for N2965: Type traits and base classes

Michael Spertus mike_spertus@symantec.com
Mon Oct 3 01:55:00 GMT 2011


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);



More information about the Libstdc++ mailing list