diff mbox

[1/4] Handle errors in both args of va_arg

Message ID 4828e445-76d1-7ae5-1a36-acc4e7073925@mentor.com
State New
Headers show

Commit Message

Tom de Vries Aug. 24, 2016, 5:56 a.m. UTC
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

Comments

Joseph Myers Aug. 29, 2016, 3:50 p.m. UTC | #1
On Wed, 24 Aug 2016, Tom de Vries wrote:

> 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.

OK.
diff mbox

Patch

Handle errors in both args of va_arg

2016-08-22  Tom de Vries  <tom@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" }
 }