diff options
| -rw-r--r-- | gcc/ChangeLog | 15 | ||||
| -rw-r--r-- | gcc/c-decl.c | 321 | ||||
| -rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/991209-1.c | 3 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-10.c | 45 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-11.c | 45 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-4.c | 2 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-5.c | 2 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-6.c | 2 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-7.c | 39 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-8.c | 32 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/declspec-9.c | 43 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/pr14289-2.c | 12 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/pr14289-3.c | 12 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/tls/diag-2.c | 10 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/tls/diag-4.c | 10 | ||||
| -rw-r--r-- | gcc/testsuite/gcc.dg/tls/diag-5.c | 3 |
17 files changed, 449 insertions, 158 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 190c7e6f..db61ded 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2004-09-11 Joseph S. Myers <jsm@polyomino.org.uk> + + * c-tree.h (enum c_storage_class): New. + (struct c_declspecs): Add storage_class, inline_p and thread_p. + * c-decl.c (shadow_tag_warned): Give errors for "inline" in empty + declarations and "auto" or "register" in file scope empty + declarations. Give more specific warnings for other cases of + storage class specifiers in empty declarations. + (grokdeclarator): Update for new structures. Don't check for + multiple storage classes. Diagnose file-scope "register" if + pedantic. + (build_null_declspecs): Update. + (declspecs_add_scspec): Update. Diagnose multiple storage class + specifiers and invalid uses of "__thread". + 2004-09-11 Zack Weinberg <zack@codesourcery.com> * tree.c (tree_code_size): New function, bulk of code from tree_size. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index acec389..60b613f 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2741,6 +2741,36 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; } + if (declspecs->inline_p) + { + error ("%<inline%> in empty declaration"); + warned = 1; + } + + if (current_scope == file_scope && declspecs->storage_class == csc_auto) + { + error ("%<auto%> in file-scope empty declaration"); + warned = 1; + } + + if (current_scope == file_scope && declspecs->storage_class == csc_register) + { + error ("%<register%> in file-scope empty declaration"); + warned = 1; + } + + if (!warned && !in_system_header && declspecs->storage_class != csc_none) + { + warning ("useless storage class specifier in empty declaration"); + warned = 2; + } + + if (!warned && !in_system_header && declspecs->thread_p) + { + warning ("useless %<__thread%> in empty declaration"); + warned = 2; + } + if (!warned && !in_system_header && declspecs->specbits) { warning ("useless keyword or type name in empty declaration"); @@ -3597,11 +3627,12 @@ grokdeclarator (const struct c_declarator *declarator, { int specbits = declspecs->specbits; tree type = declspecs->type; + bool threadp = declspecs->thread_p; + enum c_storage_class storage_class = declspecs->storage_class; int constp; int restrictp; int volatilep; int type_quals = TYPE_UNQUALIFIED; - int inlinep; int defaulted_int = 0; const char *name, *orig_name; tree typedef_type = 0; @@ -3682,7 +3713,7 @@ grokdeclarator (const struct c_declarator *declarator, | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_COMPLEX)))) /* Don't warn about typedef foo = bar. */ - && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized) + && ! (storage_class == csc_typedef && initialized) && ! in_system_header) { /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type @@ -3866,7 +3897,6 @@ grokdeclarator (const struct c_declarator *declarator, = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type); volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type); - inlinep = !! (specbits & (1 << (int) RID_INLINE)); if (pedantic && !flag_isoc99) { if (constp > 1) @@ -3882,99 +3912,82 @@ grokdeclarator (const struct c_declarator *declarator, | (restrictp ? TYPE_QUAL_RESTRICT : 0) | (volatilep ? TYPE_QUAL_VOLATILE : 0)); - /* Warn if two storage classes are given. Default to `auto'. */ - - { - int nclasses = 0; - - if (specbits & 1 << (int) RID_AUTO) nclasses++; - if (specbits & 1 << (int) RID_STATIC) nclasses++; - if (specbits & 1 << (int) RID_EXTERN) nclasses++; - if (specbits & 1 << (int) RID_REGISTER) nclasses++; - if (specbits & 1 << (int) RID_TYPEDEF) nclasses++; - - /* "static __thread" and "extern __thread" are allowed. */ - if ((specbits & (1 << (int) RID_THREAD - | 1 << (int) RID_STATIC - | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD)) - nclasses++; - - /* Warn about storage classes that are invalid for certain - kinds of declarations (parameters, typenames, etc.). */ - - if (nclasses > 1) - error ("multiple storage classes in declaration of `%s'", name); - else if (funcdef_flag - && (specbits - & ((1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO) - | (1 << (int) RID_TYPEDEF) - | (1 << (int) RID_THREAD)))) - { - if (specbits & 1 << (int) RID_AUTO - && (pedantic || current_scope == file_scope)) - pedwarn ("function definition declared `auto'"); - if (specbits & 1 << (int) RID_REGISTER) - error ("function definition declared `register'"); - if (specbits & 1 << (int) RID_TYPEDEF) - error ("function definition declared `typedef'"); - if (specbits & 1 << (int) RID_THREAD) - error ("function definition declared `__thread'"); - specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD)); - } - else if (decl_context != NORMAL && nclasses > 0) - { - if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER) - ; - else - { - switch (decl_context) - { - case FIELD: - error ("storage class specified for structure field `%s'", - name); - break; - case PARM: - error ("storage class specified for parameter `%s'", name); - break; - default: - error ("storage class specified for typename"); - break; - } - specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC) - | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD)); - } - } - else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag) - { - /* `extern' with initialization is invalid if not at file scope. */ - if (current_scope == file_scope) - warning ("`%s' initialized and declared `extern'", name); - else - error ("`%s' has both `extern' and initializer", name); - } - else if (current_scope == file_scope) - { - if (specbits & 1 << (int) RID_AUTO) - error ("file-scope declaration of `%s' specifies `auto'", name); - } - else - { - if (specbits & 1 << (int) RID_EXTERN && funcdef_flag) - error ("nested function `%s' declared `extern'", name); - else if ((specbits & (1 << (int) RID_THREAD - | 1 << (int) RID_EXTERN - | 1 << (int) RID_STATIC)) - == (1 << (int) RID_THREAD)) - { - error ("function-scope `%s' implicitly auto and declared `__thread'", - name); - specbits &= ~(1 << (int) RID_THREAD); - } - } - } + /* Warn about storage classes that are invalid for certain + kinds of declarations (parameters, typenames, etc.). */ + + if (funcdef_flag + && (threadp + || storage_class == csc_auto + || storage_class == csc_register + || storage_class == csc_typedef)) + { + if (storage_class == csc_auto + && (pedantic || current_scope == file_scope)) + pedwarn ("function definition declared %<auto%>"); + if (storage_class == csc_register) + error ("function definition declared %<register%>"); + if (storage_class == csc_typedef) + error ("function definition declared %<typedef%>"); + if (threadp) + error ("function definition declared %<__thread%>"); + threadp = false; + if (storage_class == csc_auto + || storage_class == csc_register + || storage_class == csc_typedef) + storage_class = csc_none; + } + else if (decl_context != NORMAL && (storage_class != csc_none || threadp)) + { + if (decl_context == PARM && storage_class == csc_register) + ; + else + { + switch (decl_context) + { + case FIELD: + error ("storage class specified for structure field %qs", + name); + break; + case PARM: + error ("storage class specified for parameter %qs", name); + break; + default: + error ("storage class specified for typename"); + break; + } + storage_class = csc_none; + threadp = false; + } + } + else if (storage_class == csc_extern + && initialized + && !funcdef_flag) + { + /* 'extern' with initialization is invalid if not at file scope. */ + if (current_scope == file_scope) + warning ("%qs initialized and declared %<extern%>", name); + else + error ("%qs has both %<extern%> and initializer", name); + } + else if (current_scope == file_scope) + { + if (storage_class == csc_auto) + error ("file-scope declaration of `%s' specifies `auto'", name); + if (pedantic && storage_class == csc_register) + pedwarn ("file-scope declaration of %qs specifies %<register%>", name); + } + else + { + if (storage_class == csc_extern && funcdef_flag) + error ("nested function `%s' declared `extern'", name); + else if (threadp && storage_class == csc_none) + { + error ("function-scope %qs implicitly auto and declared " + "%<__thread%>", + name); + threadp = false; + } + } /* Now figure out the structure of the declarator proper. Descend through it, creating more complex types, until we reach @@ -4337,7 +4350,7 @@ grokdeclarator (const struct c_declarator *declarator, /* If this is declaring a typedef name, return a TYPE_DECL. */ - if (specbits & (1 << (int) RID_TYPEDEF)) + if (storage_class == csc_typedef) { tree decl; /* Note that the grammar rejects storage classes @@ -4394,10 +4407,10 @@ grokdeclarator (const struct c_declarator *declarator, if (VOID_TYPE_P (type) && decl_context != PARM && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE) - && ((specbits & (1 << (int) RID_EXTERN)) + && (storage_class == csc_extern || (current_scope == file_scope - && !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))))))) + && !(storage_class == csc_static + || storage_class == csc_register))))) { error ("variable or field `%s' declared void", name); type = integer_type_node; @@ -4508,8 +4521,7 @@ grokdeclarator (const struct c_declarator *declarator, } else if (TREE_CODE (type) == FUNCTION_TYPE) { - if (specbits & (1 << (int) RID_REGISTER) - || specbits & (1 << (int) RID_THREAD)) + if (storage_class == csc_register || threadp) error ("invalid storage class for function `%s'", name); else if (current_scope != file_scope) { @@ -4518,12 +4530,12 @@ grokdeclarator (const struct c_declarator *declarator, 6.7.1p5, and `extern' makes no difference. However, GCC allows 'auto', perhaps with 'inline', to support nested functions. */ - if (specbits & (1 << (int) RID_AUTO)) + if (storage_class == csc_auto) { if (pedantic) pedwarn ("invalid storage class for function `%s'", name); } - if (specbits & (1 << (int) RID_STATIC)) + if (storage_class == csc_static) error ("invalid storage class for function `%s'", name); } @@ -4546,14 +4558,14 @@ grokdeclarator (const struct c_declarator *declarator, scope and are explicitly declared "auto". This is forbidden by standard C (C99 6.7.1p5) and is interpreted by GCC to signify a forward declaration of a nested function. */ - if ((specbits & (1 << RID_AUTO)) && current_scope != file_scope) + if (storage_class == csc_auto && current_scope != file_scope) DECL_EXTERNAL (decl) = 0; else DECL_EXTERNAL (decl) = 1; /* Record absence of global scope for `static' or `auto'. */ TREE_PUBLIC (decl) - = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO))); + = !(storage_class == csc_static || storage_class == csc_auto); /* For a function definition, record the argument information block where store_parm_decls will look for it. */ @@ -4566,10 +4578,10 @@ grokdeclarator (const struct c_declarator *declarator, /* Record presence of `inline', if it is reasonable. */ if (MAIN_NAME_P (declarator->u.id)) { - if (inlinep) + if (declspecs->inline_p) warning ("cannot inline function `main'"); } - else if (inlinep) + else if (declspecs->inline_p) { /* Record that the function is declared `inline'. */ DECL_DECLARED_INLINE_P (decl) = 1; @@ -4581,7 +4593,7 @@ grokdeclarator (const struct c_declarator *declarator, if (initialized) { DECL_INLINE (decl) = 1; - if (specbits & (1 << (int) RID_EXTERN)) + if (storage_class == csc_extern) current_extern_inline = 1; } } @@ -4595,7 +4607,7 @@ grokdeclarator (const struct c_declarator *declarator, { /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN)); + int extern_ref = !initialized && storage_class == csc_extern; /* Move type qualifiers down to element of an array. */ if (TREE_CODE (type) == ARRAY_TYPE && type_quals) @@ -4632,13 +4644,13 @@ grokdeclarator (const struct c_declarator *declarator, if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; - if (inlinep) + if (declspecs->inline_p) pedwarn ("%Jvariable '%D' declared `inline'", decl, decl); /* At file scope, an initialized extern declaration may follow a static declaration. In that case, DECL_EXTERNAL will be reset later in start_decl. */ - DECL_EXTERNAL (decl) = !!(specbits & (1 << (int) RID_EXTERN)); + DECL_EXTERNAL (decl) = (storage_class == csc_extern); /* At file scope, the presence of a `static' or `register' storage class specifier, or the absence of all storage class specifiers @@ -4646,18 +4658,18 @@ grokdeclarator (const struct c_declarator *declarator, the absence of both `static' and `register' makes it public. */ if (current_scope == file_scope) { - TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) - | (1 << (int) RID_REGISTER))); + TREE_PUBLIC (decl) = !(storage_class == csc_static + || storage_class == csc_register); TREE_STATIC (decl) = !extern_ref; } /* Not at file scope, only `static' makes a static definition. */ else { - TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; + TREE_STATIC (decl) = (storage_class == csc_static); TREE_PUBLIC (decl) = extern_ref; } - if (specbits & 1 << (int) RID_THREAD) + if (threadp) { if (targetm.have_tls) DECL_THREAD_LOCAL (decl) = 1; @@ -4671,7 +4683,7 @@ grokdeclarator (const struct c_declarator *declarator, /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ - if (specbits & (1 << (int) RID_REGISTER)) + if (storage_class == csc_register) { C_DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1; @@ -6720,6 +6732,7 @@ build_null_declspecs (void) ret->decl_attr = 0; ret->attrs = 0; ret->specbits = 0; + ret->storage_class = csc_none; ret->non_sc_seen_p = false; ret->typedef_p = false; ret->typedef_signed_p = false; @@ -6727,6 +6740,8 @@ build_null_declspecs (void) ret->explicit_int_p = false; ret->explicit_char_p = false; ret->long_long_p = false; + ret->inline_p = false; + ret->thread_p = false; return ret; } @@ -6826,23 +6841,79 @@ struct c_declspecs * declspecs_add_scspec (struct c_declspecs *specs, tree scspec) { enum rid i; + enum c_storage_class n = csc_none; + bool dupe = false; gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (scspec)); i = C_RID_CODE (scspec); if (extra_warnings && specs->non_sc_seen_p) warning ("%qs is not at beginning of declaration", IDENTIFIER_POINTER (scspec)); - if (specs->specbits & (1 << (int) i)) - error ("duplicate %qs", IDENTIFIER_POINTER (scspec)); - /* Diagnose "__thread extern" and "__thread static". */ - if (specs->specbits & (1 << (int) RID_THREAD)) - { - if (i == RID_EXTERN) + switch (i) + { + case RID_INLINE: + /* GCC has hitherto given an error for duplicate inline, but + this should be revisited since C99 permits duplicate + inline. */ + dupe = specs->inline_p; + specs->inline_p = true; + break; + case RID_THREAD: + dupe = specs->thread_p; + if (specs->storage_class == csc_auto) + error ("%<__thread%> used with %<auto%>"); + else if (specs->storage_class == csc_register) + error ("%<__thread%> used with %<register%>"); + else if (specs->storage_class == csc_typedef) + error ("%<__thread%> used with %<typedef%>"); + else + specs->thread_p = true; + break; + case RID_AUTO: + n = csc_auto; + break; + case RID_EXTERN: + n = csc_extern; + /* Diagnose "__thread extern". */ + if (specs->thread_p) error ("%<__thread%> before %<extern%>"); - else if (i == RID_STATIC) + break; + case RID_REGISTER: + n = csc_register; + break; + case RID_STATIC: + n = csc_static; + /* Diagnose "__thread static". */ + if (specs->thread_p) error ("%<__thread%> before %<static%>"); + break; + case RID_TYPEDEF: + n = csc_typedef; + break; + default: + gcc_unreachable (); + } + if (n != csc_none && n == specs->storage_class) + dupe = true; + if (dupe) + error ("duplicate %qs", IDENTIFIER_POINTER (scspec)); + if (n != csc_none) + { + if (specs->storage_class != csc_none && n != specs->storage_class) + { + error ("multiple storage classes in declaration specifiers"); + } + else + { + specs->storage_class = n; + if (n != csc_extern && n != csc_static && specs->thread_p) + { + error ("%<__thread%> used with %qs", + IDENTIFIER_POINTER (scspec)); + specs->thread_p = false; + } + } } - specs->specbits |= 1 << (int) i; return specs; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f7d6b82..e48d301 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2004-09-11 Joseph S. Myers <jsm@polyomino.org.uk> + + * gcc.dg/declspec-4.c, gcc.dg/declspec-5.c, gcc.dg/declspec-6.c, + gcc.dg/tls/diag-2.c: Update expected messages. + * gcc.dg/991209-1.c: Specify compilation options. Update expected + messages. + * gcc.dg/pr14289-2.c, gcc.dg/pr14289-3.c: Remove. + * gcc.dg/declspec-7.c, gcc.dg/declspec-8.c, gcc.dg/declspec-9.c, + gcc.dg/declspec-10.c, gcc.dg/declspec-11.c, gcc.dg/tls/diag-4.c, + gcc.dg/tls/diag-5.c: New tests. + 2004-09-11 Zack Weinberg <zack@codesourcery.com> * gcc.dg/20040910-1.c: Correct dg-error regexp. diff --git a/gcc/testsuite/gcc.dg/991209-1.c b/gcc/testsuite/gcc.dg/991209-1.c index b3a4728..2381922 100644 --- a/gcc/testsuite/gcc.dg/991209-1.c +++ b/gcc/testsuite/gcc.dg/991209-1.c @@ -1,8 +1,9 @@ /* { dg-do compile { target i?86-*-* } } */ +/* { dg-options "-ansi -pedantic" } */ int foo () { return 1; } -register char *stack_ptr __asm ("%esp"); +register char *stack_ptr __asm ("%esp"); /* { dg-warning "warning: file-scope declaration of 'stack_ptr' specifies 'register'" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-10.c b/gcc/testsuite/gcc.dg/declspec-10.c new file mode 100644 index 0000000..454cb1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-10.c @@ -0,0 +1,45 @@ +/* Test declaration specifiers. Test various checks on storage class + and function specifiers that depend on information about the + declaration, not just the specifiers. Test with -pedantic. */ +/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ +/* { dg-do compile } */ +/* { dg-options "-pedantic" } */ + +auto void f0 (void) {} /* { dg-warning "warning: function definition declared 'auto'" } */ +register void f1 (void) {} /* { dg-error "error: function definition declared 'register'" } */ +typedef void f2 (void) {} /* { dg-error "error: function definition declared 'typedef'" } */ + +void f3 (auto int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f4 (extern int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f5 (register int); +void f6 (static int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f7 (typedef int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ + +auto int x; /* { dg-error "error: file-scope declaration of `x' specifies `auto'" } */ +register int y; /* { dg-warning "warning: file-scope declaration of 'y' specifies 'register'" } */ + +void h (void) { extern void x (void) {} } /* { dg-error "error: nested function `x' declared `extern'" } */ +/* { dg-warning "warning: ISO C forbids nested functions" "nested" { target *-*-* } 21 } */ + +void +g (void) +{ + void a; /* { dg-error "error: variable or field `a' declared void" } */ + const void b; /* { dg-error "error: variable or field `b' declared void" } */ + static void c; /* { dg-error "error: variable or field `c' declared void" } */ +} + +void p; +const void p1; +extern void q; +extern const void q1; +static void r; /* { dg-error "error: variable or field `r' declared void" } */ +static const void r1; /* { dg-error "error: variable or field `r1' declared void" } */ + +register void f8 (void); /* { dg-error "error: invalid storage class for function `f8'" } */ +/* { dg-warning "warning: file-scope declaration of 'f8' specifies 'register'" "register function" { target *-*-* } 39 } */ + +void i (void) { auto void y (void) {} } /* { dg-warning "warning: ISO C forbids nested functions" } */ +/* { dg-warning "warning: function definition declared 'auto'" "nested" { target *-*-* } 42 } */ + +inline int main (void) { return 0; } /* { dg-warning "warning: cannot inline function `main'" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-11.c b/gcc/testsuite/gcc.dg/declspec-11.c new file mode 100644 index 0000000..c418de1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-11.c @@ -0,0 +1,45 @@ +/* Test declaration specifiers. Test various checks on storage class + and function specifiers that depend on information about the + declaration, not just the specifiers. Test with -pedantic-errors. */ +/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ +/* { dg-do compile } */ +/* { dg-options "-pedantic-errors" } */ + +auto void f0 (void) {} /* { dg-error "error: function definition declared 'auto'" } */ +register void f1 (void) {} /* { dg-error "error: function definition declared 'register'" } */ +typedef void f2 (void) {} /* { dg-error "error: function definition declared 'typedef'" } */ + +void f3 (auto int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f4 (extern int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f5 (register int); +void f6 (static int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f7 (typedef int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ + +auto int x; /* { dg-error "error: file-scope declaration of `x' specifies `auto'" } */ +register int y; /* { dg-error "error: file-scope declaration of 'y' specifies 'register'" } */ + +void h (void) { extern void x (void) {} } /* { dg-error "error: nested function `x' declared `extern'" } */ +/* { dg-error "error: ISO C forbids nested functions" "nested" { target *-*-* } 21 } */ + +void +g (void) +{ + void a; /* { dg-error "error: variable or field `a' declared void" } */ + const void b; /* { dg-error "error: variable or field `b' declared void" } */ + static void c; /* { dg-error "error: variable or field `c' declared void" } */ +} + +void p; +const void p1; +extern void q; +extern const void q1; +static void r; /* { dg-error "error: variable or field `r' declared void" } */ +static const void r1; /* { dg-error "error: variable or field `r1' declared void" } */ + +register void f8 (void); /* { dg-error "error: invalid storage class for function `f8'" } */ +/* { dg-error "error: file-scope declaration of 'f8' specifies 'register'" "register function" { target *-*-* } 39 } */ + +void i (void) { auto void y (void) {} } /* { dg-error "error: ISO C forbids nested functions" } */ +/* { dg-error "error: function definition declared 'auto'" "nested" { target *-*-* } 42 } */ + +inline int main (void) { return 0; } /* { dg-warning "warning: cannot inline function `main'" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-4.c b/gcc/testsuite/gcc.dg/declspec-4.c index 0610e05..fbc6c36 100644 --- a/gcc/testsuite/gcc.dg/declspec-4.c +++ b/gcc/testsuite/gcc.dg/declspec-4.c @@ -22,7 +22,7 @@ int; /* { dg-warning "warning: useless type name in empty declaration" } */ long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ /* { dg-warning "warning: empty declaration" "long" { target *-*-* } 22 } */ T; /* { dg-warning "warning: useless type name in empty declaration" } */ -static const; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ +static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ /* { dg-warning "warning: empty declaration" "long" { target *-*-* } 25 } */ union { long b; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-5.c b/gcc/testsuite/gcc.dg/declspec-5.c index aba2739..febbfb3 100644 --- a/gcc/testsuite/gcc.dg/declspec-5.c +++ b/gcc/testsuite/gcc.dg/declspec-5.c @@ -22,7 +22,7 @@ int; /* { dg-warning "warning: useless type name in empty declaration" } */ long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ /* { dg-warning "warning: empty declaration" "long" { target *-*-* } 22 } */ T; /* { dg-warning "warning: useless type name in empty declaration" } */ -static const; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ +static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ /* { dg-warning "warning: empty declaration" "long" { target *-*-* } 25 } */ union { long b; }; /* { dg-warning "warning: unnamed struct/union that defines no instances" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-6.c b/gcc/testsuite/gcc.dg/declspec-6.c index 91a5d82..305eed7 100644 --- a/gcc/testsuite/gcc.dg/declspec-6.c +++ b/gcc/testsuite/gcc.dg/declspec-6.c @@ -22,7 +22,7 @@ int; /* { dg-error "error: useless type name in empty declaration" } */ long; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ /* { dg-error "error: empty declaration" "long" { target *-*-* } 22 } */ T; /* { dg-error "error: useless type name in empty declaration" } */ -static const; /* { dg-warning "warning: useless keyword or type name in empty declaration" } */ +static const; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ /* { dg-error "error: empty declaration" "long" { target *-*-* } 25 } */ union { long b; }; /* { dg-error "error: unnamed struct/union that defines no instances" } */ diff --git a/gcc/testsuite/gcc.dg/declspec-7.c b/gcc/testsuite/gcc.dg/declspec-7.c new file mode 100644 index 0000000..bb63d95 --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-7.c @@ -0,0 +1,39 @@ +/* Test declaration specifiers. Test checks on storage class + specifiers that can be made at parse time rather than for each + declarator. Note that __thread is tested in + gcc.dg/tls/diag-*.c. */ +/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +/* Duplicate specifiers. */ + +inline inline void f0 (void), /* { dg-error "error: duplicate 'inline'" } */ + f1 (void); + +static static int a, /* { dg-error "error: duplicate 'static'" } */ + b; + +extern extern int c, /* { dg-error "error: duplicate 'extern'" } */ + d; + +typedef typedef int e, /* { dg-error "error: duplicate 'typedef'" } */ + f; + +void +h (void) +{ + auto auto int p, /* { dg-error "error: duplicate 'auto'" } */ + q; + + register register int r, /* { dg-error "error: duplicate 'register'" } */ + s; +} + +/* Multiple specifiers. */ + +static extern int x, /* { dg-error "error: multiple storage classes in declaration specifiers" } */ + y; + +extern typedef long z, /* { dg-error "error: multiple storage classes in declaration specifiers" } */ + w; diff --git a/gcc/testsuite/gcc.dg/declspec-8.c b/gcc/testsuite/gcc.dg/declspec-8.c new file mode 100644 index 0000000..ea60126 --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-8.c @@ -0,0 +1,32 @@ +/* Test declaration specifiers. Test checks on storage class + specifiers and function specifiers in empty declarations. */ +/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +/* The constraints on storage class specifiers and function specifiers + must be met for empty declarations where they are useless. Thus + there may be only one storage class specifier (C90 6.5.1, C99 + 6.7.1#2) and "inline" must not be used because the declaration is + not that of an identifier for a function (C99 6.7.4#1), and + "register" and "auto" must not be used at file scope (C90 6.7, C99 + 6.9#2). */ + +static static struct s; /* { dg-error "error: duplicate 'static'" } */ +/* { dg-warning "warning: useless storage class specifier in empty declaration" "static static" { target *-*-* } 15 } */ + +static extern struct t; /* { dg-error "error: multiple storage classes in declaration specifiers" } */ +/* { dg-warning "warning: useless storage class specifier in empty declaration" "static extern" { target *-*-* } 18 } */ + +inline union u; /* { dg-error "error: 'inline' in empty declaration" } */ + +auto struct v; /* { dg-error "error: 'auto' in file-scope empty declaration" } */ + +register struct w; /* { dg-error "error: 'register' in file-scope empty declaration" } */ + +void +f (void) +{ + auto union p; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ + register struct q; /* { dg-warning "warning: useless storage class specifier in empty declaration" } */ +} diff --git a/gcc/testsuite/gcc.dg/declspec-9.c b/gcc/testsuite/gcc.dg/declspec-9.c new file mode 100644 index 0000000..855393c --- /dev/null +++ b/gcc/testsuite/gcc.dg/declspec-9.c @@ -0,0 +1,43 @@ +/* Test declaration specifiers. Test various checks on storage class + and function specifiers that depend on information about the + declaration, not just the specifiers. Test with no special + options. */ +/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +auto void f0 (void) {} /* { dg-warning "warning: function definition declared 'auto'" } */ +register void f1 (void) {} /* { dg-error "error: function definition declared 'register'" } */ +typedef void f2 (void) {} /* { dg-error "error: function definition declared 'typedef'" } */ + +void f3 (auto int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f4 (extern int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f5 (register int); +void f6 (static int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ +void f7 (typedef int); /* { dg-error "error: storage class specified for parameter 'type name'" } */ + +auto int x; /* { dg-error "error: file-scope declaration of `x' specifies `auto'" } */ +register int y; + +void h (void) { extern void x (void) {} } /* { dg-error "error: nested function `x' declared `extern'" } */ + +void +g (void) +{ + void a; /* { dg-error "error: variable or field `a' declared void" } */ + const void b; /* { dg-error "error: variable or field `b' declared void" } */ + static void c; /* { dg-error "error: variable or field `c' declared void" } */ +} + +void p; +const void p1; +extern void q; +extern const void q1; +static void r; /* { dg-error "error: variable or field `r' declared void" } */ +static const void r1; /* { dg-error "error: variable or field `r1' declared void" } */ + +register void f8 (void); /* { dg-error "error: invalid storage class for function `f8'" } */ + +void i (void) { auto void y (void) {} } + +inline int main (void) { return 0; } /* { dg-warning "warning: cannot inline function `main'" } */ diff --git a/gcc/testsuite/gcc.dg/pr14289-2.c b/gcc/testsuite/gcc.dg/pr14289-2.c deleted file mode 100644 index 7530b46..0000000 --- a/gcc/testsuite/gcc.dg/pr14289-2.c +++ /dev/null @@ -1,12 +0,0 @@ -/* PR middle-end/14289 */ -/* { dg-do compile { target i?86-*-* } } */ -/* { dg-options "-O0" } */ - -static register int a[2] asm("ebx"); /* { dg-error "multiple storage" } */ - -void Nase(void) -{ - int i=6; - a[i]=5; /* { dg-error "address of global" } */ -} - diff --git a/gcc/testsuite/gcc.dg/pr14289-3.c b/gcc/testsuite/gcc.dg/pr14289-3.c deleted file mode 100644 index 7cfbf78..0000000 --- a/gcc/testsuite/gcc.dg/pr14289-3.c +++ /dev/null @@ -1,12 +0,0 @@ -/* PR middle-end/14289 */ -/* { dg-do compile { target i?86-*-* } } */ -/* { dg-options "-O0" } */ - -extern register int a[2] asm("ebx"); /* { dg-error "multiple storage" } */ - -void Nase(void) -{ - int i=6; - a[i]=5; /* { dg-error "address of global" } */ -} - diff --git a/gcc/testsuite/gcc.dg/tls/diag-2.c b/gcc/testsuite/gcc.dg/tls/diag-2.c index 3c5d9bd..5e7e17b 100644 --- a/gcc/testsuite/gcc.dg/tls/diag-2.c +++ b/gcc/testsuite/gcc.dg/tls/diag-2.c @@ -3,19 +3,19 @@ __thread extern int g1; /* { dg-error "'__thread' before 'extern'" } */ __thread static int g2; /* { dg-error "'__thread' before 'static'" } */ __thread __thread int g3; /* { dg-error "duplicate '__thread'" } */ -typedef __thread int g4; /* { dg-error "multiple storage classes" } */ +typedef __thread int g4; /* { dg-error "'__thread' used with 'typedef'" } */ void foo() { - __thread int l1; /* { dg-error "implicitly auto and declared `__thread'" } */ - auto __thread int l2; /* { dg-error "multiple storage classes" } */ + __thread int l1; /* { dg-error "implicitly auto and declared '__thread'" } */ + auto __thread int l2; /* { dg-error "'__thread' used with 'auto'" } */ __thread extern int l3; /* { dg-error "'__thread' before 'extern'" } */ - register __thread int l4; /* { dg-error "multiple storage classes" } */ + register __thread int l4; /* { dg-error "'__thread' used with 'register'" } */ } __thread void f1 (); /* { dg-error "invalid storage class for function" } */ extern __thread void f2 (); /* { dg-error "invalid storage class for function" } */ static __thread void f3 (); /* { dg-error "invalid storage class for function" } */ -__thread void f4 () { } /* { dg-error "function definition declared `__thread'" } */ +__thread void f4 () { } /* { dg-error "function definition declared '__thread'" } */ void bar(__thread int p1); /* { dg-error "storage class specified for parameter" } */ diff --git a/gcc/testsuite/gcc.dg/tls/diag-4.c b/gcc/testsuite/gcc.dg/tls/diag-4.c new file mode 100644 index 0000000..df3705d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tls/diag-4.c @@ -0,0 +1,10 @@ +/* Invalid __thread specifiers. As diag-4.c but some cases in + different orders. */ + +__thread typedef int g4; /* { dg-error "'__thread' used with 'typedef'" } */ + +void foo() +{ + __thread auto int l2; /* { dg-error "'__thread' used with 'auto'" } */ + __thread register int l4; /* { dg-error "'__thread' used with 'register'" } */ +} diff --git a/gcc/testsuite/gcc.dg/tls/diag-5.c b/gcc/testsuite/gcc.dg/tls/diag-5.c new file mode 100644 index 0000000..623832c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tls/diag-5.c @@ -0,0 +1,3 @@ +/* __thread specifiers on empty declarations. */ + +__thread struct foo; /* { dg-warning "warning: useless '__thread' in empty declaration" } */ |
