[PR c++/85634] Fix tsubst ICE
authorNathan Sidwell <nathan@acm.org>
Wed, 20 Jun 2018 14:34:06 +0000 (14:34 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 20 Jun 2018 14:34:06 +0000 (14:34 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-06/msg01237.html
PR c++/85634
* cp-tree.h (lookup_keep): Drop KEEP parm.
(lookup_list_keep): Delete.
(maybe_get_fns): Declare.
* parser.c (cp_parser_primary_expression): Call lookup_keep here.
(cp_parser_template_id): Not here ...
* decl.c (cp_finish_decl): ... nor here ...
* init.c (build_raw_new_expr): ... nor here ...
* pt.c (process_template_parm): ... nor here ...
* semantics.c (perform_koenig_lookup): Call lookup_keep.
(finish_call_expr): Not here.
* tree.c (ovl_cache): Delete.
(ovl_make, ovl_copy): No cache.
(lookup_keep): Always keep.
(lookup_list_keep): Delete.
(maybe_get_fns): New, broken out of ...
(get_fns): ... here.  Call it.
(built_min_nt_loc, build_min, build_min_non_dep): Drop lookup_keep.
(build_min_nt_call_vec): Likewise.

PR c++/85634
* g++.dg/lookup/pr85634.C: New.

From-SVN: r261802

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/pr85634.C [new file with mode: 0644]

index 430b4352ca9072262885f563fc3cfc4df72289fe..822a18acc2ea088391fc98c2ea4b20b187d0ab0b 100644 (file)
@@ -1,3 +1,25 @@
+2018-06-20  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/85634
+       * cp-tree.h (lookup_keep): Drop KEEP parm.
+       (lookup_list_keep): Delete.
+       (maybe_get_fns): Declare.
+       * parser.c (cp_parser_primary_expression): Call lookup_keep here.
+       (cp_parser_template_id): Not here ...
+       * decl.c (cp_finish_decl): ... nor here ...
+       * init.c (build_raw_new_expr): ... nor here ...
+       * pt.c (process_template_parm): ... nor here ...
+       * semantics.c (perform_koenig_lookup): Call lookup_keep.
+       (finish_call_expr): Not here.
+       * tree.c (ovl_cache): Delete.
+       (ovl_make, ovl_copy): No cache.
+       (lookup_keep): Always keep.
+       (lookup_list_keep): Delete.
+       (maybe_get_fns): New, broken out of ...
+       (get_fns): ... here.  Call it.
+       (built_min_nt_loc, build_min, build_min_non_dep): Drop lookup_keep.
+       (build_min_nt_call_vec): Likewise.
+
 2018-06-19  Jason Merrill  <jason@redhat.com>
 
        * cp-tree.h (CONSTRUCTOR_NO_IMPLICIT_ZERO): Remove.
index f0aae66772394d28423081bc9aaa6e0f77bf2e12..ee9242f9313eac9b6d504e5f0c6974c4d8cafea1 100644 (file)
@@ -7094,11 +7094,11 @@ extern void lookup_mark                         (tree lookup, bool val);
 extern tree lookup_add                         (tree fns, tree lookup);
 extern tree lookup_maybe_add                   (tree fns, tree lookup,
                                                 bool deduping);
-extern void lookup_keep                                (tree lookup, bool keep);
-extern void lookup_list_keep                   (tree list, bool keep);
+extern void lookup_keep                                (tree lookup);
 extern int is_overloaded_fn                    (tree) ATTRIBUTE_PURE;
 extern bool really_overloaded_fn               (tree) ATTRIBUTE_PURE;
 extern tree dependent_name                     (tree);
+extern tree maybe_get_fns                      (tree) ATTRIBUTE_PURE;
 extern tree get_fns                            (tree) ATTRIBUTE_PURE;
 extern tree get_first_fn                       (tree) ATTRIBUTE_PURE;
 extern tree ovl_scope                          (tree);
index 90714cce0626d2f924777a292d7712ee2b5b213b..f12a01b28f555acbf099e3bc5a0906b8d223c376 100644 (file)
@@ -6973,11 +6973,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
        }
 
       if (init)
-       {
-         if (TREE_CODE (init) == TREE_LIST)
-           lookup_list_keep (init, true);
-         DECL_INITIAL (decl) = init;
-       }
+       DECL_INITIAL (decl) = init;
+
       if (dep_init)
        {
          retrofit_lang_decl (decl);
index 57697d67035481d22edd01f5c41f576293dcd73e..810a776a3c8a2a3df712dce7ab36db77b27bcaf6 100644 (file)
@@ -2403,12 +2403,7 @@ build_raw_new_expr (vec<tree, va_gc> *placement, tree type, tree nelts,
   else if (init->is_empty ())
     init_list = void_node;
   else
-    {
-      init_list = build_tree_list_vec (init);
-      for (tree v = init_list; v; v = TREE_CHAIN (v))
-       if (TREE_CODE (TREE_VALUE (v)) == OVERLOAD)
-         lookup_keep (TREE_VALUE (v), true);
-    }
+    init_list = build_tree_list_vec (init);
 
   new_expr = build4 (NEW_EXPR, build_pointer_type (type),
                     build_tree_list_vec (placement), type, nelts,
index c6206fc353ce287506a99c0c5c75f7350c9ec963..b618485ab2b6f281ee529ad7ee928e06cb3bdadd 100644 (file)
@@ -5603,6 +5603,14 @@ cp_parser_primary_expression (cp_parser *parser,
              }
          }
 
+       if (processing_template_decl)
+         if (tree fns = maybe_get_fns (decl))
+           /* It's too difficult to mark ths in all the places where
+              we know for sure we need to keep the lookup, so do it
+              now.  The cost is extra GC to recycle the lookups
+              resolved at parse time.  */
+           lookup_keep (fns);
+
        decl = (finish_id_expression
                (id_expression, decl, parser->scope,
                 idk,
@@ -15989,11 +15997,6 @@ cp_parser_template_id (cp_parser *parser,
       token->type = CPP_TEMPLATE_ID;
       token->location = combined_loc;
 
-      /* We must mark the lookup as kept, so we don't throw it away on
-        the first parse.  */
-      if (is_overloaded_fn (template_id))
-       lookup_keep (get_fns (template_id), true);
-
       /* Retrieve any deferred checks.  Do not pop this access checks yet
         so the memory will not be reclaimed during token replacing below.  */
       token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
index 3386385b3f88dbd02e534e92883e0c9faf357679..be42b20df76df0c9a76b4a0129d03a5d8904ce2d 100644 (file)
@@ -4431,9 +4431,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
 
   pushdecl (decl);
 
-  if (defval && TREE_CODE (defval) == OVERLOAD)
-    lookup_keep (defval, true);
-  
   /* Build the parameter node linking the parameter declaration,
      its default argument (if any), and its constraints (if any). */
   parm = build_tree_list (defval, parm);
index 2356940a6bbd943c510e8491321b8b8cc2f7a936..38b7b66e214859bffafc4070d12dfc148b31cf38 100644 (file)
@@ -2325,6 +2325,11 @@ perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
          else
            fn = identifier;
        }
+      else if (TREE_CODE (fn) == OVERLOAD && processing_template_decl)
+       /* FIXME: We shouldn't really need to mark the lookup here, as
+          resolving the (non-dependent) call should save the single
+          function we resolve to.  Related to PR c++/83529.  */
+       lookup_keep (fn);
     }
 
   if (fn && template_id && fn != error_mark_node)
@@ -2385,10 +2390,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
          SET_EXPR_LOCATION (result, cp_expr_loc_or_loc (fn, input_location));
          KOENIG_LOOKUP_P (result) = koenig_p;
          if (is_overloaded_fn (fn))
-           {
-             fn = get_fns (fn);
-             lookup_keep (fn, true);
-           }
+           fn = get_fns (fn);
 
          if (cfun)
            {
@@ -2575,10 +2577,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
       result = convert_from_reference (result);
     }
 
-  /* Free or retain OVERLOADs from lookup.  */
-  if (is_overloaded_fn (orig_fn))
-    lookup_keep (get_fns (orig_fn), processing_template_decl);
-
   return result;
 }
 
index 4e91dbb75dac1c7206c2f98f55fb97c69c97add8..e7bd79b6276b7d30c5269f15d02332cf3cc68407 100644 (file)
@@ -2131,25 +2131,12 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual)
   return build_cp_fntype_variant (type, rqual, raises, late);
 }
 
-/* Cache of free ovl nodes.  Uses OVL_FUNCTION for chaining.  */
-static GTY((deletable)) tree ovl_cache;
-
 /* Make a raw overload node containing FN.  */
 
 tree
 ovl_make (tree fn, tree next)
 {
-  tree result = ovl_cache;
-
-  if (result)
-    {
-      ovl_cache = OVL_FUNCTION (result);
-      /* Zap the flags.  */
-      memset (result, 0, sizeof (tree_base));
-      TREE_SET_CODE (result, OVERLOAD);
-    }
-  else
-    result = make_node (OVERLOAD);
+  tree result = make_node (OVERLOAD);
 
   if (TREE_CODE (fn) == OVERLOAD)
     OVL_NESTED_P (result) = true;
@@ -2164,17 +2151,7 @@ ovl_make (tree fn, tree next)
 static tree
 ovl_copy (tree ovl)
 {
-  tree result = ovl_cache;
-
-  if (result)
-    {
-      ovl_cache = OVL_FUNCTION (result);
-      /* Zap the flags.  */
-      memset (result, 0, sizeof (tree_base));
-      TREE_SET_CODE (result, OVERLOAD);
-    }
-  else
-    result = make_node (OVERLOAD);
+  tree result = make_node (OVERLOAD);
 
   gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl));
   TREE_TYPE (result) = TREE_TYPE (ovl);
@@ -2413,44 +2390,22 @@ ovl_used (tree ovl)
     }
 }
 
-/* If KEEP is true, preserve the contents of a lookup so that it is
-   available for a later instantiation.  Otherwise release the LOOKUP
-   nodes for reuse.  */
+/* Preserve the contents of a lookup so that it is available for a
+   later instantiation.  */
 
 void
-lookup_keep (tree lookup, bool keep)
+lookup_keep (tree lookup)
 {
   for (;
        lookup && TREE_CODE (lookup) == OVERLOAD
         && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup);
        lookup = OVL_CHAIN (lookup))
-    if (keep)
-      {
-       OVL_USED_P (lookup) = true;
-       ovl_used (OVL_FUNCTION (lookup));
-      }
-    else
-      {
-       OVL_FUNCTION (lookup) = ovl_cache;
-       ovl_cache = lookup;
-      }
-
-  if (keep)
-    ovl_used (lookup);
-}
-
-/* LIST is a TREE_LIST whose TREE_VALUEs may be OVERLOADS that need
-   keeping, or may be ignored.  */
-
-void
-lookup_list_keep (tree list, bool keep)
-{
-  for (; list; list = TREE_CHAIN (list))
     {
-      tree v = TREE_VALUE (list);
-      if (TREE_CODE (v) == OVERLOAD)
-       lookup_keep (v, keep);
+      OVL_USED_P (lookup) = true;
+      ovl_used (OVL_FUNCTION (lookup));
     }
+
+  ovl_used (lookup);
 }
 
 /* Returns nonzero if X is an expression for a (possibly overloaded)
@@ -2505,10 +2460,11 @@ really_overloaded_fn (tree x)
   return is_overloaded_fn (x) == 2;
 }
 
-/* Get the overload set FROM refers to.  */
+/* Get the overload set FROM refers to.  Returns NULL if it's not an
+   overload set.  */
 
 tree
-get_fns (tree from)
+maybe_get_fns (tree from)
 {
   /* A baselink is also considered an overloaded function.  */
   if (TREE_CODE (from) == OFFSET_REF
@@ -2518,9 +2474,23 @@ get_fns (tree from)
     from = BASELINK_FUNCTIONS (from);
   if (TREE_CODE (from) == TEMPLATE_ID_EXPR)
     from = TREE_OPERAND (from, 0);
-  gcc_assert (TREE_CODE (from) == OVERLOAD
-             || TREE_CODE (from) == FUNCTION_DECL);
-  return from;
+
+  if (TREE_CODE (from) == OVERLOAD
+      || TREE_CODE (from) == FUNCTION_DECL)
+    return from;
+
+  return NULL;
+}
+
+/* FROM refers to an overload set.  Return that set (or die).  */
+
+tree
+get_fns (tree from)
+{
+  tree res = maybe_get_fns (from);
+
+  gcc_assert (res);
+  return res;
 }
 
 /* Return the first function of the overload set FROM refers to.  */
@@ -3306,12 +3276,7 @@ build_min_nt_loc (location_t loc, enum tree_code code, ...)
   length = TREE_CODE_LENGTH (code);
 
   for (i = 0; i < length; i++)
-    {
-      tree x = va_arg (p, tree);
-      TREE_OPERAND (t, i) = x;
-      if (x && TREE_CODE (x) == OVERLOAD)
-       lookup_keep (x, true);
-    }
+    TREE_OPERAND (t, i) = va_arg (p, tree);
 
   va_end (p);
   return t;
@@ -3339,21 +3304,12 @@ build_min (enum tree_code code, tree tt, ...)
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
-      if (x)
-       {
-         if (!TYPE_P (x) && TREE_SIDE_EFFECTS (x))
-           TREE_SIDE_EFFECTS (t) = 1;
-         if (TREE_CODE (x) == OVERLOAD)
-           lookup_keep (x, true);
-       }
+      if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
+       TREE_SIDE_EFFECTS (t) = 1;
     }
 
   va_end (p);
 
-  if (code == CAST_EXPR)
-    /* The single operand is a TREE_LIST, which we have to check.  */
-    lookup_list_keep (TREE_OPERAND (t, 0), true);
-
   return t;
 }
 
@@ -3382,12 +3338,7 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...)
   TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
 
   for (i = 0; i < length; i++)
-    {
-      tree x = va_arg (p, tree);
-      TREE_OPERAND (t, i) = x;
-      if (x && TREE_CODE (x) == OVERLOAD)
-       lookup_keep (x, true);
-    }
+    TREE_OPERAND (t, i) = va_arg (p, tree);
 
   if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
     /* This should not be considered a COMPOUND_EXPR, because it
@@ -3410,11 +3361,8 @@ build_min_nt_call_vec (tree fn, vec<tree, va_gc> *args)
   CALL_EXPR_FN (ret) = fn;
   CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
   FOR_EACH_VEC_SAFE_ELT (args, ix, t)
-    {
-      CALL_EXPR_ARG (ret, ix) = t;
-      if (TREE_CODE (t) == OVERLOAD)
-       lookup_keep (t, true);
-    }
+    CALL_EXPR_ARG (ret, ix) = t;
+
   return ret;
 }
 
index a2c5eabd5a6efcaae2df3cd016eb8a1560c41ac5..25a7caaebe440ac4012b0c5d679c47329047ef55 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-20  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/85634
+       * g++.dg/lookup/pr85634.C: New.
+
 2018-06-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/aarch64/ldp_stp_q.c: New test.
diff --git a/gcc/testsuite/g++.dg/lookup/pr85634.C b/gcc/testsuite/g++.dg/lookup/pr85634.C
new file mode 100644 (file)
index 0000000..e3b3682
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/85634 ICE managing lookup set
+
+namespace N {
+  template <class T> void Foo (T *const &);
+}
+
+using namespace N;
+
+template<class T> void Foo (const T &);
+
+
+template <class T>
+void Frob()
+{
+  void (*op)(const T&) = Foo;
+}
+
+template void Frob<int *>();