In this testcase, the compiler fails to diagnose trying to use the value of an INDIRECT_REF of incomplete type. Since decay_conversion is modeling the lvalue->rvalue conversion here, that seems a logical place to complain.

When making that change, I noticed that we were incorrectly calling mark_rvalue_use for the array->pointer and function->pointer conversions, which are more properly considered lvalue uses, so I've fixed that as well.

The convert_like_real change was necessary to retain the "initializing argument" message for several tests in the testsuite, since we're now diagnosing the use of incomplete in a different place.

I've also improved the incomplete type diagnostic to use the location of the expression, if one is provided.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit efa5f059291139330e0dabaa857932ec08c7a057
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jan 14 11:50:56 2016 -0500

    	PR c++/69257
    	* typeck.c (decay_conversion): Don't call mark_rvalue_use for
    	array/function-to-pointer conversion.  Call
    	complete_type_or_maybe_complain for lvalue-to-rvalue conversion.
    	* call.c (convert_like_real): Print call context if
    	decay_conversion errors.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f3f95ef..c05170a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6542,7 +6542,16 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
     case ck_rvalue:
       expr = decay_conversion (expr, complain);
       if (expr == error_mark_node)
-	return error_mark_node;
+	{
+	  if (complain)
+	    {
+	      maybe_print_user_conv_context (convs);
+	      if (fn)
+		inform (DECL_SOURCE_LOCATION (fn),
+			"  initializing argument %P of %qD", argnum, fn);
+	    }
+	  return error_mark_node;
+	}
 
       if (! MAYBE_CLASS_TYPE_P (totype))
 	return expr;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 94267b67..0503c6f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1909,11 +1909,10 @@ unlowered_expr_type (const_tree exp)
 
 /* Perform the conversions in [expr] that apply when an lvalue appears
    in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
-   function-to-pointer conversions.  In addition, manifest constants
-   are replaced by their values, and bitfield references are converted
-   to their declared types. Note that this function does not perform the
-   lvalue-to-rvalue conversion for class types. If you need that conversion
-   to for class types, then you probably need to use force_rvalue.
+   function-to-pointer conversions.  In addition, bitfield references are
+   converted to their declared types. Note that this function does not perform
+   the lvalue-to-rvalue conversion for class types. If you need that conversion
+   for class types, then you probably need to use force_rvalue.
 
    Although the returned value is being used as an rvalue, this
    function does not wrap the returned expression in a
@@ -1933,8 +1932,6 @@ decay_conversion (tree exp,
   if (type == error_mark_node)
     return error_mark_node;
 
-  exp = mark_rvalue_use (exp, loc, reject_builtin);
-
   exp = resolve_nondeduced_context (exp);
   if (type_unknown_p (exp))
     {
@@ -1962,12 +1959,19 @@ decay_conversion (tree exp,
   if (invalid_nonstatic_memfn_p (loc, exp, complain))
     return error_mark_node;
   if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
-    return cp_build_addr_expr (exp, complain);
+    {
+      exp = mark_lvalue_use (exp);
+      if (reject_builtin && reject_gcc_builtin (exp, loc))
+	return error_mark_node;
+      return cp_build_addr_expr (exp, complain);
+    }
   if (code == ARRAY_TYPE)
     {
       tree adr;
       tree ptrtype;
 
+      exp = mark_lvalue_use (exp);
+
       if (INDIRECT_REF_P (exp))
 	return build_nop (build_pointer_type (TREE_TYPE (type)),
 			  TREE_OPERAND (exp, 0));
@@ -2013,6 +2017,9 @@ decay_conversion (tree exp,
       return cp_convert (ptrtype, adr, complain);
     }
 
+  /* Otherwise, it's the lvalue-to-rvalue conversion.  */
+  exp = mark_rvalue_use (exp, loc, reject_builtin);
+
   /* If a bitfield is used in a context where integral promotion
      applies, then the caller is expected to have used
      default_conversion.  That function promotes bitfields correctly
@@ -2032,6 +2039,9 @@ decay_conversion (tree exp,
   if (!CLASS_TYPE_P (type) && cv_qualified_p (type))
     exp = build_nop (cv_unqualified (type), exp);
 
+  if (!complete_type_or_maybe_complain (type, exp, complain))
+    return error_mark_node;
+
   return exp;
 }
 
diff --git a/gcc/testsuite/g++.dg/ext/asm13.C b/gcc/testsuite/g++.dg/ext/asm13.C
new file mode 100644
index 0000000..eece05e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/asm13.C
@@ -0,0 +1,6 @@
+// PR c++/69257
+
+int fn1() {
+  struct S *x;
+  __asm ( "": :"" (*x));	// { dg-error "incomplete" }
+}
commit 0c5ad1f445e3008dcd25b6b6ac6f4cee7efce513
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jan 14 13:00:25 2016 -0500

    	* typeck2.c (cxx_incomplete_type_diagnostic): Use the location of
    	value.

diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index c67d7f6..ac2f3c3 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -475,13 +475,15 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
  retry:
   /* We must print an error message.  Be clever about what it says.  */
 
+  location_t loc = EXPR_LOC_OR_LOC (value, input_location);
+
   switch (TREE_CODE (type))
     {
     case RECORD_TYPE:
     case UNION_TYPE:
     case ENUMERAL_TYPE:
       if (!is_decl)
-	complained = emit_diagnostic (diag_kind, input_location, 0,
+	complained = emit_diagnostic (diag_kind, loc, 0,
 				      "invalid use of incomplete type %q#T",
 				      type);
       if (complained)
@@ -489,7 +491,7 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
       break;
 
     case VOID_TYPE:
-      emit_diagnostic (diag_kind, input_location, 0,
+      emit_diagnostic (diag_kind, loc, 0,
 		       "invalid use of %qT", type);
       break;
 
@@ -499,7 +501,7 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
 	  type = TREE_TYPE (type);
 	  goto retry;
 	}
-      emit_diagnostic (diag_kind, input_location, 0,
+      emit_diagnostic (diag_kind, loc, 0,
 		       "invalid use of array with unspecified bounds");
       break;
 
@@ -511,11 +513,11 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
 	  member = get_first_fn (member);
 	if (DECL_FUNCTION_MEMBER_P (member)
 	    && ! flag_ms_extensions)
-	  emit_diagnostic (diag_kind, input_location, 0,
+	  emit_diagnostic (diag_kind, loc, 0,
 			   "invalid use of member function %qD "
 			   "(did you forget the %<()%> ?)", member);
 	else
-	  emit_diagnostic (diag_kind, input_location, 0,
+	  emit_diagnostic (diag_kind, loc, 0,
 			   "invalid use of member %qD "
 			   "(did you forget the %<&%> ?)", member);
       }
@@ -523,28 +525,28 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
 
     case TEMPLATE_TYPE_PARM:
       if (is_auto (type))
-	emit_diagnostic (diag_kind, input_location, 0,
+	emit_diagnostic (diag_kind, loc, 0,
 			 "invalid use of %<auto%>");
       else
-	emit_diagnostic (diag_kind, input_location, 0,
+	emit_diagnostic (diag_kind, loc, 0,
 			 "invalid use of template type parameter %qT", type);
       break;
 
     case BOUND_TEMPLATE_TEMPLATE_PARM:
-      emit_diagnostic (diag_kind, input_location, 0,
+      emit_diagnostic (diag_kind, loc, 0,
 		       "invalid use of template template parameter %qT",
 		       TYPE_NAME (type));
       break;
 
     case TYPENAME_TYPE:
-      emit_diagnostic (diag_kind, input_location, 0,
+      emit_diagnostic (diag_kind, loc, 0,
 		       "invalid use of dependent type %qT", type);
       break;
 
     case LANG_TYPE:
       if (type == init_list_type_node)
 	{
-	  emit_diagnostic (diag_kind, input_location, 0,
+	  emit_diagnostic (diag_kind, loc, 0,
 			   "invalid use of brace-enclosed initializer list");
 	  break;
 	}
@@ -552,14 +554,14 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
       if (value && TREE_CODE (value) == COMPONENT_REF)
 	goto bad_member;
       else if (value && TREE_CODE (value) == ADDR_EXPR)
-	emit_diagnostic (diag_kind, input_location, 0,
+	emit_diagnostic (diag_kind, loc, 0,
 			 "address of overloaded function with no contextual "
 			 "type information");
       else if (value && TREE_CODE (value) == OVERLOAD)
-	emit_diagnostic (diag_kind, input_location, 0,
+	emit_diagnostic (diag_kind, loc, 0,
 			 "overloaded function with no contextual type information");
       else
-	emit_diagnostic (diag_kind, input_location, 0,
+	emit_diagnostic (diag_kind, loc, 0,
 			 "insufficient contextual information to determine type");
       break;
 

Reply via email to