Hi,
I.
Consider test-case:
...
struct A {};
void
foo (void)
{
__builtin_va_arg (0, A);
}
...
Compiling this with g++ gives the error:
...
error: first argument to ‘va_arg’ not of type ‘va_list’
...
II.
Now we add ++ in front of the expression, and get:
...
struct A {};
void
foo (void)
{
++__builtin_va_arg (0, A);
}
...
Compiling this with g++ gives this error:
...
error: no match for ‘operator++’ (operand type is ‘A’)
...
and the previous error disappears.
III.
This patch makes sure that both errors are given for the last example,
by moving the error call from gimplify_va_arg_expr to build_va_arg.
Bootstrapped and reg-tested on x86_64.
OK for trunk?
Thanks,
- Tom
Handle errors in both args of va_arg
2016-08-22 Tom de Vries <t...@codesourcery.com>
* c-common.c (build_va_arg): Add first argument error. Build va_arg
with error_mark_node as va_list instead of with illegal va_list.
* gimplify.c (gimplify_va_arg_expr): Replace first argument type error
with assert.
* g++.dg/ext/va-arg1.C: Add error check for illegal first argument.
---
gcc/c-family/c-common.c | 7 +++++--
gcc/gimplify.c | 7 +------
gcc/testsuite/g++.dg/ext/va-arg1.C | 4 +++-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 32468ca..7ad1930 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5794,16 +5794,19 @@ build_va_arg (location_t loc, tree expr, tree type)
{
tree va_type = TREE_TYPE (expr);
tree canon_va_type = (va_type == error_mark_node
- ? NULL_TREE
+ ? error_mark_node
: targetm.canonical_va_list_type (va_type));
if (va_type == error_mark_node
|| canon_va_type == NULL_TREE)
{
+ if (canon_va_type == NULL_TREE)
+ error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
+
/* Let's handle things neutrallly, if expr:
- has undeclared type, or
- is not an va_list type. */
- return build_va_arg_1 (loc, type, expr);
+ return build_va_arg_1 (loc, type, error_mark_node);
}
if (TREE_CODE (canon_va_type) != ARRAY_TYPE)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4715332..288b472 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -11959,12 +11959,7 @@ gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
if (have_va_type == error_mark_node)
return GS_ERROR;
have_va_type = targetm.canonical_va_list_type (have_va_type);
-
- if (have_va_type == NULL_TREE)
- {
- error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
- return GS_ERROR;
- }
+ gcc_assert (have_va_type != NULL_TREE);
/* Generate a diagnostic for requesting data of a type that cannot
be passed through `...' due to type promotion at the call site. */
diff --git a/gcc/testsuite/g++.dg/ext/va-arg1.C b/gcc/testsuite/g++.dg/ext/va-arg1.C
index 5606128..c0477ad 100644
--- a/gcc/testsuite/g++.dg/ext/va-arg1.C
+++ b/gcc/testsuite/g++.dg/ext/va-arg1.C
@@ -4,5 +4,7 @@ struct A {};
void foo()
{
- ++__builtin_va_arg(0, A); // { dg-error "operand type is 'A'" }
+ ++__builtin_va_arg (0, A);
+ // { dg-error "operand type is 'A'" "" {target *-*-*} "7" }
+ // { dg-error "first argument to 'va_arg' not of type 'va_list'" "" {target *-*-*} "7" }
}