c++: Fix use of local in constexpr if.
extract_local_specs wasn't finding the mention of 'an' as a template argument because we weren't walking into template arguments. So here I changed cp_walk_subtrees to do so--only walking into template arguments in the spelling of the type or expression, not any hidden behind typedefs. The change to use typedef_variant_p avoids looking through typedefs spelled with 'typedef' as well as those spelled with 'using'. And then I removed some now-redundant code for walking into template arguments in a couple of walk_tree callbacks. PR c++/92654 * tree.c (cp_walk_subtrees): Walk into type template arguments. * cp-tree.h (TYPE_TEMPLATE_INFO_MAYBE_ALIAS): Use typedef_variant_p instead of TYPE_ALIAS_P. * pt.c (push_template_decl_real): Likewise. (find_parameter_packs_r): Likewise. Remove dead code. * error.c (find_typenames_r): Remove dead code.
This commit is contained in:
parent
c8dd2446f5
commit
1e042b396e
@ -1,3 +1,13 @@
|
||||
2020-02-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/92654
|
||||
* tree.c (cp_walk_subtrees): Walk into type template arguments.
|
||||
* cp-tree.h (TYPE_TEMPLATE_INFO_MAYBE_ALIAS): Use typedef_variant_p
|
||||
instead of TYPE_ALIAS_P.
|
||||
* pt.c (push_template_decl_real): Likewise.
|
||||
(find_parameter_packs_r): Likewise. Remove dead code.
|
||||
* error.c (find_typenames_r): Remove dead code.
|
||||
|
||||
2020-02-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/92517
|
||||
|
@ -3482,7 +3482,7 @@ struct GTY(()) lang_decl {
|
||||
for the alias template (if any). Otherwise behave as
|
||||
TYPE_TEMPLATE_INFO. */
|
||||
#define TYPE_TEMPLATE_INFO_MAYBE_ALIAS(NODE) \
|
||||
(TYPE_ALIAS_P (NODE) \
|
||||
(typedef_variant_p (NODE) \
|
||||
? TYPE_ALIAS_TEMPLATE_INFO (NODE) \
|
||||
: TYPE_TEMPLATE_INFO (NODE))
|
||||
|
||||
|
@ -1526,12 +1526,6 @@ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
|
||||
if (mv && (mv == *tp || !d->p_set->add (mv)))
|
||||
vec_safe_push (d->typenames, mv);
|
||||
|
||||
/* Search into class template arguments, which cp_walk_subtrees
|
||||
doesn't do. */
|
||||
if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
|
||||
cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
|
||||
data, d->p_set);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
40
gcc/cp/pt.c
40
gcc/cp/pt.c
@ -3818,9 +3818,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
(struct find_parameter_pack_data*)data;
|
||||
bool parameter_pack_p = false;
|
||||
|
||||
/* Handle type aliases/typedefs. */
|
||||
if (TYPE_ALIAS_P (t))
|
||||
/* Don't look through typedefs; we are interested in whether a
|
||||
parameter pack is actually written in the expression/type we're
|
||||
looking at, not the target type. */
|
||||
if (TYPE_P (t) && typedef_variant_p (t))
|
||||
{
|
||||
/* But do look at arguments for an alias template. */
|
||||
if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
|
||||
cp_walk_tree (&TI_ARGS (tinfo),
|
||||
&find_parameter_packs_r,
|
||||
@ -3903,27 +3906,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
&find_parameter_packs_r, ppd, ppd->visited);
|
||||
|
||||
/* This switch statement will return immediately if we don't find a
|
||||
parameter pack. */
|
||||
parameter pack. ??? Should some of these be in cp_walk_subtrees? */
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
return NULL_TREE;
|
||||
|
||||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||||
/* Check the template itself. */
|
||||
cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
|
||||
&find_parameter_packs_r, ppd, ppd->visited);
|
||||
/* Check the template arguments. */
|
||||
cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
|
||||
ppd->visited);
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
case TEMPLATE_TEMPLATE_PARM:
|
||||
return NULL_TREE;
|
||||
|
||||
case PARM_DECL:
|
||||
return NULL_TREE;
|
||||
|
||||
case DECL_EXPR:
|
||||
@ -3932,20 +3921,6 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
case RECORD_TYPE:
|
||||
if (TYPE_PTRMEMFUNC_P (t))
|
||||
return NULL_TREE;
|
||||
/* Fall through. */
|
||||
|
||||
case UNION_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
if (TYPE_TEMPLATE_INFO (t))
|
||||
cp_walk_tree (&TYPE_TI_ARGS (t),
|
||||
&find_parameter_packs_r, ppd, ppd->visited);
|
||||
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
case TEMPLATE_DECL:
|
||||
if (!DECL_TEMPLATE_TEMPLATE_PARM_P (t))
|
||||
return NULL_TREE;
|
||||
@ -5794,8 +5769,7 @@ push_template_decl_real (tree decl, bool is_friend)
|
||||
if (check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type)))
|
||||
TYPE_RAISES_EXCEPTIONS (type) = NULL_TREE;
|
||||
}
|
||||
else if (check_for_bare_parameter_packs ((TREE_CODE (decl) == TYPE_DECL
|
||||
&& TYPE_DECL_ALIAS_P (decl))
|
||||
else if (check_for_bare_parameter_packs (is_typedef_decl (decl)
|
||||
? DECL_ORIGINAL_TYPE (decl)
|
||||
: TREE_TYPE (decl)))
|
||||
{
|
||||
|
@ -4918,6 +4918,11 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
|
||||
} \
|
||||
while (0)
|
||||
|
||||
if (TYPE_P (*tp))
|
||||
/* Walk into template args without looking through typedefs. */
|
||||
if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (*tp))
|
||||
WALK_SUBTREE (TI_ARGS (ti));
|
||||
|
||||
/* Not one of the easy cases. We must explicitly go through the
|
||||
children. */
|
||||
result = NULL_TREE;
|
||||
|
12
gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda2.C
Normal file
12
gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda2.C
Normal file
@ -0,0 +1,12 @@
|
||||
// PR c++/92654
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
template <unsigned long> struct C;
|
||||
template <auto I>
|
||||
void am() {
|
||||
[](auto an)
|
||||
{
|
||||
if constexpr (C<an>::ap) ; // { dg-error "constant" }
|
||||
}(42);
|
||||
}
|
||||
void fn() { am<42>(); }
|
Loading…
Reference in New Issue
Block a user