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;