+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>
PR c++/88976
bind (DECL_NAME (decl), decl, scope, false, nested, loc);
}
\f
+
+/* 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);
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);
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))
+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>
PR rtl-optimization/88948
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;
}
--- /dev/null
+/* 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)];
+}
--- /dev/null
+/* 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*);
--- /dev/null
+/* 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_\]+ \\\*\\\)." } */
--- /dev/null
+/* 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 \\\*." } */
--- /dev/null
+/* 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-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)
{
--- /dev/null
+/* 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);
+}