diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47f98fa95cc..c3a2d00dab7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-04-25 Joseph Myers + + PR c/39564 + * c-decl.c (grokdeclarator): Diagnose declarations of functions + with variably modified return type and no storage class + specifiers, except for the case of nested functions. Distinguish + extern declarations of functions with variably modified return + types from those of objects with variably modified types. + 2009-04-25 Jan Hubicka * tree.c (list_equal_p): New function. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index d2dbfbeea81..9693a342a8f 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -5012,11 +5012,17 @@ grokdeclarator (const struct c_declarator *declarator, DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); } - if (storage_class == csc_extern + if ((storage_class == csc_extern + || (storage_class == csc_none + && TREE_CODE (type) == FUNCTION_TYPE + && !funcdef_flag)) && variably_modified_type_p (type, NULL_TREE)) { /* C99 6.7.5.2p2 */ - error ("object with variably modified type must have no linkage"); + if (TREE_CODE (type) == FUNCTION_TYPE) + error ("non-nested function with variably modified type"); + else + error ("object with variably modified type must have no linkage"); } /* Record `register' declaration for warnings on & diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f2fdc93c4bd..c9cfd92fa3a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-25 Joseph Myers + + PR c/39564 + * gcc.dg/vla-19.c: New test. + 2009-04-25 Joseph Myers PR preprocessor/39559 diff --git a/gcc/testsuite/gcc.dg/vla-19.c b/gcc/testsuite/gcc.dg/vla-19.c new file mode 100644 index 00000000000..83093c9291a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-19.c @@ -0,0 +1,32 @@ +/* Test diagnostics for variably modified function return types. PR + 39564. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99" } */ + +int a; + +void +f1 (void) +{ + typedef int T[a]; + extern T *g1 (void); /* { dg-error "non-nested function with variably modified type" } */ +} + +void +f2 (void) +{ + extern int (*g2 (void))[a]; /* { dg-error "non-nested function with variably modified type" } */ +} + +void +f3 (void) +{ + typedef int T[a]; + T *g3 (void); /* { dg-error "non-nested function with variably modified type" } */ +} + +void +f4 (void) +{ + int (*g4 (void))[a]; /* { dg-error "non-nested function with variably modified type" } */ +}