This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC / Patch] C++/26099 or front-end support to type traits


Hi,

Time ago I assigned to myself this PR, which has of course very important implications for libstdc++, both from the performance point of view and in order to implement the type traits facilities as mandated in C++0x.

Over the last weeks I tried various options for the general infrastructure and before proceeding with implementing the semantics (part at least seems easy) I wanted to check with you all that the infrastructure is decent and consistent with the practice of front-end. I'm attaching below the patch, together with a set of simple testcases, it seems rather self-explanatory to me and, well, not too ugly, what do you think?

Thanks in advance for your (constructive ;) comments,
Paolo.

///////////////////
Index: cp/cp-tree.def
===================================================================
--- cp/cp-tree.def	(revision 122814)
+++ cp/cp-tree.def	(working copy)
@@ -422,6 +422,12 @@
    index is a machine integer.  */
 DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
 
+/** C++ extensions. */
+
+/* Represents a trait expression during template expansion. Operand 0
+   is the kind of trait.  Operand 1 the queried type.  */
+DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_expression, 2)
+
 /*
 Local variables:
 mode:c
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 122814)
+++ cp/cp-tree.h	(working copy)
@@ -481,6 +481,20 @@
   int index;
 };
 
+/* The different kinds of traits that we encounter.  */
+
+typedef enum cp_trait_kind
+{
+  CP_HAS_TRIVIAL_DESTRUCTOR,
+  CP_IS_CLASS,
+  CP_IS_EMPTY,
+  CP_IS_POD,
+  CP_IS_UNION
+} cp_trait_kind;
+
+#define TRAIT_EXPR_KIND(NODE) \
+  ((cp_trait_kind)TREE_INT_CST_LOW (TREE_OPERAND (TRAIT_EXPR_CHECK (NODE), 0)))
+
 enum cp_tree_node_structure_enum {
   TS_CP_GENERIC,
   TS_CP_IDENTIFIER,
@@ -4553,6 +4567,7 @@
 extern tree baselink_for_fns                    (tree);
 extern void finish_static_assert                (tree, tree, location_t,
                                                  bool);
+extern tree finish_trait_expr			(enum cp_trait_kind, tree);
 
 /* in tree.c */
 extern void lang_check_failed			(const char *, int,
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 122814)
+++ cp/pt.c	(working copy)
@@ -10667,6 +10667,10 @@
     case OFFSETOF_EXPR:
       return finish_offsetof (RECUR (TREE_OPERAND (t, 0)));
 
+    case TRAIT_EXPR:
+      return finish_trait_expr (TRAIT_EXPR_KIND (t),
+				RECUR (TREE_OPERAND (t, 1)));
+
     case STMT_EXPR:
       {
 	tree old_stmt_expr = cur_stmt_expr;
@@ -14852,6 +14856,9 @@
         return false;
       }
 
+    case TRAIT_EXPR:
+      return dependent_type_p (TREE_OPERAND (expression, 1));
+
     default:
       /* A constant expression is value-dependent if any subexpression is
 	 value-dependent.  */
@@ -14915,6 +14922,7 @@
   if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
       || TREE_CODE (expression) == SIZEOF_EXPR
       || TREE_CODE (expression) == ALIGNOF_EXPR
+      || TREE_CODE (expression) == TRAIT_EXPR
       || TREE_CODE (expression) == TYPEID_EXPR
       || TREE_CODE (expression) == DELETE_EXPR
       || TREE_CODE (expression) == VEC_DELETE_EXPR
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 122814)
+++ cp/semantics.c	(working copy)
@@ -4000,4 +4000,56 @@
     }
 }
 
+/* Process a trait expression.  */
+
+tree
+finish_trait_expr (cp_trait_kind kind, tree type)
+{
+  bool value = false;
+  enum tree_code type_code;
+
+  gcc_assert (kind == CP_HAS_TRIVIAL_DESTRUCTOR
+	      || kind == CP_IS_CLASS
+	      || kind == CP_IS_EMPTY
+	      || kind == CP_IS_POD
+	      || kind == CP_IS_UNION);
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  if (processing_template_decl)
+    return build2 (TRAIT_EXPR, boolean_type_node,
+		   build_int_cst (NULL_TREE, kind), type);
+
+  type_code = TREE_CODE (type);
+
+  switch (kind)
+    {
+    case CP_HAS_TRIVIAL_DESTRUCTOR:
+      if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+	value = true;
+      break;
+    case CP_IS_CLASS:
+      if (CLASS_TYPE_P (type) && type_code != UNION_TYPE)
+	value = true;
+      break;
+    case CP_IS_EMPTY:
+      if (CLASS_TYPE_P (type) && CLASSTYPE_EMPTY_P (type))
+	value = true;
+      break;
+    case CP_IS_POD:
+      if (pod_type_p (type))
+	value = true;
+      break;
+    case CP_IS_UNION:
+      if (type_code == UNION_TYPE)
+	value = true;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return value ? boolean_true_node : boolean_false_node;
+}
+
 #include "gt-cp-semantics.h"
Index: cp/lex.c
===================================================================
--- cp/lex.c	(revision 122814)
+++ cp/lex.c	(working copy)
@@ -199,6 +199,11 @@
   { "__const__",	RID_CONST,	0 },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME,	0 },
+  { "__gnu_has_trivial_destructor", RID_GNU_HAS_TRIVIAL_DESTRUCTOR, 0 },
+  { "__gnu_is_class",	RID_GNU_IS_CLASS, 0 },
+  { "__gnu_is_empty",	RID_GNU_IS_EMPTY, 0 },
+  { "__gnu_is_pod",	RID_GNU_IS_POD, 0 },
+  { "__gnu_is_union",	RID_GNU_IS_UNION, 0 },
   { "__imag",		RID_IMAGPART,	0 },
   { "__imag__",		RID_IMAGPART,	0 },
   { "__inline",		RID_INLINE,	0 },
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 122814)
+++ cp/parser.c	(working copy)
@@ -1895,6 +1895,8 @@
   (cp_parser *, tree);
 static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
+static tree cp_parser_trait_expr
+  (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
@@ -2956,6 +2958,13 @@
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id , offsetof-expression )
 
+   C++ Extensions:
+     __gnu_has_trivial_destructor ( type-id )
+     __gnu_is_class ( type-id )
+     __gnu_is_empty ( type-id )
+     __gnu_is_pod ( type-id )
+     __gnu_is_union ( type-id )
+
    Objective-C++ Extension:
 
    primary-expression:
@@ -3193,7 +3202,14 @@
 	case RID_OFFSETOF:
 	  return cp_parser_builtin_offsetof (parser);
 
-	  /* Objective-C++ expressions.  */
+	case RID_GNU_HAS_TRIVIAL_DESTRUCTOR:
+	case RID_GNU_IS_CLASS:
+	case RID_GNU_IS_EMPTY:
+	case RID_GNU_IS_POD:
+	case RID_GNU_IS_UNION:
+	  return cp_parser_trait_expr (parser, token->keyword);
+
+	/* Objective-C++ expressions.  */
 	case RID_AT_ENCODE:
 	case RID_AT_PROTOCOL:
 	case RID_AT_SELECTOR:
@@ -6273,6 +6289,58 @@
   return expr;
 }
 
+/* Parse a trait expression.  */
+
+static tree
+cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
+{
+  cp_trait_kind kind;
+  tree type;
+  cp_decl_specifier_seq decl_specs;
+
+  switch (keyword)
+    {
+    case RID_GNU_HAS_TRIVIAL_DESTRUCTOR:
+      kind = CP_HAS_TRIVIAL_DESTRUCTOR;
+      break;
+    case RID_GNU_IS_CLASS:
+      kind = CP_IS_CLASS;
+      break;
+    case RID_GNU_IS_EMPTY:
+      kind = CP_IS_EMPTY;
+      break;
+    case RID_GNU_IS_POD:
+      kind = CP_IS_POD;
+      break;
+    case RID_GNU_IS_UNION:
+      kind = CP_IS_UNION;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Consume the token.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+
+  type = cp_parser_type_id (parser);
+
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+
+  /* Build a trivial decl-specifier-seq.  */
+  clear_decl_specs (&decl_specs);
+  decl_specs.type = type;
+
+  /* Call grokdeclarator to figure out what type this is.  */
+  type = grokdeclarator (NULL, &decl_specs, TYPENAME,
+  			 /*initialized=*/0, /*attrlist=*/NULL);
+
+  /* Complete the trait expr, which may mean either processing the
+     static assert now or saving it for template instantiation.  */
+  return finish_trait_expr (kind, type);
+}
+
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
Index: c-common.h
===================================================================
--- c-common.h	(revision 122814)
+++ c-common.h	(working copy)
@@ -90,6 +90,11 @@
   /* casts */
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
+  /* C++ extensions */
+  RID_GNU_HAS_TRIVIAL_DESTRUCTOR,
+  RID_GNU_IS_CLASS, RID_GNU_IS_EMPTY, RID_GNU_IS_POD,
+  RID_GNU_IS_UNION,
+
   /* C++0x */
   RID_STATIC_ASSERT,
 

Attachment: Tests.tar
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]