Message ID | 20150427173052.GA11448@redhat.com |
---|---|
State | New |
Headers | show |
On 04/27/2015 11:30 AM, Marek Polacek wrote: > As reported in the PR, va_arg (ap, void) probably doesn't make any sense and > should be rejected thus. cc1plus and clang reject va_arg with an incomplete > type. This patch makes cc1 reject it as well. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2015-04-27 Marek Polacek <polacek@redhat.com> > > PR c/65901 > * c-typeck.c (c_build_va_arg): Require TYPE be a complete type. > > * gcc.c-torture/compile/pr48767.c (foo): Add dg-error. > * gcc.dg/pr65901.c: New test. OK. jeff
On 04/27/2015 11:30 AM, Marek Polacek wrote: > As reported in the PR, va_arg (ap, void) probably doesn't make any sense and > should be rejected thus. cc1plus and clang reject va_arg with an incomplete > type. This patch makes cc1 reject it as well. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2015-04-27 Marek Polacek <polacek@redhat.com> > > PR c/65901 > * c-typeck.c (c_build_va_arg): Require TYPE be a complete type. > > * gcc.c-torture/compile/pr48767.c (foo): Add dg-error. > * gcc.dg/pr65901.c: New test. > > diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c > index 91735b5..c58e918 100644 > --- gcc/c/c-typeck.c > +++ gcc/c/c-typeck.c > @@ -12648,6 +12648,11 @@ c_build_va_arg (location_t loc, tree expr, tree type) > if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE) > warning_at (loc, OPT_Wc___compat, > "C++ requires promoted type, not enum type, in %<va_arg%>"); > + if (type == error_mark_node || !COMPLETE_TYPE_P (type)) > + { > + c_incomplete_type_error (NULL_TREE, type); The error message in the test cases below isn't quite right. The type of the aggregates isn't undefined, it's incomplete. Looking at the function, I wonder if the first argument should be EXPR rather than than NULL_TREE? Alternatively, experimenting with other cases where GCC diagnoses invalid uses of incomplete type, I see that it issues: "invalid application of %qs to incomplete type %qT" which might work even better here since we could name the expression (va_arg). Martin > + return error_mark_node; > + } > return build_va_arg (loc, expr, type); > } > > diff --git gcc/testsuite/gcc.c-torture/compile/pr48767.c gcc/testsuite/gcc.c-torture/compile/pr48767.c > index 66cb348..c8fef35 100644 > --- gcc/testsuite/gcc.c-torture/compile/pr48767.c > +++ gcc/testsuite/gcc.c-torture/compile/pr48767.c > @@ -3,5 +3,5 @@ > void > foo (__builtin_va_list ap) > { > - __builtin_va_arg (ap, void); > + __builtin_va_arg (ap, void); /* { dg-error "invalid use of void expression" } */ > } > diff --git gcc/testsuite/gcc.dg/pr65901.c gcc/testsuite/gcc.dg/pr65901.c > index e69de29..8708a1e 100644 > --- gcc/testsuite/gcc.dg/pr65901.c > +++ gcc/testsuite/gcc.dg/pr65901.c > @@ -0,0 +1,16 @@ > +/* PR c/65901 */ > +/* { dg-do compile } */ > +/* { dg-options "" } */ > + > +struct S; > +enum E; > +union U; > + > +void > +foo (__builtin_va_list ap) > +{ > + __builtin_va_arg (ap, void); /* { dg-error "invalid use of void expression" } */ > + __builtin_va_arg (ap, struct S); /* { dg-error "invalid use of undefined type" } */ > + __builtin_va_arg (ap, enum E); /* { dg-error "invalid use of undefined type" } */ > + __builtin_va_arg (ap, union U); /* { dg-error "invalid use of undefined type" } */ > +} > > Marek >
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c index 91735b5..c58e918 100644 --- gcc/c/c-typeck.c +++ gcc/c/c-typeck.c @@ -12648,6 +12648,11 @@ c_build_va_arg (location_t loc, tree expr, tree type) if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE) warning_at (loc, OPT_Wc___compat, "C++ requires promoted type, not enum type, in %<va_arg%>"); + if (type == error_mark_node || !COMPLETE_TYPE_P (type)) + { + c_incomplete_type_error (NULL_TREE, type); + return error_mark_node; + } return build_va_arg (loc, expr, type); } diff --git gcc/testsuite/gcc.c-torture/compile/pr48767.c gcc/testsuite/gcc.c-torture/compile/pr48767.c index 66cb348..c8fef35 100644 --- gcc/testsuite/gcc.c-torture/compile/pr48767.c +++ gcc/testsuite/gcc.c-torture/compile/pr48767.c @@ -3,5 +3,5 @@ void foo (__builtin_va_list ap) { - __builtin_va_arg (ap, void); + __builtin_va_arg (ap, void); /* { dg-error "invalid use of void expression" } */ } diff --git gcc/testsuite/gcc.dg/pr65901.c gcc/testsuite/gcc.dg/pr65901.c index e69de29..8708a1e 100644 --- gcc/testsuite/gcc.dg/pr65901.c +++ gcc/testsuite/gcc.dg/pr65901.c @@ -0,0 +1,16 @@ +/* PR c/65901 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct S; +enum E; +union U; + +void +foo (__builtin_va_list ap) +{ + __builtin_va_arg (ap, void); /* { dg-error "invalid use of void expression" } */ + __builtin_va_arg (ap, struct S); /* { dg-error "invalid use of undefined type" } */ + __builtin_va_arg (ap, enum E); /* { dg-error "invalid use of undefined type" } */ + __builtin_va_arg (ap, union U); /* { dg-error "invalid use of undefined type" } */ +}