Re: C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)

2017-05-24 Thread Jakub Jelinek
On Wed, May 24, 2017 at 02:47:08PM -0400, Jason Merrill wrote:
> On Wed, May 24, 2017 at 11:08 AM, Jakub Jelinek  wrote:
> > On Wed, May 24, 2017 at 04:16:30PM +0200, Andreas Schwab wrote:
> >> FAIL: g++.dg/ext/integer-pack2.C  -std=gnu++11 (test for excess errors)
> >> Excess errors:
> >> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
> >>  error: overflow in constant expression [-fpermissive]
> >> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
> >>  error: overflow in constant expression [-fpermissive]
> >
> > To be precise, it fails only on 32-bit targets.
> 
> > If we at that point want some wider integer that when cast to int
> > is 0 (or small enough positive number?), shall we use something like
> > this, or say 1LL << (sizeof (int) * __CHAR_BIT__), or 2LL * INT_MIN,
> > something else?
> 
> This is fine.
> 
> > Do we need to include ?  Or can we replace
> > INT_MAX with __INT_MAX__?
> 
> __INT_MAX__ sounds good.
> 
> > Not sure about that -2147483650 for 16-bit int targets (perhaps the test can
> > be guarded with int32 effective target).
> 
> Yes, restricting the test to int32 seems like the easiest fix.

Ok, I've committed this (also add something to avoid failing on hypothetical
64-bit int 64-bit long long target).  Tested for both -m32 and -m64 on
x86_64-linux.

2017-05-24  Jakub Jelinek  

* g++.dg/ext/integer-pack2.C: Require int32 effective target.
Don't include limits.h.
(w): Conditionalize on long long wider than int.  Use
1LL << (__SIZEOF_INT__ * __CHAR_BIT__) instead of
-9223372036854775808.
(x): Use __INT_MAX__ instead of INT_MAX.

--- gcc/testsuite/g++.dg/ext/integer-pack2.C.jj 2017-05-24 11:59:01.0 
+0200
+++ gcc/testsuite/g++.dg/ext/integer-pack2.C2017-05-24 21:07:02.0 
+0200
@@ -1,12 +1,12 @@
-// { dg-do compile { target c++11 } }
+// { dg-do compile { target { c++11 && int32 } } }
 // { dg-options -w }
 
-#include 
-
 template struct integer_sequence { };
 template
  using make_integer_sequence = integer_sequence; // 
{ dg-error "argument" }
 
-make_integer_sequence w;
-make_integer_sequence x;// { dg-message "required" }
+#if __SIZEOF_LONG_LONG__ > __SIZEOF_INT__
+make_integer_sequence w;
+#endif
+make_integer_sequence x; // { dg-message "required" }
 make_integer_sequence y; // { dg-message "required" }


Jakub


Re: C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)

2017-05-24 Thread Jason Merrill
On Wed, May 24, 2017 at 11:08 AM, Jakub Jelinek  wrote:
> On Wed, May 24, 2017 at 04:16:30PM +0200, Andreas Schwab wrote:
>> FAIL: g++.dg/ext/integer-pack2.C  -std=gnu++11 (test for excess errors)
>> Excess errors:
>> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
>>  error: overflow in constant expression [-fpermissive]
>> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
>>  error: overflow in constant expression [-fpermissive]
>
> To be precise, it fails only on 32-bit targets.

> If we at that point want some wider integer that when cast to int
> is 0 (or small enough positive number?), shall we use something like
> this, or say 1LL << (sizeof (int) * __CHAR_BIT__), or 2LL * INT_MIN,
> something else?

This is fine.

> Do we need to include ?  Or can we replace
> INT_MAX with __INT_MAX__?

__INT_MAX__ sounds good.

> Not sure about that -2147483650 for 16-bit int targets (perhaps the test can
> be guarded with int32 effective target).

Yes, restricting the test to int32 seems like the easiest fix.

Jason


Re: C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)

2017-05-24 Thread Jakub Jelinek
On Wed, May 24, 2017 at 04:16:30PM +0200, Andreas Schwab wrote:
> FAIL: g++.dg/ext/integer-pack2.C  -std=gnu++11 (test for excess errors)
> Excess errors:
> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
>  error: overflow in constant expression [-fpermissive]
> /daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48:
>  error: overflow in constant expression [-fpermissive]

To be precise, it fails only on 32-bit targets.

If we at that point want some wider integer that when cast to int
is 0 (or small enough positive number?), shall we use something like
this, or say 1LL << (sizeof (int) * __CHAR_BIT__), or 2LL * INT_MIN,
something else?  Do we need to include ?  Or can we replace
INT_MAX with __INT_MAX__?
Not sure about that -2147483650 for 16-bit int targets (perhaps the test can
be guarded with int32 effective target).

2017-05-24  Jakub Jelinek  

* g++.dg/ext/integer-pack2.C (w): Use -9223372036854775807LL - 1
instead of -9223372036854775808.

--- gcc/testsuite/g++.dg/ext/integer-pack2.C.jj 2017-05-24 11:59:01.0 
+0200
+++ gcc/testsuite/g++.dg/ext/integer-pack2.C2017-05-24 16:24:18.341421124 
+0200
@@ -7,6 +7,6 @@ template struct intege
 template
  using make_integer_sequence = integer_sequence; // 
{ dg-error "argument" }
 
-make_integer_sequence w;
+make_integer_sequence w;
 make_integer_sequence x;// { dg-message "required" }
 make_integer_sequence y; // { dg-message "required" }


Jakub


Re: C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)

2017-05-24 Thread Andreas Schwab
FAIL: g++.dg/ext/integer-pack2.C  -std=gnu++11 (test for excess errors)
Excess errors:
/daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48: 
error: overflow in constant expression [-fpermissive]
/daten/aranym/gcc/gcc-20170524/gcc/testsuite/g++.dg/ext/integer-pack2.C:10:48: 
error: overflow in constant expression [-fpermissive]

Andreas.

-- 
Andreas Schwab, SUSE Labs, sch...@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."


C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)

2017-05-23 Thread Jason Merrill
make_integer_sequence currently uses template metaprogramming to
generate a sequence of integers, which is fairly expensive at compile
time: PR 80396 asked for some built-in to speed it up.  This patch
introduces __integer_pack as a magic function taking a single integer
argument; a call to this function as the pattern of a pack expansion
produces a list of integers which can be used as arguments to a
template (or a function, but that's not the goal).

Rather than introduce a new keyword, I decided to use a FUNCTION_DECL,
which works fine.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit a5681fc17f5d79e443062d7fc652d45ba81cda0f
Author: Jason Merrill 
Date:   Fri May 12 07:45:02 2017 -0400

PR c++/80396 - built-in for make_integer_sequence.

* pt.c (builtin_pack_fn_p, builtin_pack_call_p)
(expand_integer_pack, expand_builtin_pack_call): New.
(find_parameter_packs_r): Check builtin_pack_call_p.
(check_for_bare_parameter_packs): Handle it.
(tsubst_pack_expansion): Call expand_builtin_pack_call.
(declare_integer_pack): New.
(init_template_processing): Call it.
* decl2.c (mark_used): Check builtin_pack_fn_p.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0064222..3f9bb6b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6372,6 +6372,7 @@ extern bool always_instantiate_p  (tree);
 extern void maybe_instantiate_noexcept (tree);
 extern tree instantiate_decl   (tree, bool, bool);
 extern int comp_template_parms (const_tree, const_tree);
+extern bool builtin_pack_fn_p  (tree);
 extern bool uses_parameter_packs(tree);
 extern bool template_parameter_pack_p   (const_tree);
 extern bool function_parameter_pack_p  (const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 7247b0f..85310e0 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5109,6 +5109,13 @@ mark_used (tree decl, tsubst_flags_t complain)
   if (!require_deduced_type (decl, complain))
 return false;
 
+  if (builtin_pack_fn_p (decl))
+{
+  error ("use of built-in parameter pack %qD outside of a template",
+DECL_NAME (decl));
+  return false;
+}
+
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (cp_unevaluated_operand || in_discarded_stmt)
 return true;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cdde7a0..e11c601 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15096,7 +15096,7 @@ cp_parser_template_parameter (cp_parser* parser, bool 
*is_non_type,
   *is_parameter_pack = false;
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  /* If it is `class' or `template', we have a type-parameter.  */
+  /* If it is `template', we have a type-parameter.  */
   if (token->keyword == RID_TEMPLATE)
 return cp_parser_type_parameter (parser, is_parameter_pack);
   /* If it is `class' or `typename' we do not know yet whether it is a
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f9980fe..93874cd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -215,6 +215,7 @@ static tree instantiate_alias_template (tree, tree, 
tsubst_flags_t);
 static bool complex_alias_template_p (const_tree tmpl);
 static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
 static tree canonicalize_expr_argument (tree, tsubst_flags_t);
+static tree make_argument_pack (tree);
 
 /* Make the current scope suitable for access checking when we are
processing T.  T can be FUNCTION_DECL for instantiated function
@@ -3414,6 +3415,101 @@ get_template_argument_pack_elems (const_tree t)
   return ARGUMENT_PACK_ARGS (t);
 }
 
+/* True iff FN is a function representing a built-in variadic parameter
+   pack.  */
+
+bool
+builtin_pack_fn_p (tree fn)
+{
+  if (!fn
+  || TREE_CODE (fn) != FUNCTION_DECL
+  || !DECL_IS_BUILTIN (fn))
+return false;
+
+  if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)), "__integer_pack") == 0)
+return true;
+
+  return false;
+}
+
+/* True iff CALL is a call to a function representing a built-in variadic
+   parameter pack.  */
+
+static bool
+builtin_pack_call_p (tree call)
+{
+  if (TREE_CODE (call) != CALL_EXPR)
+return false;
+  return builtin_pack_fn_p (CALL_EXPR_FN (call));
+}
+
+/* Return a TREE_VEC for the expansion of __integer_pack(HI).  */
+
+static tree
+expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
+tree in_decl)
+{
+  tree ohi = CALL_EXPR_ARG (call, 0);
+  tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl,
+  false/*fn*/, true/*int_cst*/);
+
+  if (value_dependent_expression_p (hi))
+{
+  if (hi != ohi)
+   {
+ call = copy_node (call);
+ CALL_EXPR_ARG (call, 0) = hi;
+   }
+  tree ex = make_pack_expansion (call);
+  tree vec = make_tree_vec (1);
+