aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/pt.c35
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if35.C18
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);
+}