diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82d7ba0629d..ffdd2bbff2a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-05-10 Joseph S. Myers + + PR c/21342 + * c-decl.c (pushdecl): When there is a declaration in the current + scope and the declarations are external linkage, check for + compatibility with the type in the external scope and update the + type in the external scope with the composite type information. + Do not form a composite type of the new type and the visible type + if they are incompatible. + 2005-05-10 Nathan Sidwell * crtstuff.c: Revert part of 2005-05-08 Change. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index e7ac0d3690d..0ca4500021e 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2029,11 +2029,52 @@ pushdecl (tree x) b = I_SYMBOL_BINDING (name); if (b && B_IN_SCOPE (b, scope)) { + struct c_binding *b_ext, *b_use; + tree type = TREE_TYPE (x); + tree visdecl = b->decl; + tree vistype = TREE_TYPE (visdecl); if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE && COMPLETE_TYPE_P (TREE_TYPE (x))) b->inner_comp = false; - if (duplicate_decls (x, b->decl)) - return b->decl; + b_use = b; + b_ext = b; + /* If this is an external linkage declaration, we should check + for compatibility with the type in the external scope before + setting the type at this scope based on the visible + information only. */ + if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl)) + { + while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext)) + b_ext = b_ext->shadowed; + if (b_ext) + { + b_use = b_ext; + if (b_use->type) + TREE_TYPE (b_use->decl) = b_use->type; + } + } + if (duplicate_decls (x, b_use->decl)) + { + if (b_use != b) + { + /* Save the updated type in the external scope and + restore the proper type for this scope. */ + tree thistype; + if (comptypes (vistype, type)) + thistype = composite_type (vistype, type); + else + thistype = TREE_TYPE (b_use->decl); + b_use->type = TREE_TYPE (b_use->decl); + if (TREE_CODE (b_use->decl) == FUNCTION_DECL + && DECL_BUILT_IN (b_use->decl)) + thistype + = build_type_attribute_variant (thistype, + TYPE_ATTRIBUTES + (b_use->type)); + TREE_TYPE (b_use->decl) = thistype; + } + return b_use->decl; + } else goto skip_external_and_shadow_checks; } @@ -2120,7 +2161,15 @@ pushdecl (tree x) && duplicate_decls (x, b->decl)) { tree thistype; - thistype = (vistype ? composite_type (vistype, type) : type); + if (vistype) + { + if (comptypes (vistype, type)) + thistype = composite_type (vistype, type); + else + thistype = TREE_TYPE (b->decl); + } + else + thistype = type; b->type = TREE_TYPE (b->decl); if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl)) thistype diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 55605df8f03..7dd2e1970d9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-05-10 Joseph S. Myers + + PR c/21342 + * gcc.dg/redecl-11.c, gcc.dg/redecl-12.c, gcc.dg/redecl-13.c, + gcc.dg/redecl-14.c, gcc.dg/redecl-15.c: New tests. + 2005-05-10 Ben Elliston PR debug/16676 diff --git a/gcc/testsuite/gcc.dg/redecl-11.c b/gcc/testsuite/gcc.dg/redecl-11.c new file mode 100644 index 00000000000..a0554d9476d --- /dev/null +++ b/gcc/testsuite/gcc.dg/redecl-11.c @@ -0,0 +1,9 @@ +/* Some incompatible external linkage declarations were not diagnosed. + Bug 21342. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +int f(int (*)[]); +void g() { int f(int (*)[2]); } /* { dg-error "error: previous declaration of 'f' was here" } */ +int f(int (*)[3]); /* { dg-error "error: conflicting types for 'f'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-12.c b/gcc/testsuite/gcc.dg/redecl-12.c new file mode 100644 index 00000000000..cb1501d30ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/redecl-12.c @@ -0,0 +1,9 @@ +/* Some incompatible external linkage declarations were not diagnosed. + Bug 21342. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +extern int a[]; +void f(void) { extern int a[]; extern int a[10]; } /* { dg-error "error: previous declaration of 'a' was here" } */ +extern int a[5]; /* { dg-error "error: conflicting types for 'a'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-13.c b/gcc/testsuite/gcc.dg/redecl-13.c new file mode 100644 index 00000000000..54be4dbc2ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/redecl-13.c @@ -0,0 +1,9 @@ +/* Some incompatible external linkage declarations were not diagnosed. + Bug 21342. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +extern int a[]; +void f(void) { extern int a[10]; } /* { dg-error "error: previous declaration of 'a' was here" } */ +extern int a[5]; /* { dg-error "error: conflicting types for 'a'" } */ diff --git a/gcc/testsuite/gcc.dg/redecl-14.c b/gcc/testsuite/gcc.dg/redecl-14.c new file mode 100644 index 00000000000..ed196106361 --- /dev/null +++ b/gcc/testsuite/gcc.dg/redecl-14.c @@ -0,0 +1,22 @@ +/* Some incompatible external linkage declarations were not diagnosed. + Bug 21342. Test type in inner scope is correct. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +typedef int IA[]; +typedef int IA5[5]; +typedef IA *IAP; +typedef IA5 *IA5P; +extern IAP a[]; +void +f (void) +{ + { + extern IA5P a[]; + sizeof (*a[0]); + } + extern IAP a[]; + extern IAP a[5]; + sizeof (*a[0]); /* { dg-error "error: invalid application of 'sizeof' to incomplete type 'IA'" } */ +} diff --git a/gcc/testsuite/gcc.dg/redecl-15.c b/gcc/testsuite/gcc.dg/redecl-15.c new file mode 100644 index 00000000000..c4ac76cc8cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/redecl-15.c @@ -0,0 +1,14 @@ +/* Test for ICE with redeclaration in inner scope which is accepted + despite incompatible type. */ +/* Origin: Joseph Myers */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +f (void) +{ + g(); /* { dg-warning "warning: previous implicit declaration of 'g' was here" } */ + { + void g(); /* { dg-warning "warning: conflicting types for 'g'" } */ + } +}