From 062f0f96a1c673821d7bde72bd6d517be9fd2ec1 Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 19 Nov 2015 22:29:08 +0000 Subject: [PATCH] PR c++/68422 * cp-tree.h (PACK_EXPANSION_SIZEOF_P): New. * parser.c (cp_parser_sizeof_pack): Set it. * pt.c (tsubst_copy) [SIZEOF_EXPR]: Likewise. (tsubst_pack_expansion): Improve T... shortcut for expression packs. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230629 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/cp-tree.h | 4 ++++ gcc/cp/parser.c | 1 + gcc/cp/pt.c | 17 +++++++++++++++-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d7804a0..c4b7614 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2015-11-19 Jason Merrill + + PR c++/68422 + * cp-tree.h (PACK_EXPANSION_SIZEOF_P): New. + * parser.c (cp_parser_sizeof_pack): Set it. + * pt.c (tsubst_copy) [SIZEOF_EXPR]: Likewise. + (tsubst_pack_expansion): Improve T... shortcut for expression packs. + 2015-11-19 Ryan Burn PR c++/68396 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 160bf1e..14ea119 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -98,6 +98,7 @@ c-common.h, not after. DECLTYPE_FOR_INIT_CAPTURE (in DECLTYPE_TYPE) CONSTRUCTOR_NO_IMPLICIT_ZERO (in CONSTRUCTOR) TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO) + PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION) 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -3200,6 +3201,9 @@ extern void decl_shadowed_for_var_insert (tree, tree); /* True iff this pack expansion is within a function context. */ #define PACK_EXPANSION_LOCAL_P(NODE) TREE_LANG_FLAG_0 (NODE) +/* True iff this pack expansion is for sizeof.... */ +#define PACK_EXPANSION_SIZEOF_P(NODE) TREE_LANG_FLAG_1 (NODE) + /* True iff the wildcard can match a template parameter pack. */ #define WILDCARD_PACK_P(NODE) TREE_LANG_FLAG_0 (NODE) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 30cde0b..24ed404 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -25868,6 +25868,7 @@ cp_parser_sizeof_pack (cp_parser *parser) else if (TREE_CODE (expr) == CONST_DECL) expr = DECL_INITIAL (expr); expr = make_pack_expansion (expr); + PACK_EXPANSION_SIZEOF_P (expr) = true; if (paren) cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b4a5e71..5868be2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10868,14 +10868,26 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, } } - /* If the expansion is just T..., return the matching argument pack. */ + /* If the expansion is just T..., return the matching argument pack, unless + we need to call convert_from_reference on all the elements. This is an + important optimization; see c++/68422. */ if (!unsubstituted_packs && TREE_PURPOSE (packs) == pattern) { tree args = ARGUMENT_PACK_ARGS (TREE_VALUE (packs)); + /* Types need no adjustment, nor does sizeof..., and if we still have + some pack expansion args we won't do anything yet. */ if (TREE_CODE (t) == TYPE_PACK_EXPANSION + || PACK_EXPANSION_SIZEOF_P (t) || pack_expansion_args_count (args)) return args; + /* Also optimize expression pack expansions if we can tell that the + elements won't have reference type. */ + tree type = TREE_TYPE (pattern); + if (type && TREE_CODE (type) != REFERENCE_TYPE + && !PACK_EXPANSION_P (type) + && !WILDCARD_TYPE_P (type)) + return args; /* Otherwise use the normal path so we get convert_from_reference. */ } @@ -13940,7 +13952,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) { - tree expanded, op = TREE_OPERAND (t, 0); int len = 0; @@ -13966,6 +13977,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) { if (TREE_CODE (expanded) == TREE_VEC) expanded = TREE_VEC_ELT (expanded, len - 1); + else + PACK_EXPANSION_SIZEOF_P (expanded) = true; if (TYPE_P (expanded)) return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, -- 2.7.4