public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Implement LWG2296 helper intrinsic
@ 2016-10-07 19:23 Jakub Jelinek
  2016-10-07 19:34 ` Jason Merrill
  2017-01-01 14:27 ` Gerald Pfeifer
  0 siblings, 2 replies; 5+ messages in thread
From: Jakub Jelinek @ 2016-10-07 19:23 UTC (permalink / raw)
  To: Jason Merrill, Jonathan Wakely; +Cc: gcc-patches

Hi!

The following patch adds __builtin_addressof with the semantics it has in
clang, i.e. it is a constexpr & operator alternative that never uses the
overloaded & operator.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-10-07  Jakub Jelinek  <jakub@redhat.com>

	Implement LWG2296 helper intrinsic
c-family/
	* c-common.h (enum rid): Add RID_ADDRESSOF.
	* c-common.c (c_common_reswords): Add __builtin_addressof.
cp/
	* parser.c (cp_parser_postfix_expression): Handle RID_ADDRESSOF.
	* cp-objcp-common.c (cp_common_init_ts): Handle ADDRESSOF_EXPR.
	* constexpr.c (potential_constant_expression_1): Likewise.
	* error.c (dump_expr): Likewise.
	* typeck.c (cp_build_addressof): New function.
	* cp-tree.h (cp_build_addressof): Declare.
	* cxx-pretty-print.h (pp_cxx_addressof_expression): Declare.
	* cp-tree.def (ADDRESSOF_EXPR): New tree code.
	* cxx-pretty-print.c (cxx_pretty_printer::primary_expression): Handle
	ADDRESSOF_EXPR.  Add __builtin_addressof and
	__has_unique_object_representations into syntax in function comment.
	(pp_cxx_addressof_expression): New function.
	* pt.c (tsubst_copy_and_build): Handle ADDRESSOF_EXPR.
testsuite/
	* g++.dg/cpp0x/addressof1.C: New test.
	* g++.dg/cpp0x/addressof2.C: New test.

--- gcc/c-family/c-common.h.jj	2016-10-06 23:16:43.347087129 +0200
+++ gcc/c-family/c-common.h	2016-10-07 09:24:56.377835519 +0200
@@ -146,6 +146,7 @@ enum rid
   RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
 
   /* C++ extensions */
+  RID_ADDRESSOF,
   RID_BASES,                   RID_DIRECT_BASES,
   RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
   RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
--- gcc/c-family/c-common.c.jj	2016-10-06 23:16:43.351087082 +0200
+++ gcc/c-family/c-common.c	2016-10-07 09:24:56.380835482 +0200
@@ -463,6 +463,7 @@ const struct c_common_resword c_common_r
   { "__attribute__",	RID_ATTRIBUTE,	0 },
   { "__auto_type",	RID_AUTO_TYPE,	D_CONLY },
   { "__bases",          RID_BASES, D_CXXONLY },
+  { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
   { "__builtin_call_with_static_chain",
     RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
--- gcc/cp/parser.c.jj	2016-10-06 23:16:43.362086951 +0200
+++ gcc/cp/parser.c	2016-10-07 09:55:18.386923503 +0200
@@ -6602,6 +6602,7 @@ cp_parser_postfix_expression (cp_parser
 	break;
       }
 
+    case RID_ADDRESSOF:
     case RID_BUILTIN_SHUFFLE:
       {
 	vec<tree, va_gc> *vec;
@@ -6618,19 +6619,29 @@ cp_parser_postfix_expression (cp_parser
 	FOR_EACH_VEC_ELT (*vec, i, p)
 	  mark_exp_read (p);
 
-	if (vec->length () == 2)
-	  return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1],
-					 tf_warning_or_error);
-	else if (vec->length () == 3)
-	  return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2],
-					 tf_warning_or_error);
-	else
-	{
-	  error_at (loc, "wrong number of arguments to "
-	      "%<__builtin_shuffle%>");
-	  return error_mark_node;
-	}
-	break;
+	switch (keyword)
+	  {
+	  case RID_ADDRESSOF:
+	    if (vec->length () == 1)
+	      return cp_build_addressof (loc, (*vec)[0], tf_warning_or_error);
+	    error_at (loc, "wrong number of arguments to "
+			   "%<__builtin_addressof%>");
+	    return error_mark_node;
+
+	  case RID_BUILTIN_SHUFFLE:
+	    if (vec->length () == 2)
+	      return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
+					    (*vec)[1], tf_warning_or_error);
+	    else if (vec->length () == 3)
+	      return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1],
+					    (*vec)[2], tf_warning_or_error);
+	    error_at (loc, "wrong number of arguments to "
+			   "%<__builtin_shuffle%>");
+	    return error_mark_node;
+
+	  default:
+	    gcc_unreachable ();
+	  }
       }
 
     default:
--- gcc/cp/cp-objcp-common.c.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/cp-objcp-common.c	2016-10-07 09:55:18.391923440 +0200
@@ -315,6 +315,7 @@ cp_common_init_ts (void)
   MARK_TS_TYPED (STMT_EXPR);
   MARK_TS_TYPED (OFFSET_REF);
   MARK_TS_TYPED (OFFSETOF_EXPR);
+  MARK_TS_TYPED (ADDRESSOF_EXPR);
   MARK_TS_TYPED (PTRMEM_CST);
   MARK_TS_TYPED (EMPTY_CLASS_EXPR);
   MARK_TS_TYPED (VEC_INIT_EXPR);
--- gcc/cp/constexpr.c.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/constexpr.c	2016-10-07 09:55:18.395923390 +0200
@@ -5025,6 +5025,11 @@ potential_constant_expression_1 (tree t,
         return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
       }
 
+    case ADDRESSOF_EXPR:
+      /* This is like ADDR_EXPR, except it won't form pointer-to-member.  */
+      t = TREE_OPERAND (t, 0);
+      goto handle_addr_expr;
+
     case ADDR_EXPR:
       /* -- a unary operator & that is applied to an lvalue that
             designates an object with thread or automatic storage
@@ -5035,6 +5040,7 @@ potential_constant_expression_1 (tree t,
 	/* A pointer-to-member constant.  */
 	return true;
 
+    handle_addr_expr:
 #if 0
       /* FIXME adjust when issue 1197 is fully resolved.  For now don't do
          any checking here, as we might dereference the pointer later.  If
--- gcc/cp/error.c.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/error.c	2016-10-07 09:55:18.399923339 +0200
@@ -2678,6 +2678,10 @@ dump_expr (cxx_pretty_printer *pp, tree
       pp_cxx_offsetof_expression (pp, t);
       break;
 
+    case ADDRESSOF_EXPR:
+      pp_cxx_addressof_expression (pp, t);
+      break;
+
     case SCOPE_REF:
       dump_decl (pp, t, flags);
       break;
--- gcc/cp/typeck.c.jj	2016-10-07 09:22:41.000000000 +0200
+++ gcc/cp/typeck.c	2016-10-07 09:55:18.402923302 +0200
@@ -5456,6 +5456,29 @@ build_x_unary_op (location_t loc, enum t
   return exp;
 }
 
+/* Construct and perhaps optimize a tree representation
+   for __builtin_addressof operation.  ARG specifies the operand.  */
+
+tree
+cp_build_addressof (location_t loc, tree arg, tsubst_flags_t complain)
+{
+  tree orig_expr = arg;
+
+  if (processing_template_decl)
+    {
+      if (type_dependent_expression_p (arg))
+	return build_min_nt_loc (loc, ADDRESSOF_EXPR, arg, NULL_TREE);
+
+      arg = build_non_dependent_expr (arg);
+    }
+
+  tree exp = cp_build_addr_expr_strict (arg, complain);
+
+  if (processing_template_decl && exp != error_mark_node)
+    exp = build_min_non_dep (ADDRESSOF_EXPR, exp, orig_expr, NULL_TREE);
+  return exp;
+}
+
 /* Like c_common_truthvalue_conversion, but handle pointer-to-member
    constants, where a null value is represented by an INTEGER_CST of
    -1.  */
--- gcc/cp/cp-tree.h.jj	2016-10-07 09:22:41.124537407 +0200
+++ gcc/cp/cp-tree.h	2016-10-07 09:43:15.705007420 +0200
@@ -6658,6 +6658,8 @@ extern tree build_x_array_ref			(locatio
 extern tree build_x_unary_op			(location_t,
 						 enum tree_code, cp_expr,
                                                  tsubst_flags_t);
+extern tree cp_build_addressof			(location_t, tree,
+						 tsubst_flags_t);
 extern tree cp_build_addr_expr			(tree, tsubst_flags_t);
 extern tree cp_build_unary_op                   (enum tree_code, tree, bool,
                                                  tsubst_flags_t);
--- gcc/cp/cxx-pretty-print.h.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/cxx-pretty-print.h	2016-10-07 09:32:00.381501689 +0200
@@ -90,6 +90,7 @@ void pp_cxx_canonical_template_parameter
 void pp_cxx_trait_expression (cxx_pretty_printer *, tree);
 void pp_cxx_va_arg_expression (cxx_pretty_printer *, tree);
 void pp_cxx_offsetof_expression (cxx_pretty_printer *, tree);
+void pp_cxx_addressof_expression (cxx_pretty_printer *, tree);
 void pp_cxx_userdef_literal (cxx_pretty_printer *, tree);
 void pp_cxx_requires_clause (cxx_pretty_printer *, tree);
 void pp_cxx_requires_expr (cxx_pretty_printer *, tree);
--- gcc/cp/cp-tree.def.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/cp-tree.def	2016-10-07 09:26:39.947532646 +0200
@@ -334,6 +334,11 @@ DEFTREECODE (TAG_DEFN, "tag_defn", tcc_e
 /* Represents an 'offsetof' expression during template expansion.  */
 DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1)
 
+/* Represents an '__builtin_addressof' expression during template
+   expansion.  This is similar to ADDR_EXPR, but it doesn't invoke
+   overloaded & operators.  */
+DEFTREECODE (ADDRESSOF_EXPR, "addressof_expr", tcc_expression, 1)
+
 /* Represents the -> operator during template expansion.  */
 DEFTREECODE (ARROW_EXPR, "arrow_expr", tcc_expression, 1)
 
--- gcc/cp/cxx-pretty-print.c.jj	2016-10-06 23:16:43.000000000 +0200
+++ gcc/cp/cxx-pretty-print.c	2016-10-07 09:55:18.406923251 +0200
@@ -380,6 +380,7 @@ pp_cxx_userdef_literal (cxx_pretty_print
    GNU Extensions:
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id, offsetof-expression )
+     __builtin_addressof ( expression )
 
      __has_nothrow_assign ( type-id )   
      __has_nothrow_constructor ( type-id )
@@ -387,6 +388,7 @@ pp_cxx_userdef_literal (cxx_pretty_print
      __has_trivial_assign ( type-id )   
      __has_trivial_constructor ( type-id )
      __has_trivial_copy ( type-id )
+     __has_unique_object_representations ( type-id )
      __has_trivial_destructor ( type-id )
      __has_virtual_destructor ( type-id )     
      __is_abstract ( type-id )
@@ -456,6 +458,10 @@ cxx_pretty_printer::primary_expression (
       pp_cxx_offsetof_expression (this, t);
       break;
 
+    case ADDRESSOF_EXPR:
+      pp_cxx_addressof_expression (this, t);
+      break;
+
     case REQUIRES_EXPR:
       pp_cxx_requires_expr (this, t);
       break;
@@ -2437,6 +2443,15 @@ pp_cxx_offsetof_expression (cxx_pretty_p
   pp_cxx_right_paren (pp);
 }
 
+void
+pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t)
+{
+  pp_cxx_ws_string (pp, "__builtin_addressof");
+  pp_cxx_left_paren (pp);
+  pp->expression (TREE_OPERAND (t, 0));
+  pp_cxx_right_paren (pp);
+}
+
 static char const*
 get_fold_operator (tree t)
 {
--- gcc/cp/pt.c.jj	2016-10-06 17:46:29.000000000 +0200
+++ gcc/cp/pt.c	2016-10-07 09:55:51.183511259 +0200
@@ -17204,6 +17204,10 @@ tsubst_copy_and_build (tree t,
       RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
 			       EXPR_LOCATION (t)));
 
+    case ADDRESSOF_EXPR:
+      RETURN (cp_build_addressof (EXPR_LOCATION (t),
+				  RECUR (TREE_OPERAND (t, 0)), complain));
+
     case TRAIT_EXPR:
       {
 	tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args,
--- gcc/testsuite/g++.dg/cpp0x/addressof1.C.jj	2016-10-07 10:45:09.797113801 +0200
+++ gcc/testsuite/g++.dg/cpp0x/addressof1.C	2016-10-07 11:03:55.376874116 +0200
@@ -0,0 +1,96 @@
+// LWG2296 - addressof should be constexpr
+// { dg-do run { target c++11 } }
+
+template <typename T>
+constexpr inline T *
+addressof (T &x) noexcept
+{
+  return __builtin_addressof (x);
+}
+
+int i;
+static_assert (__builtin_addressof (i) == &i, "");
+static_assert (addressof (i) == &i, "");
+
+constexpr int &j = i;
+static_assert (__builtin_addressof (j) == &i, "");
+static_assert (addressof (j) == &i, "");
+
+struct S { int s; } s;
+static_assert (__builtin_addressof (s) == &s, "");
+static_assert ((int *) __builtin_addressof (s) == &s.s, "");
+static_assert (addressof (s) == &s, "");
+static_assert ((int *) addressof (s) == &s.s, "");
+
+struct T
+{
+  static T tt;
+  constexpr T () : p (addressof (tt)) {}
+  constexpr T *operator & () const { return p; }
+  T *p;
+};
+constexpr T t;
+T T::tt;
+static_assert (__builtin_addressof (t) == (const T *) &t.p, "");
+static_assert (&t == __builtin_addressof (T::tt), "");
+static_assert (addressof (t) == (const T *) &t.p, "");
+static_assert (&t == addressof (T::tt), "");
+
+struct S x, y;
+
+constexpr S *
+foo (bool b)
+{
+  return __builtin_addressof (b ? x : y);
+}
+
+constexpr S *
+bar (bool b, S &c, S &d)
+{
+  return __builtin_addressof (b ? c : d);
+}
+
+static_assert (foo (false) == &y, "");
+static_assert (foo (true) == &x, "");
+static_assert (bar (false, y, x) == &x, "");
+static_assert (bar (true, y, x) == &y, "");
+
+constexpr S *
+foo2 (bool b)
+{
+  return addressof (b ? x : y);
+}
+
+constexpr S *
+bar2 (bool b, S &c, S &d)
+{
+  return addressof (b ? c : d);
+}
+
+static_assert (foo2 (false) == &y, "");
+static_assert (foo2 (true) == &x, "");
+static_assert (bar2 (false, y, x) == &x, "");
+static_assert (bar2 (true, y, x) == &y, "");
+
+constexpr int a = 1;
+static_assert (__builtin_addressof (a) == &a, "");
+static_assert (addressof (a) == &a, "");
+constexpr int c[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+static_assert ((const int *) __builtin_addressof (c) == &c[0], "");
+static_assert ((const int *) addressof (c) == &c[0], "");
+
+void
+baz ()
+{
+}
+
+int
+main ()
+{
+  if (__builtin_addressof (T::tt) == __builtin_addressof (t)
+      || addressof (T::tt) == addressof (t)
+      || &T::tt != &t
+      || __builtin_addressof (baz) != baz
+      || addressof (baz) != baz)
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp0x/addressof2.C.jj	2016-10-07 11:08:38.481283997 +0200
+++ gcc/testsuite/g++.dg/cpp0x/addressof2.C	2016-10-07 11:08:02.000000000 +0200
@@ -0,0 +1,33 @@
+// LWG2296 - addressof should be constexpr
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+constexpr inline T *
+addressof (T &x) noexcept
+{
+  return __builtin_addressof (x);
+}
+
+auto a = __builtin_addressof (1);		// { dg-error "lvalue required as unary" }
+auto b = addressof (1);				// { dg-error "cannot bind non-const lvalue reference of type" }
+
+struct S { int s : 5; int t; void foo (); } s;
+
+auto c = __builtin_addressof (s);
+auto d = addressof (s);
+auto e = __builtin_addressof (s.s);		// { dg-error "attempt to take address of bit-field structure member" }
+auto f = addressof (s.s);			// { dg-error "cannot bind bitfield" }
+auto g = __builtin_addressof (S{});		// { dg-error "taking address of temporary" }
+auto h = addressof (S{});			// { dg-error "cannot bind non-const lvalue reference of type" }
+auto i = __builtin_addressof (S::t);		// { dg-error "invalid use of non-static data member" }
+auto j = __builtin_addressof (S::foo);		// { dg-error "invalid use of non-static member function" }
+
+void
+foo (bool b)
+{
+  lab:;
+  char c;
+  long long int d;
+  auto k = __builtin_addressof (lab);		// { dg-error "was not declared in this scope" }
+  auto l = __builtin_addressof (b ? c : d);	// { dg-error "lvalue required as unary" }
+}

	Jakub

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

* Re: [C++ PATCH] Implement LWG2296 helper intrinsic
  2016-10-07 19:23 [C++ PATCH] Implement LWG2296 helper intrinsic Jakub Jelinek
@ 2016-10-07 19:34 ` Jason Merrill
  2017-01-01 14:27 ` Gerald Pfeifer
  1 sibling, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2016-10-07 19:34 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jonathan Wakely, gcc-patches List

OK.

On Fri, Oct 7, 2016 at 3:23 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> The following patch adds __builtin_addressof with the semantics it has in
> clang, i.e. it is a constexpr & operator alternative that never uses the
> overloaded & operator.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2016-10-07  Jakub Jelinek  <jakub@redhat.com>
>
>         Implement LWG2296 helper intrinsic
> c-family/
>         * c-common.h (enum rid): Add RID_ADDRESSOF.
>         * c-common.c (c_common_reswords): Add __builtin_addressof.
> cp/
>         * parser.c (cp_parser_postfix_expression): Handle RID_ADDRESSOF.
>         * cp-objcp-common.c (cp_common_init_ts): Handle ADDRESSOF_EXPR.
>         * constexpr.c (potential_constant_expression_1): Likewise.
>         * error.c (dump_expr): Likewise.
>         * typeck.c (cp_build_addressof): New function.
>         * cp-tree.h (cp_build_addressof): Declare.
>         * cxx-pretty-print.h (pp_cxx_addressof_expression): Declare.
>         * cp-tree.def (ADDRESSOF_EXPR): New tree code.
>         * cxx-pretty-print.c (cxx_pretty_printer::primary_expression): Handle
>         ADDRESSOF_EXPR.  Add __builtin_addressof and
>         __has_unique_object_representations into syntax in function comment.
>         (pp_cxx_addressof_expression): New function.
>         * pt.c (tsubst_copy_and_build): Handle ADDRESSOF_EXPR.
> testsuite/
>         * g++.dg/cpp0x/addressof1.C: New test.
>         * g++.dg/cpp0x/addressof2.C: New test.
>
> --- gcc/c-family/c-common.h.jj  2016-10-06 23:16:43.347087129 +0200
> +++ gcc/c-family/c-common.h     2016-10-07 09:24:56.377835519 +0200
> @@ -146,6 +146,7 @@ enum rid
>    RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
>
>    /* C++ extensions */
> +  RID_ADDRESSOF,
>    RID_BASES,                   RID_DIRECT_BASES,
>    RID_HAS_NOTHROW_ASSIGN,      RID_HAS_NOTHROW_CONSTRUCTOR,
>    RID_HAS_NOTHROW_COPY,        RID_HAS_TRIVIAL_ASSIGN,
> --- gcc/c-family/c-common.c.jj  2016-10-06 23:16:43.351087082 +0200
> +++ gcc/c-family/c-common.c     2016-10-07 09:24:56.380835482 +0200
> @@ -463,6 +463,7 @@ const struct c_common_resword c_common_r
>    { "__attribute__",   RID_ATTRIBUTE,  0 },
>    { "__auto_type",     RID_AUTO_TYPE,  D_CONLY },
>    { "__bases",          RID_BASES, D_CXXONLY },
> +  { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
>    { "__builtin_call_with_static_chain",
>      RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
>    { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
> --- gcc/cp/parser.c.jj  2016-10-06 23:16:43.362086951 +0200
> +++ gcc/cp/parser.c     2016-10-07 09:55:18.386923503 +0200
> @@ -6602,6 +6602,7 @@ cp_parser_postfix_expression (cp_parser
>         break;
>        }
>
> +    case RID_ADDRESSOF:
>      case RID_BUILTIN_SHUFFLE:
>        {
>         vec<tree, va_gc> *vec;
> @@ -6618,19 +6619,29 @@ cp_parser_postfix_expression (cp_parser
>         FOR_EACH_VEC_ELT (*vec, i, p)
>           mark_exp_read (p);
>
> -       if (vec->length () == 2)
> -         return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1],
> -                                        tf_warning_or_error);
> -       else if (vec->length () == 3)
> -         return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2],
> -                                        tf_warning_or_error);
> -       else
> -       {
> -         error_at (loc, "wrong number of arguments to "
> -             "%<__builtin_shuffle%>");
> -         return error_mark_node;
> -       }
> -       break;
> +       switch (keyword)
> +         {
> +         case RID_ADDRESSOF:
> +           if (vec->length () == 1)
> +             return cp_build_addressof (loc, (*vec)[0], tf_warning_or_error);
> +           error_at (loc, "wrong number of arguments to "
> +                          "%<__builtin_addressof%>");
> +           return error_mark_node;
> +
> +         case RID_BUILTIN_SHUFFLE:
> +           if (vec->length () == 2)
> +             return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
> +                                           (*vec)[1], tf_warning_or_error);
> +           else if (vec->length () == 3)
> +             return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1],
> +                                           (*vec)[2], tf_warning_or_error);
> +           error_at (loc, "wrong number of arguments to "
> +                          "%<__builtin_shuffle%>");
> +           return error_mark_node;
> +
> +         default:
> +           gcc_unreachable ();
> +         }
>        }
>
>      default:
> --- gcc/cp/cp-objcp-common.c.jj 2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/cp-objcp-common.c    2016-10-07 09:55:18.391923440 +0200
> @@ -315,6 +315,7 @@ cp_common_init_ts (void)
>    MARK_TS_TYPED (STMT_EXPR);
>    MARK_TS_TYPED (OFFSET_REF);
>    MARK_TS_TYPED (OFFSETOF_EXPR);
> +  MARK_TS_TYPED (ADDRESSOF_EXPR);
>    MARK_TS_TYPED (PTRMEM_CST);
>    MARK_TS_TYPED (EMPTY_CLASS_EXPR);
>    MARK_TS_TYPED (VEC_INIT_EXPR);
> --- gcc/cp/constexpr.c.jj       2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/constexpr.c  2016-10-07 09:55:18.395923390 +0200
> @@ -5025,6 +5025,11 @@ potential_constant_expression_1 (tree t,
>          return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
>        }
>
> +    case ADDRESSOF_EXPR:
> +      /* This is like ADDR_EXPR, except it won't form pointer-to-member.  */
> +      t = TREE_OPERAND (t, 0);
> +      goto handle_addr_expr;
> +
>      case ADDR_EXPR:
>        /* -- a unary operator & that is applied to an lvalue that
>              designates an object with thread or automatic storage
> @@ -5035,6 +5040,7 @@ potential_constant_expression_1 (tree t,
>         /* A pointer-to-member constant.  */
>         return true;
>
> +    handle_addr_expr:
>  #if 0
>        /* FIXME adjust when issue 1197 is fully resolved.  For now don't do
>           any checking here, as we might dereference the pointer later.  If
> --- gcc/cp/error.c.jj   2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/error.c      2016-10-07 09:55:18.399923339 +0200
> @@ -2678,6 +2678,10 @@ dump_expr (cxx_pretty_printer *pp, tree
>        pp_cxx_offsetof_expression (pp, t);
>        break;
>
> +    case ADDRESSOF_EXPR:
> +      pp_cxx_addressof_expression (pp, t);
> +      break;
> +
>      case SCOPE_REF:
>        dump_decl (pp, t, flags);
>        break;
> --- gcc/cp/typeck.c.jj  2016-10-07 09:22:41.000000000 +0200
> +++ gcc/cp/typeck.c     2016-10-07 09:55:18.402923302 +0200
> @@ -5456,6 +5456,29 @@ build_x_unary_op (location_t loc, enum t
>    return exp;
>  }
>
> +/* Construct and perhaps optimize a tree representation
> +   for __builtin_addressof operation.  ARG specifies the operand.  */
> +
> +tree
> +cp_build_addressof (location_t loc, tree arg, tsubst_flags_t complain)
> +{
> +  tree orig_expr = arg;
> +
> +  if (processing_template_decl)
> +    {
> +      if (type_dependent_expression_p (arg))
> +       return build_min_nt_loc (loc, ADDRESSOF_EXPR, arg, NULL_TREE);
> +
> +      arg = build_non_dependent_expr (arg);
> +    }
> +
> +  tree exp = cp_build_addr_expr_strict (arg, complain);
> +
> +  if (processing_template_decl && exp != error_mark_node)
> +    exp = build_min_non_dep (ADDRESSOF_EXPR, exp, orig_expr, NULL_TREE);
> +  return exp;
> +}
> +
>  /* Like c_common_truthvalue_conversion, but handle pointer-to-member
>     constants, where a null value is represented by an INTEGER_CST of
>     -1.  */
> --- gcc/cp/cp-tree.h.jj 2016-10-07 09:22:41.124537407 +0200
> +++ gcc/cp/cp-tree.h    2016-10-07 09:43:15.705007420 +0200
> @@ -6658,6 +6658,8 @@ extern tree build_x_array_ref                     (locatio
>  extern tree build_x_unary_op                   (location_t,
>                                                  enum tree_code, cp_expr,
>                                                   tsubst_flags_t);
> +extern tree cp_build_addressof                 (location_t, tree,
> +                                                tsubst_flags_t);
>  extern tree cp_build_addr_expr                 (tree, tsubst_flags_t);
>  extern tree cp_build_unary_op                   (enum tree_code, tree, bool,
>                                                   tsubst_flags_t);
> --- gcc/cp/cxx-pretty-print.h.jj        2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/cxx-pretty-print.h   2016-10-07 09:32:00.381501689 +0200
> @@ -90,6 +90,7 @@ void pp_cxx_canonical_template_parameter
>  void pp_cxx_trait_expression (cxx_pretty_printer *, tree);
>  void pp_cxx_va_arg_expression (cxx_pretty_printer *, tree);
>  void pp_cxx_offsetof_expression (cxx_pretty_printer *, tree);
> +void pp_cxx_addressof_expression (cxx_pretty_printer *, tree);
>  void pp_cxx_userdef_literal (cxx_pretty_printer *, tree);
>  void pp_cxx_requires_clause (cxx_pretty_printer *, tree);
>  void pp_cxx_requires_expr (cxx_pretty_printer *, tree);
> --- gcc/cp/cp-tree.def.jj       2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/cp-tree.def  2016-10-07 09:26:39.947532646 +0200
> @@ -334,6 +334,11 @@ DEFTREECODE (TAG_DEFN, "tag_defn", tcc_e
>  /* Represents an 'offsetof' expression during template expansion.  */
>  DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1)
>
> +/* Represents an '__builtin_addressof' expression during template
> +   expansion.  This is similar to ADDR_EXPR, but it doesn't invoke
> +   overloaded & operators.  */
> +DEFTREECODE (ADDRESSOF_EXPR, "addressof_expr", tcc_expression, 1)
> +
>  /* Represents the -> operator during template expansion.  */
>  DEFTREECODE (ARROW_EXPR, "arrow_expr", tcc_expression, 1)
>
> --- gcc/cp/cxx-pretty-print.c.jj        2016-10-06 23:16:43.000000000 +0200
> +++ gcc/cp/cxx-pretty-print.c   2016-10-07 09:55:18.406923251 +0200
> @@ -380,6 +380,7 @@ pp_cxx_userdef_literal (cxx_pretty_print
>     GNU Extensions:
>       __builtin_va_arg ( assignment-expression , type-id )
>       __builtin_offsetof ( type-id, offsetof-expression )
> +     __builtin_addressof ( expression )
>
>       __has_nothrow_assign ( type-id )
>       __has_nothrow_constructor ( type-id )
> @@ -387,6 +388,7 @@ pp_cxx_userdef_literal (cxx_pretty_print
>       __has_trivial_assign ( type-id )
>       __has_trivial_constructor ( type-id )
>       __has_trivial_copy ( type-id )
> +     __has_unique_object_representations ( type-id )
>       __has_trivial_destructor ( type-id )
>       __has_virtual_destructor ( type-id )
>       __is_abstract ( type-id )
> @@ -456,6 +458,10 @@ cxx_pretty_printer::primary_expression (
>        pp_cxx_offsetof_expression (this, t);
>        break;
>
> +    case ADDRESSOF_EXPR:
> +      pp_cxx_addressof_expression (this, t);
> +      break;
> +
>      case REQUIRES_EXPR:
>        pp_cxx_requires_expr (this, t);
>        break;
> @@ -2437,6 +2443,15 @@ pp_cxx_offsetof_expression (cxx_pretty_p
>    pp_cxx_right_paren (pp);
>  }
>
> +void
> +pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t)
> +{
> +  pp_cxx_ws_string (pp, "__builtin_addressof");
> +  pp_cxx_left_paren (pp);
> +  pp->expression (TREE_OPERAND (t, 0));
> +  pp_cxx_right_paren (pp);
> +}
> +
>  static char const*
>  get_fold_operator (tree t)
>  {
> --- gcc/cp/pt.c.jj      2016-10-06 17:46:29.000000000 +0200
> +++ gcc/cp/pt.c 2016-10-07 09:55:51.183511259 +0200
> @@ -17204,6 +17204,10 @@ tsubst_copy_and_build (tree t,
>        RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
>                                EXPR_LOCATION (t)));
>
> +    case ADDRESSOF_EXPR:
> +      RETURN (cp_build_addressof (EXPR_LOCATION (t),
> +                                 RECUR (TREE_OPERAND (t, 0)), complain));
> +
>      case TRAIT_EXPR:
>        {
>         tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args,
> --- gcc/testsuite/g++.dg/cpp0x/addressof1.C.jj  2016-10-07 10:45:09.797113801 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/addressof1.C     2016-10-07 11:03:55.376874116 +0200
> @@ -0,0 +1,96 @@
> +// LWG2296 - addressof should be constexpr
> +// { dg-do run { target c++11 } }
> +
> +template <typename T>
> +constexpr inline T *
> +addressof (T &x) noexcept
> +{
> +  return __builtin_addressof (x);
> +}
> +
> +int i;
> +static_assert (__builtin_addressof (i) == &i, "");
> +static_assert (addressof (i) == &i, "");
> +
> +constexpr int &j = i;
> +static_assert (__builtin_addressof (j) == &i, "");
> +static_assert (addressof (j) == &i, "");
> +
> +struct S { int s; } s;
> +static_assert (__builtin_addressof (s) == &s, "");
> +static_assert ((int *) __builtin_addressof (s) == &s.s, "");
> +static_assert (addressof (s) == &s, "");
> +static_assert ((int *) addressof (s) == &s.s, "");
> +
> +struct T
> +{
> +  static T tt;
> +  constexpr T () : p (addressof (tt)) {}
> +  constexpr T *operator & () const { return p; }
> +  T *p;
> +};
> +constexpr T t;
> +T T::tt;
> +static_assert (__builtin_addressof (t) == (const T *) &t.p, "");
> +static_assert (&t == __builtin_addressof (T::tt), "");
> +static_assert (addressof (t) == (const T *) &t.p, "");
> +static_assert (&t == addressof (T::tt), "");
> +
> +struct S x, y;
> +
> +constexpr S *
> +foo (bool b)
> +{
> +  return __builtin_addressof (b ? x : y);
> +}
> +
> +constexpr S *
> +bar (bool b, S &c, S &d)
> +{
> +  return __builtin_addressof (b ? c : d);
> +}
> +
> +static_assert (foo (false) == &y, "");
> +static_assert (foo (true) == &x, "");
> +static_assert (bar (false, y, x) == &x, "");
> +static_assert (bar (true, y, x) == &y, "");
> +
> +constexpr S *
> +foo2 (bool b)
> +{
> +  return addressof (b ? x : y);
> +}
> +
> +constexpr S *
> +bar2 (bool b, S &c, S &d)
> +{
> +  return addressof (b ? c : d);
> +}
> +
> +static_assert (foo2 (false) == &y, "");
> +static_assert (foo2 (true) == &x, "");
> +static_assert (bar2 (false, y, x) == &x, "");
> +static_assert (bar2 (true, y, x) == &y, "");
> +
> +constexpr int a = 1;
> +static_assert (__builtin_addressof (a) == &a, "");
> +static_assert (addressof (a) == &a, "");
> +constexpr int c[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
> +static_assert ((const int *) __builtin_addressof (c) == &c[0], "");
> +static_assert ((const int *) addressof (c) == &c[0], "");
> +
> +void
> +baz ()
> +{
> +}
> +
> +int
> +main ()
> +{
> +  if (__builtin_addressof (T::tt) == __builtin_addressof (t)
> +      || addressof (T::tt) == addressof (t)
> +      || &T::tt != &t
> +      || __builtin_addressof (baz) != baz
> +      || addressof (baz) != baz)
> +    __builtin_abort ();
> +}
> --- gcc/testsuite/g++.dg/cpp0x/addressof2.C.jj  2016-10-07 11:08:38.481283997 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/addressof2.C     2016-10-07 11:08:02.000000000 +0200
> @@ -0,0 +1,33 @@
> +// LWG2296 - addressof should be constexpr
> +// { dg-do compile { target c++11 } }
> +
> +template <typename T>
> +constexpr inline T *
> +addressof (T &x) noexcept
> +{
> +  return __builtin_addressof (x);
> +}
> +
> +auto a = __builtin_addressof (1);              // { dg-error "lvalue required as unary" }
> +auto b = addressof (1);                                // { dg-error "cannot bind non-const lvalue reference of type" }
> +
> +struct S { int s : 5; int t; void foo (); } s;
> +
> +auto c = __builtin_addressof (s);
> +auto d = addressof (s);
> +auto e = __builtin_addressof (s.s);            // { dg-error "attempt to take address of bit-field structure member" }
> +auto f = addressof (s.s);                      // { dg-error "cannot bind bitfield" }
> +auto g = __builtin_addressof (S{});            // { dg-error "taking address of temporary" }
> +auto h = addressof (S{});                      // { dg-error "cannot bind non-const lvalue reference of type" }
> +auto i = __builtin_addressof (S::t);           // { dg-error "invalid use of non-static data member" }
> +auto j = __builtin_addressof (S::foo);         // { dg-error "invalid use of non-static member function" }
> +
> +void
> +foo (bool b)
> +{
> +  lab:;
> +  char c;
> +  long long int d;
> +  auto k = __builtin_addressof (lab);          // { dg-error "was not declared in this scope" }
> +  auto l = __builtin_addressof (b ? c : d);    // { dg-error "lvalue required as unary" }
> +}
>
>         Jakub

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

* Re: [C++ PATCH] Implement LWG2296 helper intrinsic
  2016-10-07 19:23 [C++ PATCH] Implement LWG2296 helper intrinsic Jakub Jelinek
  2016-10-07 19:34 ` Jason Merrill
@ 2017-01-01 14:27 ` Gerald Pfeifer
  2017-01-01 14:53   ` Jakub Jelinek
  1 sibling, 1 reply; 5+ messages in thread
From: Gerald Pfeifer @ 2017-01-01 14:27 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jason Merrill, Jonathan Wakely, gcc-patches

On Fri, 7 Oct 2016, Jakub Jelinek wrote:
> The following patch adds __builtin_addressof with the semantics it has in
> clang, i.e. it is a constexpr & operator alternative that never uses the
> overloaded & operator.

Nice!

Are you planning to document this in gcc-7/changes.html ?

Gerald

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

* Re: [C++ PATCH] Implement LWG2296 helper intrinsic
  2017-01-01 14:27 ` Gerald Pfeifer
@ 2017-01-01 14:53   ` Jakub Jelinek
  2017-01-03 10:55     ` Jonathan Wakely
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2017-01-01 14:53 UTC (permalink / raw)
  To: Gerald Pfeifer; +Cc: Jason Merrill, Jonathan Wakely, gcc-patches

On Sun, Jan 01, 2017 at 10:27:24AM -0400, Gerald Pfeifer wrote:
> On Fri, 7 Oct 2016, Jakub Jelinek wrote:
> > The following patch adds __builtin_addressof with the semantics it has in
> > clang, i.e. it is a constexpr & operator alternative that never uses the
> > overloaded & operator.
> 
> Nice!
> 
> Are you planning to document this in gcc-7/changes.html ?

We shouldn't document the builtin, but that std::addressof is usable in
constexpr contexts.  I'll defer documentation thereof to Jon, together with
other libstdc++ changes.

	Jakub

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

* Re: [C++ PATCH] Implement LWG2296 helper intrinsic
  2017-01-01 14:53   ` Jakub Jelinek
@ 2017-01-03 10:55     ` Jonathan Wakely
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Wakely @ 2017-01-03 10:55 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Gerald Pfeifer, Jason Merrill, gcc-patches

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

On 01/01/17 15:53 +0100, Jakub Jelinek wrote:
>On Sun, Jan 01, 2017 at 10:27:24AM -0400, Gerald Pfeifer wrote:
>> On Fri, 7 Oct 2016, Jakub Jelinek wrote:
>> > The following patch adds __builtin_addressof with the semantics it has in
>> > clang, i.e. it is a constexpr & operator alternative that never uses the
>> > overloaded & operator.
>>
>> Nice!
>>
>> Are you planning to document this in gcc-7/changes.html ?
>
>We shouldn't document the builtin, but that std::addressof is usable in
>constexpr contexts.  I'll defer documentation thereof to Jon, together with
>other libstdc++ changes.

I've committed this to wwwdocs.



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1686 bytes --]

? htdocs/gcc-7/.changes.html.swp
Index: htdocs/gcc-7/changes.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-7/changes.html,v
retrieving revision 1.32
diff -u -r1.32 changes.html
--- htdocs/gcc-7/changes.html	27 Nov 2016 12:54:13 -0000	1.32
+++ htdocs/gcc-7/changes.html	3 Jan 2017 10:54:01 -0000
@@ -287,13 +287,30 @@
       <code>std::chrono::round</code>, and <code>std::chrono::abs</code>;
     </li>
     <li>
-      <code>std::clamp</code>;
+      <code>std::clamp</code>, <code>std::gcd</code>, <code>std::lcm</code>,
+      3-dimensional <code>std::hypot</code>;
+    </li>
+    <li><code>std::shared_mutex</code>;</li>
+    <li><code>std::default_searcher</code>,
+      <code>std::boyer_moore_searcher</code> and
+      <code>std::boyer_moore_horspool_searcher</code>;
+    </li>
+    <li>
+      Extraction and re-insertion of map and set nodes, <code>try_emplace</code>
+      members for maps, and functions for accessing containers
+      <code>std::size</code>, <code>std::empty</code>, and
+      <code>std::data</code>;
     </li>
     <li>
+      <code>std::shared_ptr</code> support for arrays,
       <code>std::shared_ptr&lt;T&gt;::weak_type</code>,
       <code>std::enable_shared_from_this&lt;T&gt;::weak_from_this()</code>,
       and <code>std::owner_less&lt;void&gt;</code>;
     </li>
+    <li><code>std::as_const</code>, <code>std::not_fn</code>,
+      <code>std::has_unique_object_representations</code>,
+      constexpr <code>std::addressof</code>.
+    </li>
   </ul>
   Thanks to Daniel Kr&uuml;gler, Tim Shen, Edward Smith-Rowland, and Ville Voutilainen for
   work on the C++17 support.

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

end of thread, other threads:[~2017-01-03 10:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-07 19:23 [C++ PATCH] Implement LWG2296 helper intrinsic Jakub Jelinek
2016-10-07 19:34 ` Jason Merrill
2017-01-01 14:27 ` Gerald Pfeifer
2017-01-01 14:53   ` Jakub Jelinek
2017-01-03 10:55     ` Jonathan Wakely

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