aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2019-02-06 01:51:29 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2019-02-06 01:51:29 +0000
commitfbe83e6b4d0308f547ab11de6dc0eda2741cc11f (patch)
tree7aeeee4d2b0346b478fb60c80c4ce2c67f2e0e10
parente9f061bd28eb2de30d150011a9dbd91a2fc58cf9 (diff)
downloadgcc-fbe83e6b4d0308f547ab11de6dc0eda2741cc11f.zip
gcc-fbe83e6b4d0308f547ab11de6dc0eda2741cc11f.tar.gz
gcc-fbe83e6b4d0308f547ab11de6dc0eda2741cc11f.tar.bz2
Fix type of extern array declared in inner scope with outer initialization shadowed (PR c/88584).
As reported in bug 88584, if you have a file-scope array with external linkage, initialized at file scope, and that array is shadowed at block scope, and is declared again with external linkage and an incomplete type in an inner scope, it is wrongly given a complete type in that inner scope when the correct C semantics give it an incomplete type (only the visible declarations contribute to the type in a given scope). In general, issues with the types of external linkage declarations being different in different scopes were addressed by my fixes for bug 13801, for GCC 4.0. In this case, however, the code in pushdecl dealing with giving declarations the right type in each scope works fine, and the type is subsequently modified by complete_array_type called from finish_decl: finish_decl is trying to complete an array type based on an initializer, but that's only correct for the original initialization at file scope, not for such a declaration in an inner scope (it's harmless but unnecessary in the case where the original declaration is still visible in the inner scope). Thus, this patch changes finish_decl to stop this logic applying for such an external declaration in an inner scope. (An erroneous attempt to include an initializer for an extern variable in an inner scope is diagnosed elsewhere.) This is a regression from GCC 3.4, which properly rejected the code in question (quite likely by accident). Bootstrapped with no regressions on x86_64-pc-linux-gnu. gcc/c: PR c/88584 * c-decl.c (finish_decl): Do not complete array types for arrays with external linkage not at file scope. gcc/testsuite: PR c/88584 * gcc.dg/redecl-18.c: New test. From-SVN: r268571
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-decl.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/redecl-18.c17
4 files changed, 35 insertions, 2 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 1450d65..9bb8351 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-06 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/88584
+ * c-decl.c (finish_decl): Do not complete array types for arrays
+ with external linkage not at file scope.
+
2019-02-05 Richard Biener <rguenther@suse.de>
PR c/88606
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 65aee4d..b658eb1 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5099,10 +5099,15 @@ finish_decl (tree decl, location_t init_loc, tree init,
type = TREE_TYPE (decl);
- /* Deduce size of array from initialization, if not already known. */
+ /* Deduce size of array from initialization, if not already known.
+ This is only needed for an initialization in the current scope;
+ it must not be done for a file-scope initialization of a
+ declaration with external linkage, redeclared in an inner scope
+ with the outer declaration shadowed in an intermediate scope. */
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE
- && TREE_CODE (decl) != TYPE_DECL)
+ && TREE_CODE (decl) != TYPE_DECL
+ && !(TREE_PUBLIC (decl) && current_scope != file_scope))
{
bool do_default
= (TREE_STATIC (decl)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ac70c72..2c6d0e4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-02-06 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/88584
+ * gcc.dg/redecl-18.c: New test.
+
2019-02-05 Jakub Jelinek <jakub@redhat.com>
PR c++/89187
diff --git a/gcc/testsuite/gcc.dg/redecl-18.c b/gcc/testsuite/gcc.dg/redecl-18.c
new file mode 100644
index 0000000..f96bbe7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/redecl-18.c
@@ -0,0 +1,17 @@
+/* Test redeclaration in an inner scope, with an incomplete type, of a
+ file-scope initialized array shadowed in an intermediate scope (bug
+ 88584). */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int a[1] = { 0 };
+
+void
+f (void)
+{
+ int a;
+ {
+ extern int a[];
+ sizeof (a); /* { dg-error "incomplete" } */
+ }
+}