summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-02 19:39:04 +0000
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-02 19:39:04 +0000
commit3eafcdb5bf402c162e8b5f18a77a8afebfcc20a0 (patch)
treed9cc9fb4c89fa7f24c4b6b67239e8a3bb79274eb /gcc
parent836c012512928660f99775081e13475b297972f7 (diff)
downloadgcc-3eafcdb5bf402c162e8b5f18a77a8afebfcc20a0.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99118 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/c-decl.c127
-rw-r--r--gcc/c-tree.h5
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/builtins-30.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-2.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-4.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-5.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-6.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-7.c10
-rw-r--r--gcc/testsuite/gcc.dg/pr15698-8.c11
13 files changed, 233 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d0b8c2bace..4183ec0f5df 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+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.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 3578862269f..c8516c7501b 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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);
+ }
}
}
}
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index c7cbd133065..c22ae8ab8d1 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 46c9e1db3ee..d39b39b755b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/testsuite/gcc.dg/builtins-30.c b/gcc/testsuite/gcc.dg/builtins-30.c
index 7c700c514dc..d65b8948ee1 100644
--- a/gcc/testsuite/gcc.dg/builtins-30.c
+++ b/gcc/testsuite/gcc.dg/builtins-30.c
@@ -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);
}
diff --git a/gcc/testsuite/gcc.dg/pr15698-1.c b/gcc/testsuite/gcc.dg/pr15698-1.c
new file mode 100644
index 00000000000..6b1c4e2ee3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-1.c
@@ -0,0 +1,23 @@
+/* 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;
+}
diff --git a/gcc/testsuite/gcc.dg/pr15698-2.c b/gcc/testsuite/gcc.dg/pr15698-2.c
new file mode 100644
index 00000000000..c0d635aba62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-2.c
@@ -0,0 +1,9 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-3.c b/gcc/testsuite/gcc.dg/pr15698-3.c
new file mode 100644
index 00000000000..15d998a8c5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-3.c
@@ -0,0 +1,11 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-4.c b/gcc/testsuite/gcc.dg/pr15698-4.c
new file mode 100644
index 00000000000..b1554f48b4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-4.c
@@ -0,0 +1,9 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-5.c b/gcc/testsuite/gcc.dg/pr15698-5.c
new file mode 100644
index 00000000000..c87e133c5f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-5.c
@@ -0,0 +1,10 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-6.c b/gcc/testsuite/gcc.dg/pr15698-6.c
new file mode 100644
index 00000000000..bca51f28c7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-6.c
@@ -0,0 +1,9 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-7.c b/gcc/testsuite/gcc.dg/pr15698-7.c
new file mode 100644
index 00000000000..b75f8153dec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-7.c
@@ -0,0 +1,10 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/pr15698-8.c b/gcc/testsuite/gcc.dg/pr15698-8.c
new file mode 100644
index 00000000000..b9b6595a7fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr15698-8.c
@@ -0,0 +1,11 @@
+/* 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" } */