Commit d8b5a1a0 by Martin Sebor Committed by Martin Sebor

PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched return type

PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched return type
PR middle-end/86308 - ICE in verify_gimple calling index() with an invalid declaration
PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched return type
PR c/88886 - [9 Regression] ice in get_constant, at c-family/c-format.c:292

gcc/c/ChangeLog:

	PR c/86125
	PR c/88886
	PR middle-end/86308
	* c-decl.c (match_builtin_function_types): Add arguments.
	(diagnose_mismatched_decls): Diagnose mismatched declarations
	of built-ins more strictly.

gcc/testsuite/ChangeLog:

	PR c/86125
	PR c/88886
	PR middle-end/86308
	* gcc.dg/Wbuiltin-declaration-mismatch-6.c: New test.
	* gcc.dg/Wbuiltin-declaration-mismatch-7.c: New test.
	* gcc.dg/Wbuiltin-declaration-mismatch-8.c: New test.
	* gcc.dg/Wbuiltin-declaration-mismatch-9.c: New test.
	* gcc.dg/Wbuiltin-declaration-mismatch-10.c: New test.
	* gcc.dg/builtins-69.c: New test.
	* gcc.dg/Wint-conversion-2.c: Add expected warning.
	* gcc.c-torture/execute/eeprof-1.c: Adjust function signatures.

From-SVN: r268251
parent b0e0e885
2019-01-24 Martin Sebor <msebor@redhat.com>
PR c/86125
PR c/88886
PR middle-end/86308
* c-decl.c (match_builtin_function_types): Add arguments.
(diagnose_mismatched_decls): Diagnose mismatched declarations
of built-ins more strictly.
2019-01-24 Jakub Jelinek <jakub@redhat.com> 2019-01-24 Jakub Jelinek <jakub@redhat.com>
PR c++/88976 PR c++/88976
......
...@@ -1631,43 +1631,91 @@ c_bind (location_t loc, tree decl, bool is_global) ...@@ -1631,43 +1631,91 @@ c_bind (location_t loc, tree decl, bool is_global)
bind (DECL_NAME (decl), decl, scope, false, nested, loc); bind (DECL_NAME (decl), decl, scope, false, nested, loc);
} }
/* Stores the first FILE* argument type (whatever it is) seen in
a declaration of a file I/O built-in. Subsequent declarations
of such built-ins are expected to refer to it rather than to
fileptr_type_node which is just void* (or to any other type).
Used only by match_builtin_function_types. */
static GTY(()) tree last_fileptr_type;
/* Subroutine of compare_decls. Allow harmless mismatches in return /* Subroutine of compare_decls. Allow harmless mismatches in return
and argument types provided that the type modes match. This function and argument types provided that the type modes match. Set *STRICT
return a unified type given a suitable match, and 0 otherwise. */ and *ARGNO to the expected argument type and number in case of
an argument type mismatch or null and zero otherwise. Return
a unified type given a suitable match, and 0 otherwise. */
static tree static tree
match_builtin_function_types (tree newtype, tree oldtype) match_builtin_function_types (tree newtype, tree oldtype,
tree *strict, unsigned *argno)
{ {
tree newrettype, oldrettype;
tree newargs, oldargs;
tree trytype, tryargs;
/* Accept the return type of the new declaration if same modes. */ /* Accept the return type of the new declaration if same modes. */
oldrettype = TREE_TYPE (oldtype); tree oldrettype = TREE_TYPE (oldtype);
newrettype = TREE_TYPE (newtype); tree newrettype = TREE_TYPE (newtype);
*argno = 0;
*strict = NULL_TREE;
if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype)) if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
return NULL_TREE; return NULL_TREE;
oldargs = TYPE_ARG_TYPES (oldtype); if (!comptypes (oldrettype, newrettype))
newargs = TYPE_ARG_TYPES (newtype); *strict = oldrettype;
tryargs = newargs;
while (oldargs || newargs) tree oldargs = TYPE_ARG_TYPES (oldtype);
tree newargs = TYPE_ARG_TYPES (newtype);
tree tryargs = newargs;
for (unsigned i = 1; oldargs || newargs; ++i)
{ {
if (!oldargs if (!oldargs
|| !newargs || !newargs
|| !TREE_VALUE (oldargs) || !TREE_VALUE (oldargs)
|| !TREE_VALUE (newargs) || !TREE_VALUE (newargs))
|| TYPE_MODE (TREE_VALUE (oldargs))
!= TYPE_MODE (TREE_VALUE (newargs)))
return NULL_TREE; return NULL_TREE;
tree oldtype = TREE_VALUE (oldargs);
tree newtype = TREE_VALUE (newargs);
/* Fail for types with incompatible modes/sizes. */
if (TYPE_MODE (TREE_VALUE (oldargs))
!= TYPE_MODE (TREE_VALUE (newargs)))
return NULL_TREE;
/* Fail for function and object pointer mismatches. */
if (FUNCTION_POINTER_TYPE_P (oldtype) != FUNCTION_POINTER_TYPE_P (newtype)
|| POINTER_TYPE_P (oldtype) != POINTER_TYPE_P (newtype))
return NULL_TREE;
if (oldtype == fileptr_type_node)
{
/* Store the first FILE* argument type (whatever it is), and
expect any subsequent declarations of file I/O built-ins
to refer to it rather than to fileptr_type_node which is
just void*. */
if (last_fileptr_type)
{
if (!comptypes (last_fileptr_type, newtype))
{
*argno = i;
*strict = last_fileptr_type;
}
}
else
last_fileptr_type = newtype;
}
else if (!*strict && !comptypes (oldtype, newtype))
{
*argno = i;
*strict = oldtype;
}
oldargs = TREE_CHAIN (oldargs); oldargs = TREE_CHAIN (oldargs);
newargs = TREE_CHAIN (newargs); newargs = TREE_CHAIN (newargs);
} }
trytype = build_function_type (newrettype, tryargs); tree trytype = build_function_type (newrettype, tryargs);
/* Allow declaration to change transaction_safe attribute. */ /* Allow declaration to change transaction_safe attribute. */
tree oldattrs = TYPE_ATTRIBUTES (oldtype); tree oldattrs = TYPE_ATTRIBUTES (oldtype);
...@@ -1881,14 +1929,26 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ...@@ -1881,14 +1929,26 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (TREE_CODE (olddecl) == FUNCTION_DECL if (TREE_CODE (olddecl) == FUNCTION_DECL
&& fndecl_built_in_p (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl)) && fndecl_built_in_p (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
{ {
/* Accept harmless mismatch in function types. /* Accept "harmless" mismatches in function types such
This is for the ffs and fprintf builtins. */ as missing qualifiers or pointer vs same size integer
tree trytype = match_builtin_function_types (newtype, oldtype); mismatches. This is for the ffs and fprintf builtins.
However, with -Wextra in effect, diagnose return and
argument types that are incompatible according to
language rules. */
tree mismatch_expect;
unsigned mismatch_argno;
tree trytype = match_builtin_function_types (newtype, oldtype,
&mismatch_expect,
&mismatch_argno);
if (trytype && comptypes (newtype, trytype)) if (trytype && comptypes (newtype, trytype))
*oldtypep = oldtype = trytype; *oldtypep = oldtype = trytype;
else else
{ {
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
won't print anything. */
const char *header const char *header
= header_for_builtin_fn (DECL_FUNCTION_CODE (olddecl)); = header_for_builtin_fn (DECL_FUNCTION_CODE (olddecl));
location_t loc = DECL_SOURCE_LOCATION (newdecl); location_t loc = DECL_SOURCE_LOCATION (newdecl);
...@@ -1905,11 +1965,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ...@@ -1905,11 +1965,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
inform (&richloc, inform (&richloc,
"%qD is declared in header %qs", olddecl, header); "%qD is declared in header %qs", olddecl, header);
} }
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
won't print anything. */
return false; return false;
} }
if (mismatch_expect && extra_warnings)
{
/* If types match only loosely, print a warning but accept
the redeclaration. */
location_t newloc = DECL_SOURCE_LOCATION (newdecl);
if (mismatch_argno)
warning_at (newloc, OPT_Wbuiltin_declaration_mismatch,
"mismatch in argument %u type of built-in "
"function %qD; expected %qT",
mismatch_argno, newdecl, mismatch_expect);
else
warning_at (newloc, OPT_Wbuiltin_declaration_mismatch,
"mismatch in return type of built-in "
"function %qD; expected %qT",
newdecl, mismatch_expect);
}
} }
else if (TREE_CODE (olddecl) == FUNCTION_DECL else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_IS_BUILTIN (olddecl)) && DECL_IS_BUILTIN (olddecl))
......
2019-01-24 Martin Sebor <msebor@redhat.com>
PR c/86125
PR c/88886
PR middle-end/86308
* gcc.dg/Wbuiltin-declaration-mismatch-6.c: New test.
* gcc.dg/Wbuiltin-declaration-mismatch-7.c: New test.
* gcc.dg/Wbuiltin-declaration-mismatch-8.c: New test.
* gcc.dg/Wbuiltin-declaration-mismatch-9.c: New test.
* gcc.dg/Wbuiltin-declaration-mismatch-10.c: New test.
* gcc.dg/builtins-69.c: New test.
* gcc.dg/Wint-conversion-2.c: Add expected warning.
* gcc.c-torture/execute/eeprof-1.c: Adjust function signatures.
2019-01-24 Uroš Bizjak <ubizjak@gmail.com> 2019-01-24 Uroš Bizjak <ubizjak@gmail.com>
PR rtl-optimization/88948 PR rtl-optimization/88948
......
...@@ -62,18 +62,18 @@ int main () ...@@ -62,18 +62,18 @@ int main ()
return 0; return 0;
} }
void __cyg_profile_func_enter (void (*fn)(), void (*parent)()) NOCHK; void __cyg_profile_func_enter (void*, void*) NOCHK;
void __cyg_profile_func_exit (void (*fn)(), void (*parent)()) NOCHK; void __cyg_profile_func_exit (void*, void*) NOCHK;
__attribute__ ((noinline)) __attribute__ ((noinline))
void __cyg_profile_func_enter (void (*fn)(), void (*parent)()) void __cyg_profile_func_enter (void *fn, void *parent)
{ {
entry_calls++; entry_calls++;
last_fn_entered = fn; last_fn_entered = (void (*)())fn;
} }
__attribute__ ((noinline)) __attribute__ ((noinline))
void __cyg_profile_func_exit (void (*fn)(), void (*parent)()) void __cyg_profile_func_exit (void *fn, void *parent)
{ {
exit_calls++; exit_calls++;
last_fn_exited = fn; last_fn_exited = (void (*)())fn;
} }
/* PR c/86308 - ICE in verify_gimple calling an invalid index() declaration
{ dg-do compile }
{ dg-options "-Wall" } */
int index (int, int); /* { dg-warning "conflicting types for built-in function .index.; expected .char \\\*\\\(const char \\\*, int\\\)." } */
int foo (const short *a)
{
return a[index (0, 0)];
}
/* PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched
return type
Verify that declarations of file I/O built-ins with an arbitrary
object pointer do not trigger -Wbuiltin-declaration-mismatch.
{ dg-do compile }
{ dg-options "-Wbuiltin-declaration-mismatch -Wextra" } */
typedef __SIZE_TYPE__ size_t;
struct StdioFile;
int fprintf (struct StdioFile*, const char*, ...);
int vfprintf (struct StdioFile*, const char*, __builtin_va_list);
int fputc (int, struct StdioFile*);
int fputs (const char*, struct StdioFile*);
int fscanf (struct StdioFile*, const char*, ...);
int vfscanf (struct StdioFile*, const char*, __builtin_va_list);
size_t fwrite (const void*, size_t, size_t, struct StdioFile*);
/* PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched
return type
Verify that a declaration of vfprintf() with withe the wrong last
argument triggers -Wbuiltin-declaration-mismatch even without -Wextra.
{ dg-do compile }
{ dg-options "-Wbuiltin-declaration-mismatch" } */
struct StdioFile;
typedef __SIZE_TYPE__ size_t;
struct StdioFile;
int fprintf (struct StdioFile*, const char*); /* { dg-warning "conflicting types for built-in function .fprintf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \.\.\.\\\)." } */
int vfprintf (struct StdioFile*, const char*, ...); /* { dg-warning "conflicting types for built-in function .vfprintf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \[a-z_\]+ \\\*\\\)." } */
int fputc (char, struct StdioFile*); /* { dg-warning "conflicting types for built-in function .fputc.; expected .int\\\(int, void \\\*\\\)." } */
size_t fputs (const char*, struct StdioFile*); /* { dg-warning "conflicting types for built-in function .fputs.; expected .int\\\(const char \\\*, \[a-z_\]+ \\\*\\\)." } */
int fscanf (struct StdioFile*, const char*, size_t, ...); /* { dg-warning "conflicting types for built-in function .fscanf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \.\.\.\\\)." } */
int vfscanf (struct StdioFile*, const char*, ...); /* { dg-warning "conflicting types for built-in function .vfscanf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \[a-z_\]+ \\\*\\\)." } */
size_t fwrite (const void*, size_t, size_t, struct StdioFile); /* { dg-warning "conflicting types for built-in function .fwrite.; expected .\(long \)?unsigned int\\\(const void \\\*, \(long \)?unsigned int, *\(long \)?unsigned int, *\[a-z_\]+ \\\*\\\)." } */
/* PR c/86125 - missing -Wbuiltin-declaration-mismatch on a mismatched
return type
Verify that declarations of file I/O built-ins with different
definitions of struct FILE triggers -Wbuiltin-declaration-mismatch
when -Wextra is specified.
{ dg-do compile }
{ dg-options "-Wall -Wbuiltin-declaration-mismatch" } */
struct FooFile;
int fputc (int, struct FooFile*);
typedef struct FooFile AlsoFooFile;
int fprintf (AlsoFooFile*, const char*, ...);
typedef AlsoFooFile* FooFilePtr;
int fscanf (FooFilePtr, const char*, ...);
/* No warning here (-Wextra not specified). */
struct BarFile;
int vfprintf (struct BarFile*, const char*, __builtin_va_list);
/* Set -Wextra and verify -Wbuiltin-declaration-mismatch is issued. */
#pragma GCC diagnostic warning "-Wextra"
int fputs (const char*, struct BarFile*); /* { dg-warning "mismatch in argument 2 type of built-in function .fputs.; expected .struct FooFile \\\*." } */
/* PR c/88886 - ice in get_constant, at c-family/c-format.c:292
{ dg-do compile }
{ dg-options "-Wall" } */
int sscanf (long, unsigned[], ...); /* { dg-warning "conflicting types for built-in function .sscanf.; expected .int\\\(const char \\\*, const char \\\*, ...\\\)." } */
void a (void)
{
sscanf (0,
"" /* { dg-warning "passing argument 2 of .sscanf. from incompatible pointer type" } */
);
}
/* PR middle-end/86202 */ /* PR middle-end/86202 - ICE in get_range_info calling an invalid memcpy()
declaration */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Wint-conversion" } */ /* { dg-options "-Wint-conversion" } */
void *memcpy (void *, void *, __SIZE_TYPE__ *); void *memcpy (void *, void *, __SIZE_TYPE__ *); /* { dg-warning "conflicting types for built-in function .memcpy." } */
void *a, *b; void *a, *b;
void f (void) void f (void)
{ {
......
/* PR middle-end/86308 - ICE in verify_gimple calling index() with
an invalid declaration
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
int index (int, int); /* { dg-warning "conflicting types for built-in function .index.; expected .char \\\*\\\(const char \\\*, int\\\)." } */
int test_index (void)
{
return index (0, 0);
}
/* PR middle-end/86202 - ICE in get_range_info calling an invalid memcpy()
declaration */
void *memcpy (void *, void *, __SIZE_TYPE__ *); /* { dg-warning "conflicting types for built-in function .memcpy.; expected .void \\\*\\\(void \\\*, const void \\\*, \(long \)?unsigned int\\\)." } */
void test_memcpy (void *p, void *q, __SIZE_TYPE__ *r)
{
memcpy (p, q, r);
}
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