From d8b5a1a00d4f88aa82c9119095e2b4993444f6ee Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 24 Jan 2019 21:06:01 +0000 Subject: [PATCH] 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 --- gcc/c/ChangeLog | 9 ++ gcc/c/c-decl.c | 120 ++++++++++++++---- gcc/testsuite/ChangeLog | 14 ++ .../gcc.c-torture/execute/eeprof-1.c | 12 +- .../gcc.dg/Wbuiltin-declaration-mismatch-10.c | 10 ++ .../gcc.dg/Wbuiltin-declaration-mismatch-6.c | 18 +++ .../gcc.dg/Wbuiltin-declaration-mismatch-7.c | 26 ++++ .../gcc.dg/Wbuiltin-declaration-mismatch-8.c | 26 ++++ .../gcc.dg/Wbuiltin-declaration-mismatch-9.c | 12 ++ gcc/testsuite/gcc.dg/Wint-conversion-2.c | 5 +- gcc/testsuite/gcc.dg/builtins-69.c | 22 ++++ 11 files changed, 243 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-10.c create mode 100644 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-6.c create mode 100644 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-7.c create mode 100644 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-8.c create mode 100644 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c create mode 100644 gcc/testsuite/gcc.dg/builtins-69.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 32c77f9360b..cb89cd881e5 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2019-01-24 Martin Sebor + + 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 PR c++/88976 diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 57049f80073..b60f1557e9e 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -1631,43 +1631,91 @@ c_bind (location_t loc, tree decl, bool is_global) 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 - and argument types provided that the type modes match. This function - return a unified type given a suitable match, and 0 otherwise. */ + and argument types provided that the type modes match. Set *STRICT + 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 -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. */ - oldrettype = TREE_TYPE (oldtype); - newrettype = TREE_TYPE (newtype); + tree oldrettype = TREE_TYPE (oldtype); + tree newrettype = TREE_TYPE (newtype); + + *argno = 0; + *strict = NULL_TREE; if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype)) return NULL_TREE; - oldargs = TYPE_ARG_TYPES (oldtype); - newargs = TYPE_ARG_TYPES (newtype); - tryargs = newargs; + if (!comptypes (oldrettype, newrettype)) + *strict = oldrettype; - 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 || !newargs || !TREE_VALUE (oldargs) - || !TREE_VALUE (newargs) - || TYPE_MODE (TREE_VALUE (oldargs)) - != TYPE_MODE (TREE_VALUE (newargs))) + || !TREE_VALUE (newargs)) 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); newargs = TREE_CHAIN (newargs); } - trytype = build_function_type (newrettype, tryargs); + tree trytype = build_function_type (newrettype, tryargs); /* Allow declaration to change transaction_safe attribute. */ tree oldattrs = TYPE_ATTRIBUTES (oldtype); @@ -1881,14 +1929,26 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, if (TREE_CODE (olddecl) == FUNCTION_DECL && fndecl_built_in_p (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl)) { - /* Accept harmless mismatch in function types. - This is for the ffs and fprintf builtins. */ - tree trytype = match_builtin_function_types (newtype, oldtype); + /* Accept "harmless" mismatches in function types such + as missing qualifiers or pointer vs same size integer + 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)) *oldtypep = oldtype = trytype; 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 = header_for_builtin_fn (DECL_FUNCTION_CODE (olddecl)); location_t loc = DECL_SOURCE_LOCATION (newdecl); @@ -1905,11 +1965,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, inform (&richloc, "%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; } + + 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 && DECL_IS_BUILTIN (olddecl)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 55dcd7469a6..fa88d9d35cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2019-01-24 Martin Sebor + + 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 PR rtl-optimization/88948 diff --git a/gcc/testsuite/gcc.c-torture/execute/eeprof-1.c b/gcc/testsuite/gcc.c-torture/execute/eeprof-1.c index 81dcefbab12..c10f4cf83c3 100644 --- a/gcc/testsuite/gcc.c-torture/execute/eeprof-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/eeprof-1.c @@ -62,18 +62,18 @@ int main () return 0; } -void __cyg_profile_func_enter (void (*fn)(), void (*parent)()) NOCHK; -void __cyg_profile_func_exit (void (*fn)(), void (*parent)()) NOCHK; +void __cyg_profile_func_enter (void*, void*) NOCHK; +void __cyg_profile_func_exit (void*, void*) NOCHK; __attribute__ ((noinline)) -void __cyg_profile_func_enter (void (*fn)(), void (*parent)()) +void __cyg_profile_func_enter (void *fn, void *parent) { entry_calls++; - last_fn_entered = fn; + last_fn_entered = (void (*)())fn; } __attribute__ ((noinline)) -void __cyg_profile_func_exit (void (*fn)(), void (*parent)()) +void __cyg_profile_func_exit (void *fn, void *parent) { exit_calls++; - last_fn_exited = fn; + last_fn_exited = (void (*)())fn; } diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-10.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-10.c new file mode 100644 index 00000000000..58de1d48b6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-10.c @@ -0,0 +1,10 @@ +/* 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)]; +} diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-6.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-6.c new file mode 100644 index 00000000000..32af9febfaf --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-6.c @@ -0,0 +1,18 @@ +/* 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*); diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-7.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-7.c new file mode 100644 index 00000000000..77a4bfff4d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-7.c @@ -0,0 +1,26 @@ +/* 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_\]+ \\\*\\\)." } */ diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-8.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-8.c new file mode 100644 index 00000000000..d06af6528fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-8.c @@ -0,0 +1,26 @@ +/* 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 \\\*." } */ diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c new file mode 100644 index 00000000000..f0c1ce33267 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-9.c @@ -0,0 +1,12 @@ +/* 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" } */ + ); +} diff --git a/gcc/testsuite/gcc.dg/Wint-conversion-2.c b/gcc/testsuite/gcc.dg/Wint-conversion-2.c index 0c9dac44c41..bf590a7bcd7 100644 --- a/gcc/testsuite/gcc.dg/Wint-conversion-2.c +++ b/gcc/testsuite/gcc.dg/Wint-conversion-2.c @@ -1,8 +1,9 @@ -/* PR middle-end/86202 */ +/* PR middle-end/86202 - ICE in get_range_info calling an invalid memcpy() + declaration */ /* { dg-do compile } */ /* { 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 f (void) { diff --git a/gcc/testsuite/gcc.dg/builtins-69.c b/gcc/testsuite/gcc.dg/builtins-69.c new file mode 100644 index 00000000000..26dfb3bfc1b --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-69.c @@ -0,0 +1,22 @@ +/* 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); +} -- 2.30.2