+2004-08-26 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ PR c/13801
+ * c-decl.c (struct c_binding): Add type and inner_comp fields.
+ (bind): Set type and inner_comp fields.
+ (pop_scope): Restore type of decl to the correct type from an
+ outer scope. Give error when popping file scope for incomplete
+ arrays completed incompatibly with default initialization in an
+ inner scope.
+ (diagnose_mismatched_decls): Handle externs with initializers at
+ block scope.
+ (pushdecl): Set type of external declaration at block scope based
+ only on the visible declarations. Save type when changing the
+ type of a declaration. Merge an external declaration at block
+ scope with a visible static declaration at file scope.
+ (implicitly_declare): Give recycled old declaration the new type
+ except for incompatible declarations of built-in functions, saving
+ the old type.
+
2004-08-26 Ziemowit Laski <zlaski@apple.com>
* c-parse.in (OBJC_TYPE_QUAL): New %token for ObjC use.
suppress further errors about that identifier in the current
function.
+ The ->type field stores the type of the declaration in this scope;
+ if NULL, the type is the type of the ->decl field. This is only of
+ relevance for objects with external or internal linkage which may
+ be redeclared in inner scopes, forming composite types that only
+ persist for the duration of those scopes. In the external scope,
+ this stores the composite of all the types declared for this
+ object, visible or not. The ->inner_comp field (used only at file
+ scope) stores whether an incomplete array type at file scope was
+ completed at an inner scope to an array size other than 1.
+
The depth field is copied from the scope structure that holds this
decl. It is used to preserve the proper ordering of the ->shadowed
field (see bind()) and also for a handful of special-case checks.
struct c_binding GTY((chain_next ("%h.prev")))
{
tree decl; /* the decl bound */
+ tree type; /* the type in this scope */
tree id; /* the identifier it's bound to */
struct c_binding *prev; /* the previous decl in this scope */
struct c_binding *shadowed; /* the innermost decl shadowed by this one */
unsigned int depth : 28; /* depth of this scope */
BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */
BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */
- /* two free bits */
+ BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
+ /* one free bit */
};
#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
b->depth = scope->depth;
b->invisible = invisible;
b->nested = nested;
+ b->inner_comp = 0;
+
+ b->type = 0;
b->prev = scope->bindings;
scope->bindings = b;
&& scope != external_scope)
warning ("%Junused variable `%D'", p, p);
+ if (b->inner_comp)
+ {
+ error ("%Jtype of array %qD completed incompatibly with"
+ " implicit initialization", p, p);
+ }
+
/* Fall through. */
case TYPE_DECL:
case CONST_DECL:
if (I_SYMBOL_BINDING (b->id) != b) abort ();
#endif
I_SYMBOL_BINDING (b->id) = b->shadowed;
+ if (b->shadowed && b->shadowed->type)
+ TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
}
break;
else if (!DECL_FILE_SCOPE_P (newdecl))
{
if (DECL_EXTERNAL (newdecl))
- abort ();
+ {
+ /* Extern with initializer at block scope, which will
+ already have received an error. */
+ }
else if (DECL_EXTERNAL (olddecl))
- error ("%Jdeclaration of '%D' with no linkage follows "
- "extern declaration", newdecl, newdecl);
+ {
+ error ("%Jdeclaration of '%D' with no linkage follows "
+ "extern declaration", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ }
else
- error ("%Jredeclaration of '%D' with no linkage",
- newdecl, newdecl);
+ {
+ error ("%Jredeclaration of '%D' with no linkage",
+ newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ }
- locate_old_decl (olddecl, error);
return false;
}
}
b = I_SYMBOL_BINDING (name);
if (b && B_IN_SCOPE (b, scope))
{
+ 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;
else
have compatible type; otherwise, the behavior is undefined.) */
if (DECL_EXTERNAL (x) || scope == file_scope)
{
+ tree type = TREE_TYPE (x);
+ tree vistype = 0;
+ tree visdecl = 0;
+ bool type_saved = false;
+ if (b && !B_IN_EXTERNAL_SCOPE (b)
+ && (TREE_CODE (b->decl) == FUNCTION_DECL
+ || TREE_CODE (b->decl) == VAR_DECL)
+ && DECL_FILE_SCOPE_P (b->decl))
+ {
+ visdecl = b->decl;
+ vistype = TREE_TYPE (visdecl);
+ }
if (warn_nested_externs
&& scope != file_scope
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of '%D'", x);
while (b && !B_IN_EXTERNAL_SCOPE (b))
- b = b->shadowed;
+ {
+ /* If this decl might be modified, save its type. This is
+ done here rather than when the decl is first bound
+ because the type may change after first binding, through
+ being completed or through attributes being added. If we
+ encounter multiple such decls, only the first should have
+ its type saved; the others will already have had their
+ proper types saved and the types will not have changed as
+ their scopes will not have been re-entered. */
+ if (DECL_FILE_SCOPE_P (b->decl) && !type_saved)
+ {
+ b->type = TREE_TYPE (b->decl);
+ type_saved = true;
+ }
+ if (B_IN_FILE_SCOPE (b)
+ && TREE_CODE (b->decl) == VAR_DECL
+ && TREE_STATIC (b->decl)
+ && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
+ && !TYPE_DOMAIN (TREE_TYPE (b->decl))
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+ {
+ /* Array type completed in inner scope, which should be
+ diagnosed if the completion does not have size 1 and
+ it does not get completed in the file scope. */
+ b->inner_comp = true;
+ }
+ b = b->shadowed;
+ }
+
+ /* If a matching external declaration has been found, set its
+ type to the composite of all the types of that declaration.
+ After the consistency checks, it will be reset to the
+ composite of the visible types only. */
+ if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+ && b->type)
+ TREE_TYPE (b->decl) = b->type;
/* The point of the same_translation_unit_p check here is,
we want to detect a duplicate decl for a construct like
&& (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
&& duplicate_decls (x, b->decl))
{
+ tree thistype;
+ thistype = (vistype ? composite_type (vistype, type) : type);
+ b->type = TREE_TYPE (b->decl);
+ if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->type));
+ TREE_TYPE (b->decl) = thistype;
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
return b->decl;
}
else if (TREE_PUBLIC (x))
{
- bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
- nested = true;
+ if (visdecl && !b && duplicate_decls (x, visdecl))
+ {
+ /* An external declaration at block scope referring to a
+ visible entity with internal linkage. The composite
+ type will already be correct for this scope, so we
+ just need to fall through to make the declaration in
+ this scope. */
+ nested = true;
+ }
+ else
+ {
+ bind (name, x, external_scope, /*invisible=*/true,
+ /*nested=*/false);
+ nested = true;
+ }
}
}
/* Similarly, a declaration of a function with static linkage at
tree
implicitly_declare (tree functionid)
{
- tree decl = lookup_name_in_scope (functionid, external_scope);
+ struct c_binding *b;
+ tree decl = 0;
+ for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
+ {
+ if (B_IN_SCOPE (b, external_scope))
+ {
+ decl = b->decl;
+ break;
+ }
+ }
if (decl)
{
}
else
{
+ tree newtype = default_function_type;
+ if (b->type)
+ TREE_TYPE (decl) = b->type;
/* Implicit declaration of a function already declared
(somehow) in a different scope, or as a built-in.
If this is the first time this has happened, warn;
- then recycle the old declaration. */
+ then recycle the old declaration but with the new type. */
if (!C_DECL_IMPLICIT (decl))
{
implicit_decl_warning (functionid, decl);
}
if (DECL_BUILT_IN (decl))
{
- if (!comptypes (default_function_type, TREE_TYPE (decl)))
+ newtype = build_type_attribute_variant (newtype,
+ TYPE_ATTRIBUTES
+ (TREE_TYPE (decl)));
+ if (!comptypes (newtype, TREE_TYPE (decl)))
{
warning ("incompatible implicit declaration of built-in"
" function %qD", decl);
+ newtype = TREE_TYPE (decl);
}
}
else
{
- if (!comptypes (default_function_type, TREE_TYPE (decl)))
+ if (!comptypes (newtype, TREE_TYPE (decl)))
{
error ("incompatible implicit declaration of function %qD",
decl);
locate_old_decl (decl, error);
}
}
+ b->type = TREE_TYPE (decl);
+ TREE_TYPE (decl) = newtype;
bind (functionid, decl, current_scope,
/*invisible=*/false, /*nested=*/true);
return decl;
+2004-08-26 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ PR c/13801
+ * gcc.dg/redecl-3.c, gcc.dg/redecl-4.c, gcc.dg/redecl-6.c,
+ gcc.dg/redecl-7.c, gcc.dg/redecl-8.c, gcc.dg/redecl-9.c,
+ gcc.dg/redecl-10.c, gcc.dg/debug/redecl-1.c,
+ gcc.dg/debug/redecl-2.c, gcc.dg/debug/redecl-3.c,
+ gcc.dg/debug/redecl-4.c, gcc.dg/debug/redecl-5.c: New tests.
+
2004-08-26 Nick Clifton <nickc@redhat.com>
* gcc.c-torture/compile/pr17119.c: New test.
--- /dev/null
+/* Test for multiple declarations and composite types. As in bug
+ 13801. Test no problems in debug information generation. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int IA[];
+typedef int A10[10];
+
+/* Test all combinations of: a variable declared at file scope (no
+ type specifiers, or extern, or static), or just inside a function
+ (with extern), redeclared in an inner scope (with extern), and
+ redeclared in an inner scope when the previous declaration is
+ hidden (with extern, and not if the original declaration was
+ static). Test three times: incomplete variable types; pointers to
+ incomplete types; functions returning such pointers.
+
+ This test only includes the valid code cases, to test debug info
+ generation. (Incomplete static at file scope is not permitted by
+ ISO C, but is accepted by GCC as an extension without
+ -pedantic.) */
+
+A10 a5;
+void
+f5 (void)
+{
+ sizeof(a5);
+ {
+ extern IA a5;
+ sizeof(a5);
+ {
+ int a5;
+ {
+ extern A10 a5;
+ sizeof(a5);
+ }
+ }
+ sizeof(a5);
+ }
+ sizeof(a5);
+}
+extern A10 a5;
+
+A10 a7;
+void
+f7 (void)
+{
+ sizeof(a7);
+ {
+ extern A10 a7;
+ sizeof(a7);
+ {
+ int a7;
+ {
+ extern A10 a7;
+ sizeof(a7);
+ }
+ }
+ sizeof(a7);
+ }
+ sizeof(a7);
+}
+extern A10 a7;
+
+extern A10 a13;
+void
+f13 (void)
+{
+ sizeof(a13);
+ {
+ extern IA a13;
+ sizeof(a13);
+ {
+ int a13;
+ {
+ extern A10 a13;
+ sizeof(a13);
+ }
+ }
+ sizeof(a13);
+ }
+ sizeof(a13);
+}
+extern A10 a13;
+
+extern A10 a15;
+void
+f15 (void)
+{
+ sizeof(a15);
+ {
+ extern A10 a15;
+ sizeof(a15);
+ {
+ int a15;
+ {
+ extern A10 a15;
+ sizeof(a15);
+ }
+ }
+ sizeof(a15);
+ }
+ sizeof(a15);
+}
+extern A10 a15;
+
+
+static A10 a18;
+void
+f18 (void)
+{
+ sizeof(a18);
+ {
+ extern IA a18;
+ sizeof(a18);
+ }
+ sizeof(a18);
+}
+extern A10 a18;
+
+static A10 a19;
+void
+f19 (void)
+{
+ sizeof(a19);
+ {
+ extern A10 a19;
+ sizeof(a19);
+ }
+ sizeof(a19);
+}
+extern A10 a19;
+
+A10 *b5;
+void
+g5 (void)
+{
+ sizeof(*b5);
+ {
+ extern IA *b5;
+ sizeof(*b5);
+ {
+ int b5;
+ {
+ extern A10 *b5;
+ sizeof(*b5);
+ }
+ }
+ sizeof(*b5);
+ }
+ sizeof(*b5);
+}
+extern A10 *b5;
+
+A10 *b7;
+void
+g7 (void)
+{
+ sizeof(*b7);
+ {
+ extern A10 *b7;
+ sizeof(*b7);
+ {
+ int b7;
+ {
+ extern A10 *b7;
+ sizeof(*b7);
+ }
+ }
+ sizeof(*b7);
+ }
+ sizeof(*b7);
+}
+extern A10 *b7;
+
+extern A10 *b13;
+void
+g13 (void)
+{
+ sizeof(*b13);
+ {
+ extern IA *b13;
+ sizeof(*b13);
+ {
+ int b13;
+ {
+ extern A10 *b13;
+ sizeof(*b13);
+ }
+ }
+ sizeof(*b13);
+ }
+ sizeof(*b13);
+}
+extern A10 *b13;
+
+extern A10 *b15;
+void
+g15 (void)
+{
+ sizeof(*b15);
+ {
+ extern A10 *b15;
+ sizeof(*b15);
+ {
+ int b15;
+ {
+ extern A10 *b15;
+ sizeof(*b15);
+ }
+ }
+ sizeof(*b15);
+ }
+ sizeof(*b15);
+}
+extern A10 *b15;
+
+static A10 *b18;
+void
+g18 (void)
+{
+ sizeof(*b18);
+ {
+ extern IA *b18;
+ sizeof(*b18);
+ }
+ sizeof(*b18);
+}
+extern A10 *b18;
+
+static A10 *b19;
+void
+g19 (void)
+{
+ sizeof(*b19);
+ {
+ extern A10 *b19;
+ sizeof(*b19);
+ }
+ sizeof(*b19);
+}
+extern A10 *b19;
+
+A10 *c5 (void);
+void
+h5 (void)
+{
+ sizeof(*c5());
+ {
+ extern IA *c5 (void);
+ sizeof(*c5());
+ {
+ int c5;
+ {
+ extern A10 *c5 (void);
+ sizeof(*c5());
+ }
+ }
+ sizeof(*c5());
+ }
+ sizeof(*c5());
+}
+A10 *c5 (void) { return 0; }
+
+A10 *c7 (void);
+void
+h7 (void)
+{
+ sizeof(*c7());
+ {
+ extern A10 *c7 (void);
+ sizeof(*c7());
+ {
+ int c7;
+ {
+ extern A10 *c7 (void);
+ sizeof(*c7());
+ }
+ }
+ sizeof(*c7());
+ }
+ sizeof(*c7());
+}
+A10 *c7 (void) { return 0; }
+
+extern A10 *c13 (void);
+void
+h13 (void)
+{
+ sizeof(*c13());
+ {
+ extern IA *c13 (void);
+ sizeof(*c13());
+ {
+ int c13;
+ {
+ extern A10 *c13 (void);
+ sizeof(*c13());
+ }
+ }
+ sizeof(*c13());
+ }
+ sizeof(*c13());
+}
+extern A10 *c13 (void) { return 0; }
+
+extern A10 *c15 (void);
+void
+h15 (void)
+{
+ sizeof(*c15());
+ {
+ extern A10 *c15 (void);
+ sizeof(*c15());
+ {
+ int c15;
+ {
+ extern A10 *c15 (void);
+ sizeof(*c15());
+ }
+ }
+ sizeof(*c15());
+ }
+ sizeof(*c15());
+}
+extern A10 *c15 (void) { return 0; }
+
+static A10 *c18 (void);
+void
+h18 (void)
+{
+ sizeof(*c18());
+ {
+ extern IA *c18 (void);
+ sizeof(*c18());
+ }
+ sizeof(*c18());
+}
+static A10 *c18 (void) { return 0; }
+
+static A10 *c19 (void);
+void
+h19 (void)
+{
+ sizeof(*c19());
+ {
+ extern A10 *c19 (void);
+ sizeof(*c19());
+ }
+ sizeof(*c19());
+}
+static A10 *c19 (void) { return 0; }
--- /dev/null
+/* Test for multiple declarations and composite types. As in bug
+ 13801. Illustrates how bug causes correct code to be wrongly
+ diagnosed. Debug test: avoid ICE. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int IA[];
+typedef int A5[5];
+typedef int A10[10];
+
+A10 array10;
+
+A5 *ap;
+void
+f (void)
+{
+ int ap;
+ {
+ extern IA *ap;
+ /* This assignment is valid. */
+ ap = &array10;
+ }
+}
--- /dev/null
+/* Test for multiple declarations and composite types. */
+
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int y[];
+void
+g (void)
+{
+ extern int y[1];
+}
--- /dev/null
+/* Test for multiple declarations and composite types. */
+
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+static int y[];
+void
+g (void)
+{
+ extern int y[1];
+}
--- /dev/null
+/* Test for multiple declarations and composite types, as in bug
+ 13801. Test types saved from outer scopes are up to date. Debug
+ test. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int x[];
+
+void
+f (void)
+{
+ extern int x[];
+}
+
+int x[10];
+
+void
+g (void)
+{
+ int x;
+ {
+ extern int x[10];
+ }
+}
+
+void
+h (void)
+{
+ sizeof (x);
+}
--- /dev/null
+/* Test for multiple declarations and composite types. Check we don't
+ ICE with nested initializers. */
+
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+static int w[];
+void
+f (void)
+{
+ extern int w[] = { 1, 2 }; /* { dg-error "has both" } */
+}
+
+int x[];
+void
+g (void)
+{
+ extern int x[] = { 3, 4, 5 }; /* { dg-error "has both" } */
+}
+
+static int y[];
+void
+h (void)
+{
+ extern int y[] = { 6 }; /* { dg-error "has both" } */
+}
+
+int z[];
+void
+i (void)
+{
+ extern int z[] = { 7 }; /* { dg-error "has both" } */
+}
--- /dev/null
+/* Test for multiple declarations and composite types. Includes bug
+ 13801. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+typedef int IA[];
+typedef int A10[10];
+
+/* Test all combinations of: a variable declared at file scope (no
+ type specifiers, or extern, or static), or just inside a function
+ (with extern), redeclared in an inner scope (with extern), and
+ redeclared in an inner scope when the previous declaration is
+ hidden (with extern, and not if the original declaration was
+ static). Test three times: incomplete variable types; pointers to
+ incomplete types; functions returning such pointers. */
+
+IA a0;
+void
+f0 (void)
+{
+ sizeof(a0); /* { dg-error "incomplete" } */
+ {
+ extern IA a0;
+ sizeof(a0); /* { dg-error "incomplete" } */
+ {
+ int a0;
+ {
+ extern IA a0;
+ sizeof(a0); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a0); /* { dg-error "incomplete" } */
+ }
+ sizeof(a0); /* { dg-error "incomplete" } */
+}
+extern A10 a0;
+
+IA a1;
+void
+f1 (void)
+{
+ sizeof(a1); /* { dg-error "incomplete" } */
+ {
+ extern IA a1;
+ sizeof(a1); /* { dg-error "incomplete" } */
+ {
+ int a1;
+ {
+ extern A10 a1;
+ sizeof(a1);
+ }
+ }
+ sizeof(a1); /* { dg-error "incomplete" } */
+ }
+ sizeof(a1); /* { dg-error "incomplete" } */
+}
+extern A10 a1;
+
+IA a2;
+void
+f2 (void)
+{
+ sizeof(a2); /* { dg-error "incomplete" } */
+ {
+ extern A10 a2;
+ sizeof(a2);
+ {
+ int a2;
+ {
+ extern IA a2;
+ sizeof(a2); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a2);
+ }
+ sizeof(a2); /* { dg-error "incomplete" } */
+}
+extern A10 a2;
+
+IA a3;
+void
+f3 (void)
+{
+ sizeof(a3); /* { dg-error "incomplete" } */
+ {
+ extern A10 a3;
+ sizeof(a3);
+ {
+ int a3;
+ {
+ extern A10 a3;
+ sizeof(a3);
+ }
+ }
+ sizeof(a3);
+ }
+ sizeof(a3); /* { dg-error "incomplete" } */
+}
+extern A10 a3;
+
+A10 a4;
+void
+f4 (void)
+{
+ sizeof(a4);
+ {
+ extern IA a4;
+ sizeof(a4);
+ {
+ int a4;
+ {
+ extern IA a4;
+ sizeof(a4); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a4);
+ }
+ sizeof(a4);
+}
+extern A10 a4;
+
+A10 a5;
+void
+f5 (void)
+{
+ sizeof(a5);
+ {
+ extern IA a5;
+ sizeof(a5);
+ {
+ int a5;
+ {
+ extern A10 a5;
+ sizeof(a5);
+ }
+ }
+ sizeof(a5);
+ }
+ sizeof(a5);
+}
+extern A10 a5;
+
+A10 a6;
+void
+f6 (void)
+{
+ sizeof(a6);
+ {
+ extern A10 a6;
+ sizeof(a6);
+ {
+ int a6;
+ {
+ extern IA a6;
+ sizeof(a6); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a6);
+ }
+ sizeof(a6);
+}
+extern A10 a6;
+
+A10 a7;
+void
+f7 (void)
+{
+ sizeof(a7);
+ {
+ extern A10 a7;
+ sizeof(a7);
+ {
+ int a7;
+ {
+ extern A10 a7;
+ sizeof(a7);
+ }
+ }
+ sizeof(a7);
+ }
+ sizeof(a7);
+}
+extern A10 a7;
+
+extern IA a8;
+void
+f8 (void)
+{
+ sizeof(a8); /* { dg-error "incomplete" } */
+ {
+ extern IA a8;
+ sizeof(a8); /* { dg-error "incomplete" } */
+ {
+ int a8;
+ {
+ extern IA a8;
+ sizeof(a8); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a8); /* { dg-error "incomplete" } */
+ }
+ sizeof(a8); /* { dg-error "incomplete" } */
+}
+extern A10 a8;
+
+extern IA a9;
+void
+f9 (void)
+{
+ sizeof(a9); /* { dg-error "incomplete" } */
+ {
+ extern IA a9;
+ sizeof(a9); /* { dg-error "incomplete" } */
+ {
+ int a9;
+ {
+ extern A10 a9;
+ sizeof(a9);
+ }
+ }
+ sizeof(a9); /* { dg-error "incomplete" } */
+ }
+ sizeof(a9); /* { dg-error "incomplete" } */
+}
+extern A10 a9;
+
+extern IA a10;
+void
+f10 (void)
+{
+ sizeof(a10); /* { dg-error "incomplete" } */
+ {
+ extern A10 a10;
+ sizeof(a10);
+ {
+ int a10;
+ {
+ extern IA a10;
+ sizeof(a10); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a10);
+ }
+ sizeof(a10); /* { dg-error "incomplete" } */
+}
+extern A10 a10;
+
+extern IA a11;
+void
+f11 (void)
+{
+ sizeof(a11); /* { dg-error "incomplete" } */
+ {
+ extern A10 a11;
+ sizeof(a11);
+ {
+ int a11;
+ {
+ extern A10 a11;
+ sizeof(a11);
+ }
+ }
+ sizeof(a11);
+ }
+ sizeof(a11); /* { dg-error "incomplete" } */
+}
+extern A10 a11;
+
+extern A10 a12;
+void
+f12 (void)
+{
+ sizeof(a12);
+ {
+ extern IA a12;
+ sizeof(a12);
+ {
+ int a12;
+ {
+ extern IA a12;
+ sizeof(a12); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a12);
+ }
+ sizeof(a12);
+}
+extern A10 a12;
+
+extern A10 a13;
+void
+f13 (void)
+{
+ sizeof(a13);
+ {
+ extern IA a13;
+ sizeof(a13);
+ {
+ int a13;
+ {
+ extern A10 a13;
+ sizeof(a13);
+ }
+ }
+ sizeof(a13);
+ }
+ sizeof(a13);
+}
+extern A10 a13;
+
+extern A10 a14;
+void
+f14 (void)
+{
+ sizeof(a14);
+ {
+ extern A10 a14;
+ sizeof(a14);
+ {
+ int a14;
+ {
+ extern IA a14;
+ sizeof(a14); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(a14);
+ }
+ sizeof(a14);
+}
+extern A10 a14;
+
+extern A10 a15;
+void
+f15 (void)
+{
+ sizeof(a15);
+ {
+ extern A10 a15;
+ sizeof(a15);
+ {
+ int a15;
+ {
+ extern A10 a15;
+ sizeof(a15);
+ }
+ }
+ sizeof(a15);
+ }
+ sizeof(a15);
+}
+extern A10 a15;
+
+static IA a16;
+void
+f16 (void)
+{
+ sizeof(a16); /* { dg-error "incomplete" } */
+ {
+ extern IA a16;
+ sizeof(a16); /* { dg-error "incomplete" } */
+ }
+ sizeof(a16); /* { dg-error "incomplete" } */
+}
+extern A10 a16;
+
+static IA a17;
+void
+f17 (void)
+{
+ sizeof(a17); /* { dg-error "incomplete" } */
+ {
+ extern A10 a17;
+ sizeof(a17);
+ }
+ sizeof(a17); /* { dg-error "incomplete" } */
+}
+extern A10 a17;
+
+static A10 a18;
+void
+f18 (void)
+{
+ sizeof(a18);
+ {
+ extern IA a18;
+ sizeof(a18);
+ }
+ sizeof(a18);
+}
+extern A10 a18;
+
+static A10 a19;
+void
+f19 (void)
+{
+ sizeof(a19);
+ {
+ extern A10 a19;
+ sizeof(a19);
+ }
+ sizeof(a19);
+}
+extern A10 a19;
+
+IA *b0;
+void
+g0 (void)
+{
+ sizeof(*b0); /* { dg-error "incomplete" } */
+ {
+ extern IA *b0;
+ sizeof(*b0); /* { dg-error "incomplete" } */
+ {
+ int b0;
+ {
+ extern IA *b0;
+ sizeof(*b0); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b0); /* { dg-error "incomplete" } */
+ }
+ sizeof(*b0); /* { dg-error "incomplete" } */
+}
+extern A10 *b0;
+
+IA *b1;
+void
+g1 (void)
+{
+ sizeof(*b1); /* { dg-error "incomplete" } */
+ {
+ extern IA *b1;
+ sizeof(*b1); /* { dg-error "incomplete" } */
+ {
+ int b1;
+ {
+ extern A10 *b1;
+ sizeof(*b1);
+ }
+ }
+ sizeof(*b1); /* { dg-error "incomplete" } */
+ }
+ sizeof(*b1); /* { dg-error "incomplete" } */
+}
+extern A10 *b1;
+
+IA *b2;
+void
+g2 (void)
+{
+ sizeof(*b2); /* { dg-error "incomplete" } */
+ {
+ extern A10 *b2;
+ sizeof(*b2);
+ {
+ int b2;
+ {
+ extern IA *b2;
+ sizeof(*b2); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b2);
+ }
+ sizeof(*b2); /* { dg-error "incomplete" } */
+}
+extern A10 *b2;
+
+IA *b3;
+void
+g3 (void)
+{
+ sizeof(*b3); /* { dg-error "incomplete" } */
+ {
+ extern A10 *b3;
+ sizeof(*b3);
+ {
+ int b3;
+ {
+ extern A10 *b3;
+ sizeof(*b3);
+ }
+ }
+ sizeof(*b3);
+ }
+ sizeof(*b3); /* { dg-error "incomplete" } */
+}
+extern A10 *b3;
+
+A10 *b4;
+void
+g4 (void)
+{
+ sizeof(*b4);
+ {
+ extern IA *b4;
+ sizeof(*b4);
+ {
+ int b4;
+ {
+ extern IA *b4;
+ sizeof(*b4); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b4);
+ }
+ sizeof(*b4);
+}
+extern A10 *b4;
+
+A10 *b5;
+void
+g5 (void)
+{
+ sizeof(*b5);
+ {
+ extern IA *b5;
+ sizeof(*b5);
+ {
+ int b5;
+ {
+ extern A10 *b5;
+ sizeof(*b5);
+ }
+ }
+ sizeof(*b5);
+ }
+ sizeof(*b5);
+}
+extern A10 *b5;
+
+A10 *b6;
+void
+g6 (void)
+{
+ sizeof(*b6);
+ {
+ extern A10 *b6;
+ sizeof(*b6);
+ {
+ int b6;
+ {
+ extern IA *b6;
+ sizeof(*b6); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b6);
+ }
+ sizeof(*b6);
+}
+extern A10 *b6;
+
+A10 *b7;
+void
+g7 (void)
+{
+ sizeof(*b7);
+ {
+ extern A10 *b7;
+ sizeof(*b7);
+ {
+ int b7;
+ {
+ extern A10 *b7;
+ sizeof(*b7);
+ }
+ }
+ sizeof(*b7);
+ }
+ sizeof(*b7);
+}
+extern A10 *b7;
+
+extern IA *b8;
+void
+g8 (void)
+{
+ sizeof(*b8); /* { dg-error "incomplete" } */
+ {
+ extern IA *b8;
+ sizeof(*b8); /* { dg-error "incomplete" } */
+ {
+ int b8;
+ {
+ extern IA *b8;
+ sizeof(*b8); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b8); /* { dg-error "incomplete" } */
+ }
+ sizeof(*b8); /* { dg-error "incomplete" } */
+}
+extern A10 *b8;
+
+extern IA *b9;
+void
+g9 (void)
+{
+ sizeof(*b9); /* { dg-error "incomplete" } */
+ {
+ extern IA *b9;
+ sizeof(*b9); /* { dg-error "incomplete" } */
+ {
+ int b9;
+ {
+ extern A10 *b9;
+ sizeof(*b9);
+ }
+ }
+ sizeof(*b9); /* { dg-error "incomplete" } */
+ }
+ sizeof(*b9); /* { dg-error "incomplete" } */
+}
+extern A10 *b9;
+
+extern IA *b10;
+void
+g10 (void)
+{
+ sizeof(*b10); /* { dg-error "incomplete" } */
+ {
+ extern A10 *b10;
+ sizeof(*b10);
+ {
+ int b10;
+ {
+ extern IA *b10;
+ sizeof(*b10); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b10);
+ }
+ sizeof(*b10); /* { dg-error "incomplete" } */
+}
+extern A10 *b10;
+
+extern IA *b11;
+void
+g11 (void)
+{
+ sizeof(*b11); /* { dg-error "incomplete" } */
+ {
+ extern A10 *b11;
+ sizeof(*b11);
+ {
+ int b11;
+ {
+ extern A10 *b11;
+ sizeof(*b11);
+ }
+ }
+ sizeof(*b11);
+ }
+ sizeof(*b11); /* { dg-error "incomplete" } */
+}
+extern A10 *b11;
+
+extern A10 *b12;
+void
+g12 (void)
+{
+ sizeof(*b12);
+ {
+ extern IA *b12;
+ sizeof(*b12);
+ {
+ int b12;
+ {
+ extern IA *b12;
+ sizeof(*b12); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b12);
+ }
+ sizeof(*b12);
+}
+extern A10 *b12;
+
+extern A10 *b13;
+void
+g13 (void)
+{
+ sizeof(*b13);
+ {
+ extern IA *b13;
+ sizeof(*b13);
+ {
+ int b13;
+ {
+ extern A10 *b13;
+ sizeof(*b13);
+ }
+ }
+ sizeof(*b13);
+ }
+ sizeof(*b13);
+}
+extern A10 *b13;
+
+extern A10 *b14;
+void
+g14 (void)
+{
+ sizeof(*b14);
+ {
+ extern A10 *b14;
+ sizeof(*b14);
+ {
+ int b14;
+ {
+ extern IA *b14;
+ sizeof(*b14); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*b14);
+ }
+ sizeof(*b14);
+}
+extern A10 *b14;
+
+extern A10 *b15;
+void
+g15 (void)
+{
+ sizeof(*b15);
+ {
+ extern A10 *b15;
+ sizeof(*b15);
+ {
+ int b15;
+ {
+ extern A10 *b15;
+ sizeof(*b15);
+ }
+ }
+ sizeof(*b15);
+ }
+ sizeof(*b15);
+}
+extern A10 *b15;
+
+static IA *b16;
+void
+g16 (void)
+{
+ sizeof(*b16); /* { dg-error "incomplete" } */
+ {
+ extern IA *b16;
+ sizeof(*b16); /* { dg-error "incomplete" } */
+ }
+ sizeof(*b16); /* { dg-error "incomplete" } */
+}
+extern A10 *b16;
+
+static IA *b17;
+void
+g17 (void)
+{
+ sizeof(*b17); /* { dg-error "incomplete" } */
+ {
+ extern A10 *b17;
+ sizeof(*b17);
+ }
+ sizeof(*b17); /* { dg-error "incomplete" } */
+}
+extern A10 *b17;
+
+static A10 *b18;
+void
+g18 (void)
+{
+ sizeof(*b18);
+ {
+ extern IA *b18;
+ sizeof(*b18);
+ }
+ sizeof(*b18);
+}
+extern A10 *b18;
+
+static A10 *b19;
+void
+g19 (void)
+{
+ sizeof(*b19);
+ {
+ extern A10 *b19;
+ sizeof(*b19);
+ }
+ sizeof(*b19);
+}
+extern A10 *b19;
+
+IA *c0 (void);
+void
+h0 (void)
+{
+ sizeof(*c0()); /* { dg-error "incomplete" } */
+ {
+ extern IA *c0 (void);
+ sizeof(*c0()); /* { dg-error "incomplete" } */
+ {
+ int c0;
+ {
+ extern IA *c0 (void);
+ sizeof(*c0()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c0()); /* { dg-error "incomplete" } */
+ }
+ sizeof(*c0()); /* { dg-error "incomplete" } */
+}
+A10 *c0 (void) { return 0; }
+
+IA *c1 (void);
+void
+h1 (void)
+{
+ sizeof(*c1()); /* { dg-error "incomplete" } */
+ {
+ extern IA *c1 (void);
+ sizeof(*c1()); /* { dg-error "incomplete" } */
+ {
+ int c1;
+ {
+ extern A10 *c1 (void);
+ sizeof(*c1());
+ }
+ }
+ sizeof(*c1()); /* { dg-error "incomplete" } */
+ }
+ sizeof(*c1()); /* { dg-error "incomplete" } */
+}
+A10 *c1 (void) { return 0; }
+
+IA *c2 (void);
+void
+h2 (void)
+{
+ sizeof(*c2()); /* { dg-error "incomplete" } */
+ {
+ extern A10 *c2 (void);
+ sizeof(*c2());
+ {
+ int c2;
+ {
+ extern IA *c2 (void);
+ sizeof(*c2()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c2());
+ }
+ sizeof(*c2()); /* { dg-error "incomplete" } */
+}
+A10 *c2 (void) { return 0; }
+
+IA *c3 (void);
+void
+h3 (void)
+{
+ sizeof(*c3()); /* { dg-error "incomplete" } */
+ {
+ extern A10 *c3 (void);
+ sizeof(*c3());
+ {
+ int c3;
+ {
+ extern A10 *c3 (void);
+ sizeof(*c3());
+ }
+ }
+ sizeof(*c3());
+ }
+ sizeof(*c3()); /* { dg-error "incomplete" } */
+}
+A10 *c3 (void) { return 0; }
+
+A10 *c4 (void);
+void
+h4 (void)
+{
+ sizeof(*c4());
+ {
+ extern IA *c4 (void);
+ sizeof(*c4());
+ {
+ int c4;
+ {
+ extern IA *c4 (void);
+ sizeof(*c4()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c4());
+ }
+ sizeof(*c4());
+}
+A10 *c4 (void) { return 0; }
+
+A10 *c5 (void);
+void
+h5 (void)
+{
+ sizeof(*c5());
+ {
+ extern IA *c5 (void);
+ sizeof(*c5());
+ {
+ int c5;
+ {
+ extern A10 *c5 (void);
+ sizeof(*c5());
+ }
+ }
+ sizeof(*c5());
+ }
+ sizeof(*c5());
+}
+A10 *c5 (void) { return 0; }
+
+A10 *c6 (void);
+void
+h6 (void)
+{
+ sizeof(*c6());
+ {
+ extern A10 *c6 (void);
+ sizeof(*c6());
+ {
+ int c6;
+ {
+ extern IA *c6 (void);
+ sizeof(*c6()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c6());
+ }
+ sizeof(*c6());
+}
+A10 *c6 (void) { return 0; }
+
+A10 *c7 (void);
+void
+h7 (void)
+{
+ sizeof(*c7());
+ {
+ extern A10 *c7 (void);
+ sizeof(*c7());
+ {
+ int c7;
+ {
+ extern A10 *c7 (void);
+ sizeof(*c7());
+ }
+ }
+ sizeof(*c7());
+ }
+ sizeof(*c7());
+}
+A10 *c7 (void) { return 0; }
+
+extern IA *c8 (void);
+void
+h8 (void)
+{
+ sizeof(*c8()); /* { dg-error "incomplete" } */
+ {
+ extern IA *c8 (void);
+ sizeof(*c8()); /* { dg-error "incomplete" } */
+ {
+ int c8;
+ {
+ extern IA *c8 (void);
+ sizeof(*c8()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c8()); /* { dg-error "incomplete" } */
+ }
+ sizeof(*c8()); /* { dg-error "incomplete" } */
+}
+extern A10 *c8 (void) { return 0; }
+
+extern IA *c9 (void);
+void
+h9 (void)
+{
+ sizeof(*c9()); /* { dg-error "incomplete" } */
+ {
+ extern IA *c9 (void);
+ sizeof(*c9()); /* { dg-error "incomplete" } */
+ {
+ int c9;
+ {
+ extern A10 *c9 (void);
+ sizeof(*c9());
+ }
+ }
+ sizeof(*c9()); /* { dg-error "incomplete" } */
+ }
+ sizeof(*c9()); /* { dg-error "incomplete" } */
+}
+extern A10 *c9 (void) { return 0; }
+
+extern IA *c10 (void);
+void
+h10 (void)
+{
+ sizeof(*c10()); /* { dg-error "incomplete" } */
+ {
+ extern A10 *c10 (void);
+ sizeof(*c10());
+ {
+ int c10;
+ {
+ extern IA *c10 (void);
+ sizeof(*c10()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c10());
+ }
+ sizeof(*c10()); /* { dg-error "incomplete" } */
+}
+extern A10 *c10 (void) { return 0; }
+
+extern IA *c11 (void);
+void
+h11 (void)
+{
+ sizeof(*c11()); /* { dg-error "incomplete" } */
+ {
+ extern A10 *c11 (void);
+ sizeof(*c11());
+ {
+ int c11;
+ {
+ extern A10 *c11 (void);
+ sizeof(*c11());
+ }
+ }
+ sizeof(*c11());
+ }
+ sizeof(*c11()); /* { dg-error "incomplete" } */
+}
+extern A10 *c11 (void) { return 0; }
+
+extern A10 *c12 (void);
+void
+h12 (void)
+{
+ sizeof(*c12());
+ {
+ extern IA *c12 (void);
+ sizeof(*c12());
+ {
+ int c12;
+ {
+ extern IA *c12 (void);
+ sizeof(*c12()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c12());
+ }
+ sizeof(*c12());
+}
+extern A10 *c12 (void) { return 0; }
+
+extern A10 *c13 (void);
+void
+h13 (void)
+{
+ sizeof(*c13());
+ {
+ extern IA *c13 (void);
+ sizeof(*c13());
+ {
+ int c13;
+ {
+ extern A10 *c13 (void);
+ sizeof(*c13());
+ }
+ }
+ sizeof(*c13());
+ }
+ sizeof(*c13());
+}
+extern A10 *c13 (void) { return 0; }
+
+extern A10 *c14 (void);
+void
+h14 (void)
+{
+ sizeof(*c14());
+ {
+ extern A10 *c14 (void);
+ sizeof(*c14());
+ {
+ int c14;
+ {
+ extern IA *c14 (void);
+ sizeof(*c14()); /* { dg-error "incomplete" } */
+ }
+ }
+ sizeof(*c14());
+ }
+ sizeof(*c14());
+}
+extern A10 *c14 (void) { return 0; }
+
+extern A10 *c15 (void);
+void
+h15 (void)
+{
+ sizeof(*c15());
+ {
+ extern A10 *c15 (void);
+ sizeof(*c15());
+ {
+ int c15;
+ {
+ extern A10 *c15 (void);
+ sizeof(*c15());
+ }
+ }
+ sizeof(*c15());
+ }
+ sizeof(*c15());
+}
+extern A10 *c15 (void) { return 0; }
+
+static IA *c16 (void);
+void
+h16 (void)
+{
+ sizeof(*c16()); /* { dg-error "incomplete" } */
+ {
+ extern IA *c16 (void);
+ sizeof(*c16()); /* { dg-error "incomplete" } */
+ }
+ sizeof(*c16()); /* { dg-error "incomplete" } */
+}
+static A10 *c16 (void) { return 0; }
+
+static IA *c17 (void);
+void
+h17 (void)
+{
+ sizeof(*c17()); /* { dg-error "incomplete" } */
+ {
+ extern A10 *c17 (void);
+ sizeof(*c17());
+ }
+ sizeof(*c17()); /* { dg-error "incomplete" } */
+}
+static A10 *c17 (void) { return 0; }
+
+static A10 *c18 (void);
+void
+h18 (void)
+{
+ sizeof(*c18());
+ {
+ extern IA *c18 (void);
+ sizeof(*c18());
+ }
+ sizeof(*c18());
+}
+static A10 *c18 (void) { return 0; }
+
+static A10 *c19 (void);
+void
+h19 (void)
+{
+ sizeof(*c19());
+ {
+ extern A10 *c19 (void);
+ sizeof(*c19());
+ }
+ sizeof(*c19());
+}
+static A10 *c19 (void) { return 0; }
--- /dev/null
+/* Test for multiple declarations and composite types, with built-in
+ functions. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=c89 -Wformat -g" } */
+
+void
+f (void)
+{
+ int printf;
+ int strcmp;
+ {
+ int printf (const char *, ...);
+ int strcmp ();
+ /* Should get format warnings even though the built-in declaration
+ isn't "visible". */
+ printf ("%s", 1); /* { dg-warning "format" } */
+ /* The type of strcmp here should have no prototype. */
+ if (0)
+ strcmp (1);
+ /* Likewise, implicitly declared memcmp. */
+ if (0)
+ memcmp (1);
+ }
+}
+
+/* Should still diagnose incompatible prototype for strcmp. */
+int strcmp (void); /* { dg-error "conflict" } */
--- /dev/null
+/* Test for multiple declarations and composite types. As in bug
+ 13801. Illustrates how bug causes correct code to be wrongly
+ diagnosed. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int IA[];
+typedef int A5[5];
+typedef int A10[10];
+
+A10 array10;
+
+A5 *ap;
+void
+f (void)
+{
+ int ap;
+ {
+ extern IA *ap;
+ /* This assignment is valid. */
+ ap = &array10;
+ }
+}
--- /dev/null
+/* Test for multiple declarations and composite types. Diagnosis of
+ completion incompatible with implicit initializer. */
+
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+int x[];
+
+void
+f (void)
+{
+ extern int x[2]; /* { dg-error "completed incompatibly" } */
+}
+
+/* The following is OK. */
+
+int y[];
+void
+g (void)
+{
+ extern int y[1];
+}
--- /dev/null
+/* Test for multiple declarations and composite types. Diagnosis of
+ completion incompatible with implicit initializer. */
+
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+static int x[];
+
+void
+f (void)
+{
+ extern int x[2]; /* { dg-error "completed incompatibly" } */
+}
+
+/* The following is OK. */
+
+static int y[];
+void
+g (void)
+{
+ extern int y[1];
+}
--- /dev/null
+/* Test for multiple declarations and composite types, as in bug
+ 13801. Test types saved from outer scopes are up to date. */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int x[];
+
+void
+f (void)
+{
+ extern int x[];
+}
+
+int x[10];
+
+void
+g (void)
+{
+ int x;
+ {
+ extern int x[10];
+ }
+}
+
+void
+h (void)
+{
+ sizeof (x);
+}