Re: C++ PATCH to add __integer_pack built-in for std::make_integer_sequence (c++/80396)
On Wed, May 24, 2017 at 02:47:08PM -0400, Jason Merrill wrote: > On Wed, May 24, 2017 at 11:08 AM, Jakub Jelinekwrote: > > 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)
On Wed, May 24, 2017 at 11:08 AM, Jakub Jelinekwrote: > 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)
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)
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)
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 MerrillDate: 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); +