c++: Fix use of local in constexpr if.
authorJason Merrill <jason@redhat.com>
Fri, 7 Feb 2020 15:31:30 +0000 (10:31 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 7 Feb 2020 19:20:46 +0000 (14:20 -0500)
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.

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda2.C [new file with mode: 0644]

index df7d2ca0587c6b0d2f5082c80a10d74bbb4f98c8..580b7665c679c0c3b2887f46da244d3be781bbd6 100644 (file)
@@ -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
index b8035b4360d9aee18864a89610ffad3f5172af96..c46d1e92b3b0fbcc4f3cbf1d6e97657f6644c96e 100644 (file)
@@ -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))
 
index 973b3034e121aa76464dd9c0ea205c51f6a43413..ab8638fbaec638cfaacb08edb78aa4e12bd31178 100644 (file)
@@ -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;
 }
 
index 01bade85cdfff48a3d327b6227d1441fd1326b47..2fb52caa5d44c85d6a52124d35dd8d1b390724ac 100644 (file)
@@ -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)))
     {
index 21f733af48629d8577011cd0d2c06e705e2ebd6b..fda630790a242e75c5fdbb323bc124782caf52cb 100644 (file)
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda2.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if-lambda2.C
new file mode 100644 (file)
index 0000000..fb26ac7
--- /dev/null
@@ -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>(); }