Fix type of extern array declared in inner scope with outer initialization shadowed...
authorJoseph Myers <joseph@codesourcery.com>
Wed, 6 Feb 2019 01:51:29 +0000 (01:51 +0000)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 6 Feb 2019 01:51:29 +0000 (01:51 +0000)
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

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/redecl-18.c [new file with mode: 0644]

index 1450d65601d7704f88df0aa3f81c40419b84a8dd..9bb8351cc2ce88a65fdab6a974341e479404eb50 100644 (file)
@@ -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
index 65aee4d3e0493449e00ef4818ef4b950d2f7959d..b658eb155bf1eb6b50ddf9b5b41d18a6d29279a1 100644 (file)
@@ -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)
index ac70c7281399a1e06001519759422ebd4264814c..2c6d0e47b5c7789e28b1255ad54a59dc6494b94d 100644 (file)
@@ -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 (file)
index 0000000..f96bbe7
--- /dev/null
@@ -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" } */
+  }
+}