diff mbox

[C++] PR 65340

Message ID 5508DCFB.7020103@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 18, 2015, 2:03 a.m. UTC
Hi,

On 03/18/2015 01:11 AM, Jason Merrill wrote:
> On 03/17/2015 01:09 PM, Paolo Carlini wrote:
>> -  require_deduced_type (decl);
>> +  if (complain & tf_error)
>> +    require_deduced_type (decl);
>
> I think we want to return false if there's a problem here so that we 
> don't just silently accept this in SFINAE context.  So probably we 
> want to replace the call with an inlined form like earlier in mark_used.
Indeed, I was a bit nervous about that, should have asked... Anyway, the 
below is finishing testing.
> Are there other places that still need to pass complain to mark_used?
Well, if we are talking about functions getting a tsubst_flags_t and 
*not* passing it down to mark_used, there are quite a few - see 
attached. I didn't feel like raising the issue at this time because in 
all those cases, at variance with the specific case we are changing for 
the bug, the return value of mark_used is *not* checked, thus is we 
suppress the errors in SFINAE context we would like to also add a check 
and return early, but in general, doing that when we are *outside* 
SFINAE changes what happens during error recovery, thus it seems a bit 
risky fiddling with those right now...

Thanks,
Paolo.

/////////////////

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 221481)
+++ cp/call.c	(working copy)
@@ -5968,7 +5968,7 @@ build_op_delete_call (enum tree_code code, tree ad
 	  argarray[0] = addr;
 	  for (i = 1; i < nargs; i++)
 	    argarray[i] = CALL_EXPR_ARG (placement, i);
-	  mark_used (fn);
+	  mark_used (fn, complain);
 	  return build_cxx_call (fn, nargs, argarray, complain);
 	}
       else
@@ -7390,7 +7390,7 @@ build_over_call (struct z_candidate *cand, int fla
 	 the implementation elided its use.  */
       if (!trivial || DECL_DELETED_FN (fn))
 	{
-	  mark_used (fn);
+	  mark_used (fn, complain);
 	  already_used = true;
 	}
 
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 221481)
+++ cp/class.c	(working copy)
@@ -7651,8 +7651,8 @@ resolve_address_of_overloaded_function (tree targe
       /* Make =delete work with SFINAE.  */
       if (DECL_DELETED_FN (fn) && !(flags & tf_error))
 	return error_mark_node;
-      
-      mark_used (fn);
+
+      mark_used (fn, flags);
     }
 
   /* We could not check access to member functions when this
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 221481)
+++ cp/decl.c	(working copy)
@@ -14594,7 +14594,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t
 	 ordinary FUNCTION_DECL.  */
       fn = lookup_name (id);
       arg = build_address (decl);
-      mark_used (decl);
+      mark_used (decl, complain);
       cleanup = cp_build_function_call_nary (fn, complain, arg, NULL_TREE);
       if (cleanup == error_mark_node)
 	return error_mark_node;
@@ -14637,7 +14637,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t
       && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
     /* Treat objects with destructors as used; the destructor may do
        something substantive.  */
-    mark_used (decl);
+    mark_used (decl, complain);
 
   return cleanup;
 }
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 221481)
+++ cp/pt.c	(working copy)
@@ -9883,7 +9883,7 @@ gen_elem_of_pack_expansion_instantiation (tree pat
 	  if (index == 0)
 	    {
 	      aps = make_argument_pack_select (arg_pack, index);
-	      mark_used (parm);
+	      mark_used (parm, complain);
 	      register_local_specialization (aps, parm);
 	    }
 	  else
@@ -12654,7 +12654,7 @@ tsubst_baselink (tree baselink, tree object_type,
     if (BASELINK_P (baselink))
       fns = BASELINK_FUNCTIONS (baselink);
     if (!template_id_p && !really_overloaded_fn (fns))
-      mark_used (OVL_CURRENT (fns));
+      mark_used (OVL_CURRENT (fns), complain);
 
     /* Add back the template arguments, if present.  */
     if (BASELINK_P (baselink) && template_id_p)
@@ -12769,7 +12769,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
 					   scope);
       /* Remember that there was a reference to this entity.  */
-      mark_used (expr);
+      mark_used (expr, complain);
     }
 
   if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
@@ -12879,7 +12879,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t com
       
       if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
 	r = ARGUMENT_PACK_SELECT_ARG (r);
-      mark_used (r);
+      mark_used (r, complain);
       return r;
 
     case CONST_DECL:
@@ -13036,7 +13036,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t com
 	}
       else
 	r = t;
-      mark_used (r);
+      mark_used (r, complain);
       return r;
 
     case NAMESPACE_DECL:
@@ -13400,7 +13400,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t com
 	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
 	r = build2 (code, type, op0, op1);
 	PTRMEM_OK_P (r) = PTRMEM_OK_P (t);
-	mark_used (TREE_OPERAND (r, 1));
+	mark_used (TREE_OPERAND (r, 1), complain);
 	return r;
       }
 
@@ -14919,7 +14919,7 @@ tsubst_copy_and_build (tree t,
 						args, complain, in_decl);
       /* Remember that there was a reference to this entity.  */
       if (DECL_P (op1))
-	mark_used (op1);
+	mark_used (op1, complain);
       RETURN (build_x_arrow (input_location, op1, complain));
 
     case NEW_EXPR:
@@ -15355,7 +15355,7 @@ tsubst_copy_and_build (tree t,
 						     args, complain, in_decl);
 	/* Remember that there was a reference to this entity.  */
 	if (DECL_P (object))
-	  mark_used (object);
+	  mark_used (object, complain);
 	object_type = TREE_TYPE (object);
 
 	member = TREE_OPERAND (t, 1);
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 221481)
+++ cp/rtti.c	(working copy)
@@ -708,10 +708,10 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst
 	  target_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
 	  static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype));
 	  td2 = get_tinfo_decl (target_type);
-	  mark_used (td2);
+	  mark_used (td2, complain);
 	  td2 = cp_build_addr_expr (td2, complain);
 	  td3 = get_tinfo_decl (static_type);
-	  mark_used (td3);
+	  mark_used (td3, complain);
 	  td3 = cp_build_addr_expr (td3, complain);
 
 	  /* Determine how T and V are related.  */
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 221481)
+++ cp/semantics.c	(working copy)
@@ -3115,7 +3115,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t c
   tree initializer = convert_from_reference (decl);
 
   /* Mark it as used now even if the use is ill-formed.  */
-  mark_used (decl);
+  mark_used (decl, complain);
 
   /* Core issue 696: "[At the July 2009 meeting] the CWG expressed
      support for an approach in which a reference to a local
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 221481)
+++ cp/typeck.c	(working copy)
@@ -2296,7 +2296,7 @@ build_class_member_access_expr (tree object, tree
   if (DECL_P (member))
     {
       member_scope = DECL_CLASS_CONTEXT (member);
-      mark_used (member);
+      mark_used (member, complain);
       if (TREE_DEPRECATED (member))
 	warn_deprecated_use (member, NULL_TREE);
     }
@@ -3475,7 +3475,7 @@ cp_build_function_call_vec (tree function, vec<tre
 
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      mark_used (function);
+      mark_used (function, complain);
       fndecl = function;
 
       /* Convert anything with function type to a pointer-to-function.  */
@@ -5374,7 +5374,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	 and the created OFFSET_REF.  */
       tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
       tree fn = get_first_fn (TREE_OPERAND (arg, 1));
-      mark_used (fn);
+      mark_used (fn, complain);
 
       if (! flag_ms_extensions)
 	{
@@ -5561,7 +5561,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	 function.  */
       gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
 		  && DECL_STATIC_FUNCTION_P (fn));
-      mark_used (fn);
+      mark_used (fn, complain);
       val = build_address (fn);
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
 	/* Do not lose object's side effects.  */

Comments

Jason Merrill March 18, 2015, 2:15 a.m. UTC | #1
On 03/17/2015 10:03 PM, Paolo Carlini wrote:
> Hi,
>
> On 03/18/2015 01:11 AM, Jason Merrill wrote:
>> On 03/17/2015 01:09 PM, Paolo Carlini wrote:
>>> -  require_deduced_type (decl);
>>> +  if (complain & tf_error)
>>> +    require_deduced_type (decl);
>>
>> I think we want to return false if there's a problem here so that we
>> don't just silently accept this in SFINAE context.  So probably we
>> want to replace the call with an inlined form like earlier in mark_used.
> Indeed, I was a bit nervous about that, should have asked... Anyway, the
> below is finishing testing.

OK.

>> Are there other places that still need to pass complain to mark_used?
> Well, if we are talking about functions getting a tsubst_flags_t and
> *not* passing it down to mark_used, there are quite a few - see
> attached. I didn't feel like raising the issue at this time because in
> all those cases, at variance with the specific case we are changing for
> the bug, the return value of mark_used is *not* checked, thus is we
> suppress the errors in SFINAE context we would like to also add a check
> and return early, but in general, doing that when we are *outside*
> SFINAE changes what happens during error recovery, thus it seems a bit
> risky fiddling with those right now...

Agreed, let's defer this until stage 1.

Jason
Jason Merrill April 15, 2015, 1:31 a.m. UTC | #2
On 03/17/2015 10:15 PM, Jason Merrill wrote:
> On 03/17/2015 10:03 PM, Paolo Carlini wrote:
>> On 03/18/2015 01:11 AM, Jason Merrill wrote:

>>> Are there other places that still need to pass complain to mark_used?
>> Well, if we are talking about functions getting a tsubst_flags_t and
>> *not* passing it down to mark_used, there are quite a few - see
>> attached. I didn't feel like raising the issue at this time because in
>> all those cases, at variance with the specific case we are changing for
>> the bug, the return value of mark_used is *not* checked, thus is we
>> suppress the errors in SFINAE context we would like to also add a check
>> and return early, but in general, doing that when we are *outside*
>> SFINAE changes what happens during error recovery, thus it seems a bit
>> risky fiddling with those right now...
>
> Agreed, let's defer this until stage 1.

I note that it's now stage 1.  :)

There are various places in the compiler that error and continue if 
tf_error is set, but return error_mark_node immediately if not; it seems 
reasonable to follow that pattern in the places that don't currently 
check the return value.

Jason
Paolo Carlini April 15, 2015, 8:44 a.m. UTC | #3
Hi,

On 04/15/2015 03:31 AM, Jason Merrill wrote:
> Agreed, let's defer this until stage 1.
>
> I note that it's now stage 1.  :)
>
> There are various places in the compiler that error and continue if 
> tf_error is set, but return error_mark_node immediately if not; it 
> seems reasonable to follow that pattern in the places that don't 
> currently check the return value.
Agreed. First, let me double check that the draft patch which I attached 
in this thread still passes testing.

Paolo.
diff mbox

Patch

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 221481)
+++ cp/call.c	(working copy)
@@ -7486,7 +7486,7 @@  build_over_call (struct z_candidate *cand, int fla
     }
 
   if (!already_used
-      && !mark_used (fn))
+      && !mark_used (fn, complain))
     return error_mark_node;
 
   if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 221481)
+++ cp/decl2.c	(working copy)
@@ -5037,7 +5037,12 @@  mark_used (tree decl, tsubst_flags_t complain)
       && uses_template_parms (DECL_TI_ARGS (decl)))
     return true;
 
-  require_deduced_type (decl);
+  if (undeduced_auto_decl (decl))
+    {
+      if (complain & tf_error)
+	error ("use of %qD before deduction of %<auto%>", decl);
+      return false;
+    }
 
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (cp_unevaluated_operand != 0)
Index: testsuite/g++.dg/cpp1y/pr65340.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr65340.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/pr65340.C	(working copy)
@@ -0,0 +1,19 @@ 
+// PR c++/65340
+// { dg-do compile { target c++14 } }
+
+template <typename Type> Type constant;
+namespace reflect {
+namespace functors {
+  struct recurse { auto operator()(, ); }; // { dg-error "expected" }
+}
+  auto &recurse = constant < functors :: recurse > ;
+}
+namespace functors {
+struct traverse {
+  template <typename Algo, typename Value>
+  auto operator()(Algo, Value) -> decltype(reflect
+                                           :: recurse(0, 0)); // { dg-error "use of" }
+};
+}
+auto &traverse = constant < functors :: traverse > ;
+operator()()->decltype(traverse(0, 0)) // { dg-error "no match|expected" }