Commit 6fb58bba by Joseph Myers Committed by Joseph Myers

re PR c/15698 (no error in presence of broken builtin fn + K&R declaration)

	PR c/15698
	* c-tree.h (C_DECL_BUILTIN_PROTOTYPE): New.
	* c-decl.c (current_function_prototype_built_in,
	current_function_prototype_arg_types): New.
	(merge_decls): Keep source location of prototype followed by
	nonprototype declaration.  Update C_DECL_BUILTIN_PROTOTYPE.
	(builtin_function): Set C_DECL_BUILTIN_PROTOTYPE.
	(start_function): Always set current_function_prototype_locus,
	current_function_prototype_built_in and
	current_function_prototype_arg_types.  Check for external
	prototype whether or not visible for external function and set
	current_function_prototype_arg_types accordingly.
	(store_parm_decls_oldstyle): Use
	current_function_prototype_arg_types for checking old-style
	definition against prototype.  Give warnings only if
	current_function_prototype_built_in).

testsuite:
	* gcc.dg/builtins-30.c: Update expected messages.
	* gcc.dg/pr15698-1.c, gcc.dg/pr15698-2.c, gcc.dg/pr15698-3.c,
	gcc.dg/pr15698-4.c, gcc.dg/pr15698-5.c, gcc.dg/pr15698-6.c,
	gcc.dg/pr15698-7.c, pr15698-8.c: New tests.

From-SVN: r99118
parent 806aa901
2005-05-02 Joseph S. Myers <joseph@codesourcery.com>
PR c/15698
* c-tree.h (C_DECL_BUILTIN_PROTOTYPE): New.
* c-decl.c (current_function_prototype_built_in,
current_function_prototype_arg_types): New.
(merge_decls): Keep source location of prototype followed by
nonprototype declaration. Update C_DECL_BUILTIN_PROTOTYPE.
(builtin_function): Set C_DECL_BUILTIN_PROTOTYPE.
(start_function): Always set current_function_prototype_locus,
current_function_prototype_built_in and
current_function_prototype_arg_types. Check for external
prototype whether or not visible for external function and set
current_function_prototype_arg_types accordingly.
(store_parm_decls_oldstyle): Use
current_function_prototype_arg_types for checking old-style
definition against prototype. Give warnings only if
current_function_prototype_built_in).
2005-05-02 Daniel Jacobowitz <dan@codesourcery.com>
* ggc.h (ggc_alloc_zone_pass_stat): New macro.
......
......@@ -98,6 +98,14 @@ static int enum_overflow;
static location_t current_function_prototype_locus;
/* Whether this prototype was built-in. */
static bool current_function_prototype_built_in;
/* The argument type information of this prototype. */
static tree current_function_prototype_arg_types;
/* The argument information structure for the function currently being
defined. */
......@@ -1574,6 +1582,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
/* For real parm decl following a forward decl, rechain the old decl
in its new location and clear TREE_ASM_WRITTEN (it's not a
......@@ -1647,8 +1659,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
/* Keep source location of definition rather than declaration. */
if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
/* Keep source location of definition rather than declaration and of
prototype rather than non-prototype unless that prototype is
built-in. */
if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
|| (old_is_prototype && !new_is_prototype
&& !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
/* Merge the unused-warning information. */
......@@ -1764,6 +1780,11 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
C_DECL_DECLARED_BUILTIN (newdecl) = 1;
if (new_is_prototype)
C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
else
C_DECL_BUILTIN_PROTOTYPE (newdecl)
= C_DECL_BUILTIN_PROTOTYPE (olddecl);
}
/* Also preserve various other info from the definition. */
......@@ -2706,6 +2727,7 @@ builtin_function (const char *name, tree type, int function_code,
DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
DECL_BUILT_IN_CLASS (decl) = cl;
DECL_FUNCTION_CODE (decl) = function_code;
C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
......@@ -5716,14 +5738,53 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
TREE_TYPE (TREE_TYPE (old_decl)))
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
{
TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
TREE_TYPE (decl1));
current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
current_function_prototype_locus = UNKNOWN_LOCATION;
current_function_prototype_built_in = false;
current_function_prototype_arg_types = NULL_TREE;
if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
{
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
TREE_TYPE (TREE_TYPE (old_decl))))
{
TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
TREE_TYPE (decl1));
current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
current_function_prototype_built_in
= C_DECL_BUILTIN_PROTOTYPE (old_decl);
current_function_prototype_arg_types
= TYPE_ARG_TYPES (TREE_TYPE (decl1));
}
if (TREE_PUBLIC (decl1))
{
/* If there is an external prototype declaration of this
function, record its location but do not copy information
to this decl. This may be an invisible declaration
(built-in or in a scope which has finished) or simply
have more refined argument types than any declaration
found above. */
struct c_binding *b;
for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
if (B_IN_SCOPE (b, external_scope))
break;
if (b)
{
tree ext_decl, ext_type;
ext_decl = b->decl;
ext_type = b->type ? b->type : TREE_TYPE (ext_decl);
if (TREE_CODE (ext_type) == FUNCTION_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
TREE_TYPE (ext_type)))
{
current_function_prototype_locus
= DECL_SOURCE_LOCATION (ext_decl);
current_function_prototype_built_in
= C_DECL_BUILTIN_PROTOTYPE (ext_decl);
current_function_prototype_arg_types
= TYPE_ARG_TYPES (ext_type);
}
}
}
}
/* Optionally warn of old-fashioned def with no previous prototype. */
......@@ -6063,11 +6124,11 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
set the DECL_ARG_TYPE of each argument according to
the type previously specified, and report any mismatches. */
if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
if (current_function_prototype_arg_types)
{
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
type = current_function_prototype_arg_types;
parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
!= void_type_node));
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
......@@ -6075,9 +6136,15 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
if (parm == 0 || type == 0
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
error ("number of arguments doesn%'t match prototype");
error ("%Hprototype declaration",
&current_function_prototype_locus);
if (current_function_prototype_built_in)
warning (0, "number of arguments doesn%'t match "
"built-in prototype");
else
{
error ("number of arguments doesn%'t match prototype");
error ("%Hprototype declaration",
&current_function_prototype_locus);
}
break;
}
/* Type for passing arg must be consistent with that
......@@ -6104,17 +6171,33 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
if (pedantic)
{
pedwarn ("promoted argument %qD "
"doesn%'t match prototype", parm);
pedwarn ("%Hprototype declaration",
&current_function_prototype_locus);
/* ??? Is it possible to get here with a
built-in prototype or will it always have
been diagnosed as conflicting with an
old-style definition and discarded? */
if (current_function_prototype_built_in)
warning (0, "promoted argument %qD "
"doesn%'t match built-in prototype", parm);
else
{
pedwarn ("promoted argument %qD "
"doesn%'t match prototype", parm);
pedwarn ("%Hprototype declaration",
&current_function_prototype_locus);
}
}
}
else
{
error ("argument %qD doesn%'t match prototype", parm);
error ("%Hprototype declaration",
&current_function_prototype_locus);
if (current_function_prototype_built_in)
warning (0, "argument %qD doesn%'t match "
"built-in prototype", parm);
else
{
error ("argument %qD doesn%'t match prototype", parm);
error ("%Hprototype declaration",
&current_function_prototype_locus);
}
}
}
}
......
......@@ -89,6 +89,11 @@ struct lang_type GTY(())
#define C_DECL_DECLARED_BUILTIN(EXP) \
DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (EXP))
/* For FUNCTION_DECLs, evaluates true if the decl is built-in, has a
built-in prototype and does not have a non-built-in prototype. */
#define C_DECL_BUILTIN_PROTOTYPE(EXP) \
DECL_LANG_FLAG_6 (FUNCTION_DECL_CHECK (EXP))
/* Record whether a decl was declared register. This is strictly a
front-end flag, whereas DECL_REGISTER is used for code generation;
they may differ for structures with volatile fields. */
......
2005-05-02 Joseph S. Myers <joseph@codesourcery.com>
PR c/15698
* gcc.dg/builtins-30.c: Update expected messages.
* gcc.dg/pr15698-1.c, gcc.dg/pr15698-2.c, gcc.dg/pr15698-3.c,
gcc.dg/pr15698-4.c, gcc.dg/pr15698-5.c, gcc.dg/pr15698-6.c,
gcc.dg/pr15698-7.c, pr15698-8.c: New tests.
2005-05-02 Kazu Hirata <kazu@cs.umass.edu>
PR tree-optimization/21294
......
......@@ -8,13 +8,14 @@ extern double strtod (const char *, char **);
specifying too few arguments... */
double cos ()
{ /* { dg-warning "shadows a built-in" } */
/* { dg-warning "warning: number of arguments doesn't match built-in prototype" "built-in" { target *-*-* } 10 } */
return strtod ("nan", 0);
}
/* the right number, but the wrong type, arguments... */
double sin (foo)
int foo UNUSED; /* { dg-warning "shadows a built-in" } */
{
{ /* { dg-warning "warning: argument 'foo' doesn't match built-in prototype" } */
return strtod ("nan", 0);
}
......@@ -22,6 +23,7 @@ double sin (foo)
long double cosl (foo, bar)
const char *foo UNUSED; /* { dg-warning "shadows a built-in" } */
int bar UNUSED;
{
{ /* { dg-warning "warning: number of arguments doesn't match built-in prototype" } */
/* { dg-warning "warning: argument 'foo' doesn't match built-in prototype" "foo" { target *-*-* } 26 } */
return strtod ("nan", 0);
}
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Original test. */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
int foobar ();
int func (int blah)
{
char *rindex();
}
int foobar ()
{
return 0;
}
char *rindex(a, b)
register char *a, b;
{ /* { dg-warning "warning: argument 'a' doesn't match built-in prototype" } */
return 0;
}
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Prototype at inner scope. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
void f() { void g(void); } /* { dg-error "error: prototype declaration" } */
void g(a) int a; {} /* { dg-error "error: number of arguments doesn't match prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Prototype not last declaration. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
void f();
void f(int); /* { dg-error "error: prototype declaration" } */
void f();
void f(a) long a; {} /* { dg-error "error: argument 'a' doesn't match prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Unprototyped built-in function with user prototype. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
int isnan(void); /* { dg-error "error: prototype declaration" } */
int isnan(a) int a; {} /* { dg-error "error: number of arguments doesn't match prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Unprototyped built-in function with user prototype at
inner scope. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
void f(void) { int isnan(void); } /* { dg-error "error: prototype declaration" } */
int isnan(a) int a; {} /* { dg-error "error: number of arguments doesn't match prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Prototyped built-in function, wrong number of
arguments. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
char *strchr(a) const char *a; { return 0; } /* { dg-warning "warning: number of arguments doesn't match built-in prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Prototyped built-in function, wrong number of
arguments, with explicit prototype as well. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
char *strchr(const char *, int); /* { dg-error "error: prototype declaration" } */
char *strchr(a) const char *a; { return 0; } /* { dg-error "error: number of arguments doesn't match prototype" } */
/* Test diagnostics for old-style definition not matching prior
prototype are present and give correct location for that prototype
(bug 15698). Prototype refined at inner scope with only refinement
conflicting with definition. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99" } */
int f(int (*)[]);
int g() { int f(int (*)[2]); } /* { dg-error "error: prototype declaration" } */
int f(a) int (*a)[3]; { return 0; } /* { dg-error "error: argument 'a' doesn't match prototype" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment