diff options
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C | 18 |
3 files changed, 56 insertions, 2 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ceb5359..a82747c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -493,6 +493,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) OVL_NESTED_P (in OVERLOAD) DECL_MODULE_EXPORT_P (in _DECL) + PACK_EXPANSION_FORCE_EXTRA_ARGS_P (in *_PACK_EXPANSION) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). @@ -3903,6 +3904,10 @@ struct GTY(()) lang_decl { /* True iff this pack expansion is for auto... in lambda init-capture. */ #define PACK_EXPANSION_AUTO_P(NODE) TREE_LANG_FLAG_2 (NODE) +/* True if we must use PACK_EXPANSION_EXTRA_ARGS and avoid partial + instantiation of this pack expansion. */ +#define PACK_EXPANSION_FORCE_EXTRA_ARGS_P(NODE) TREE_LANG_FLAG_3 (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/pt.c b/gcc/cp/pt.c index 1b81501..224dd9e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3855,6 +3855,18 @@ expand_builtin_pack_call (tree call, tree args, tsubst_flags_t complain, return NULL_TREE; } +/* Return true if the tree T has the extra args mechanism for + avoiding partial instantiation. */ + +static bool +has_extra_args_mechanism_p (const_tree t) +{ + return (PACK_EXPANSION_P (t) /* PACK_EXPANSION_EXTRA_ARGS */ + || TREE_CODE (t) == REQUIRES_EXPR /* REQUIRES_EXPR_EXTRA_ARGS */ + || (TREE_CODE (t) == IF_STMT + && IF_STMT_CONSTEXPR_P (t))); /* IF_STMT_EXTRA_ARGS */ +} + /* Structure used to track the progress of find_parameter_packs_r. */ struct find_parameter_pack_data { @@ -3867,6 +3879,9 @@ struct find_parameter_pack_data /* True iff we're making a type pack expansion. */ bool type_pack_expansion_p; + + /* True iff we found a subtree that has the extra args mechanism. */ + bool found_extra_args_tree_p = false; }; /* Identifies all of the argument packs that occur in a template @@ -3968,6 +3983,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs); } + if (has_extra_args_mechanism_p (t) && !PACK_EXPANSION_P (t)) + ppd->found_extra_args_tree_p = true; + if (TYPE_P (t)) cp_walk_tree (&TYPE_CONTEXT (t), &find_parameter_packs_r, ppd, ppd->visited); @@ -4229,6 +4247,14 @@ make_pack_expansion (tree arg, tsubst_flags_t complain) PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs; PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p (); + if (ppd.found_extra_args_tree_p) + /* If the pattern of this pack expansion contains a subtree that has + the extra args mechanism for avoiding partial instantiation, then + force this pack expansion to also use extra args. Otherwise + partial instantiation of this pack expansion may not lower the + level of some parameter packs within the pattern, which would + confuse tsubst_pack_expansion later (PR101764). */ + PACK_EXPANSION_FORCE_EXTRA_ARGS_P (result) = true; return result; } @@ -12405,10 +12431,15 @@ make_argument_pack_select (tree arg_pack, unsigned index) substitution. */ static bool -use_pack_expansion_extra_args_p (tree parm_packs, +use_pack_expansion_extra_args_p (tree t, + tree parm_packs, int arg_pack_len, bool has_empty_arg) { + if (has_empty_arg + && PACK_EXPANSION_FORCE_EXTRA_ARGS_P (t)) + return true; + /* If one pack has an expansion and another pack has a normal argument or if one pack has an empty argument and an another one hasn't then tsubst_pack_expansion cannot perform the @@ -13161,7 +13192,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, /* We cannot expand this expansion expression, because we don't have all of the argument packs we need. */ - if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs)) + if (use_pack_expansion_extra_args_p (t, packs, len, unsubstituted_packs)) { /* We got some full packs, but we can't substitute them in until we have values for all the packs. So remember these until then. */ diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C new file mode 100644 index 0000000..b1248fe --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C @@ -0,0 +1,18 @@ +// PR c++/101764 +// { dg-do compile { target c++17 } } + +void g(...); + +template<class> +auto f() { + return [](auto... ts) { + g([] { if constexpr (sizeof(ts)); }...); +#if __cpp_concepts + g(requires { decltype(ts){0}; }...); +#endif + }; +} + +int main() { + f<int>()('a', true); +} |