diff mbox

[C++] PR c++/80891 #3

Message ID e8dccfa2-0e17-b6df-efdf-6250f7fed886@acm.org
State New
Headers show

Commit Message

Nathan Sidwell May 29, 2017, 12:56 p.m. UTC
This patch fixes the 3rd testcase in 80891.  Here we were squirelling 
away overload lookup results in template definitions, but failing to 
mark them as used.  tsubst rightly asserted.

Fixed by adding calls to lookup_mark in the relevant expr build functions.

build_nt_call_vec is in the common core, but only ever called from the 
c++ FE.  This patch replaces those calls with a C++-specific builder, 
that does the marking.  I left the common one in gcc/tree.c alone, but 
perhaps it should be removed as unneeded?

nathan
diff mbox

Patch

2017-05-29  Nathan Sidwell  <nathan@acm.org>

	PR c++/80891 (#3)
	* cp-tree.h (build_min_nt_call_vec): Declare.
	* decl.c (build_offset_ref_call_from_tree): Call it.
	* parser.c (cp_parser_postfix_expression): Likewise.
	* pt.c (tsubst_copy_and_build): Likewise.
	* semantics.c (finish_call_expr): Likewise.
	* tree.c (build_min_nt_loc): Keep unresolved lookups.
	(build_min): Likewise.
	(build_min_non_dep): Likewise.
	(build_min_non_dep_call_vec): Likewise.
	(build_min_nt_call_vec): New.

	PR c++/80891 (#3)
	* g++.dg/lookup/pr80891-3.C: New.

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 248569)
+++ cp/cp-tree.h	(working copy)
@@ -6891,6 +6891,7 @@  extern tree build_min_nt_loc			(location
 						 ...);
 extern tree build_min_non_dep			(enum tree_code, tree, ...);
 extern tree build_min_non_dep_op_overload	(enum tree_code, tree, tree, ...);
+extern tree build_min_nt_call_vec (tree, vec<tree, va_gc> *);
 extern tree build_min_non_dep_call_vec		(tree, tree, vec<tree, va_gc> *);
 extern vec<tree, va_gc>* vec_copy_and_insert    (vec<tree, va_gc>*, tree, unsigned);
 extern tree build_cplus_new			(tree, tree, tsubst_flags_t);
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 248569)
+++ cp/decl2.c	(working copy)
@@ -4891,7 +4891,7 @@  build_offset_ref_call_from_tree (tree fn
 		  || TREE_CODE (fn) == MEMBER_REF);
       if (type_dependent_expression_p (fn)
 	  || any_type_dependent_arguments_p (*args))
-	return build_nt_call_vec (fn, *args);
+	return build_min_nt_call_vec (fn, *args);
 
       orig_args = make_tree_vector_copy (*args);
 
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 248569)
+++ cp/parser.c	(working copy)
@@ -6952,7 +6952,7 @@  cp_parser_postfix_expression (cp_parser
 		  {
 		    maybe_generic_this_capture (instance, fn);
 		    postfix_expression
-		      = build_nt_call_vec (postfix_expression, args);
+		      = build_min_nt_call_vec (postfix_expression, args);
 		    release_tree_vector (args);
 		    break;
 		  }
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 248569)
+++ cp/pt.c	(working copy)
@@ -17389,7 +17389,7 @@  tsubst_copy_and_build (tree t,
 			&& TREE_CODE (fn) != FIELD_DECL)
 		    || type_dependent_expression_p (fn)
 		    || any_type_dependent_arguments_p (call_args)))
-	      ret = build_nt_call_vec (function, call_args);
+	      ret = build_min_nt_call_vec (function, call_args);
 	    else if (!BASELINK_P (fn))
 	      ret = finish_call_expr (function, &call_args,
 				       /*disallow_virtual=*/false,
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 248569)
+++ cp/semantics.c	(working copy)
@@ -2322,7 +2322,7 @@  finish_call_expr (tree fn, vec<tree, va_
       if (type_dependent_expression_p (fn)
 	  || any_type_dependent_arguments_p (*args))
 	{
-	  result = build_nt_call_vec (fn, *args);
+	  result = build_min_nt_call_vec (fn, *args);
 	  SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
 	  KOENIG_LOOKUP_P (result) = koenig_p;
 	  if (is_overloaded_fn (fn))
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 248570)
+++ cp/tree.c	(working copy)
@@ -3216,13 +3216,14 @@  build_min_nt_loc (location_t loc, enum t
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
+      if (x && TREE_CODE (x) == OVERLOAD)
+	lookup_keep (x, true);
     }
 
   va_end (p);
   return t;
 }
 
-
 /* Similar to `build', but for template definitions.  */
 
 tree
@@ -3245,8 +3246,13 @@  build_min (enum tree_code code, tree tt,
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
-      if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x))
-	TREE_SIDE_EFFECTS (t) = 1;
+      if (x)
+	{
+	  if (!TYPE_P (x) && TREE_SIDE_EFFECTS (x))
+	    TREE_SIDE_EFFECTS (t) = 1;
+	  if (TREE_CODE (x) == OVERLOAD)
+	    lookup_keep (x, true);
+	}
     }
 
   va_end (p);
@@ -3281,6 +3287,8 @@  build_min_non_dep (enum tree_code code,
     {
       tree x = va_arg (p, tree);
       TREE_OPERAND (t, i) = x;
+      if (x && TREE_CODE (x) == OVERLOAD)
+	lookup_keep (x, true);
     }
 
   if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR)
@@ -3292,14 +3300,34 @@  build_min_non_dep (enum tree_code code,
   return convert_from_reference (t);
 }
 
-/* Similar to `build_nt_call_vec', but for template definitions of
+/* Similar to build_min_nt, but call expressions  */
+
+tree
+build_min_nt_call_vec (tree fn, vec<tree, va_gc> *args)
+{
+  tree ret, t;
+  unsigned int ix;
+
+  ret = build_vl_exp (CALL_EXPR, vec_safe_length (args) + 3);
+  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);
+    }
+  return ret;
+}
+
+/* Similar to `build_min_nt_call_vec', but for template definitions of
    non-dependent expressions. NON_DEP is the non-dependent expression
    that has been built.  */
 
 tree
 build_min_non_dep_call_vec (tree non_dep, tree fn, vec<tree, va_gc> *argvec)
 {
-  tree t = build_nt_call_vec (fn, argvec);
+  tree t = build_min_nt_call_vec (fn, argvec);
   if (REFERENCE_REF_P (non_dep))
     non_dep = TREE_OPERAND (non_dep, 0);
   TREE_TYPE (t) = TREE_TYPE (non_dep);
Index: testsuite/g++.dg/lookup/pr80891-3.C
===================================================================
--- testsuite/g++.dg/lookup/pr80891-3.C	(revision 0)
+++ testsuite/g++.dg/lookup/pr80891-3.C	(working copy)
@@ -0,0 +1,26 @@ 
+// PR c++/80891 part 3
+// We were failing to mark OVERLOADS held in template definitions as
+// immutable in non-call contexts.
+
+namespace std {
+  int endl();
+}
+
+using std::endl;
+
+template <class RealType> void test_spots(RealType)
+{
+  using namespace std;
+  RealType a;
+  a << endl;
+}
+
+template <typename T>
+void operator<< (T, int (&)());
+
+struct Q {};
+void test_maintest_method()
+{
+  Q q;
+  test_spots(q);
+}