PR middle-end/93926 - ICE on a built-in redeclaration returning an integer instead...
authorMartin Sebor <msebor@redhat.com>
Mon, 2 Mar 2020 00:52:44 +0000 (17:52 -0700)
committerMartin Sebor <msebor@redhat.com>
Mon, 2 Mar 2020 00:52:44 +0000 (17:52 -0700)
gcc/c/ChangeLog:

PR middle-end/93926
* c-decl.c (types_close_enough_to_match): New function.
(match_builtin_function_types):
(diagnose_mismatched_decls): Add missing inform call to a warning.

gcc/testsuite/ChangeLog:

PR middle-end/93926
* gcc.dg/Wbuiltin-declaration-mismatch-13.c: New test.

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c [new file with mode: 0644]

index effb71bd328f4eca00c5bad0e3e1eea6f41315aa..199b655270c5ab1033fc44225d59c52ae26fcb99 100644 (file)
@@ -1,3 +1,10 @@
+2020-03-01  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/93926
+       * c-decl.c (types_close_enough_to_match): New function.
+       (match_builtin_function_types):
+       (diagnose_mismatched_decls): Add missing inform call to a warning.
+
 2020-03-01  Martin Sebor  <msebor@redhat.com>
 
        PR c/93812
index 1aa410db6e471df7abed7dd8b0e119e278ed06e0..c819fd0d0d54b7147c782850f28e861b2f6b0349 100644 (file)
@@ -1649,6 +1649,18 @@ c_bind (location_t loc, tree decl, bool is_global)
 
 static GTY(()) tree last_structptr_types[6];
 
+/* Returns true if types T1 and T2 representing return types or types
+   of function arguments are close enough to be considered interchangeable
+   in redeclarations of built-in functions.  */
+
+static bool
+types_close_enough_to_match (tree t1, tree t2)
+{
+  return (TYPE_MODE (t1) == TYPE_MODE (t2)
+         && POINTER_TYPE_P (t1) == POINTER_TYPE_P (t2)
+         && FUNCTION_POINTER_TYPE_P (t1) == FUNCTION_POINTER_TYPE_P (t2));
+}
+
 /* Subroutine of compare_decls.  Allow harmless mismatches in return
    and argument types provided that the type modes match.  Set *STRICT
    and *ARGNO to the expected argument type and number in case of
@@ -1659,16 +1671,19 @@ static tree
 match_builtin_function_types (tree newtype, tree oldtype,
                              tree *strict, unsigned *argno)
 {
-  /* Accept the return type of the new declaration if same modes.  */
-  tree oldrettype = TREE_TYPE (oldtype);
-  tree newrettype = TREE_TYPE (newtype);
-
   *argno = 0;
   *strict = NULL_TREE;
 
-  if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
+  /* Accept the return type of the new declaration if it has the same
+     mode and if they're both pointers or if neither is.  */
+  tree oldrettype = TREE_TYPE (oldtype);
+  tree newrettype = TREE_TYPE (newtype);
+
+  if (!types_close_enough_to_match (oldrettype, newrettype))
     return NULL_TREE;
 
+  /* Check that the return types are compatible but don't fail if they
+     are not (e.g., int vs long in ILP32) and just let the caller know.  */
   if (!comptypes (TYPE_MAIN_VARIANT (oldrettype),
                  TYPE_MAIN_VARIANT (newrettype)))
     *strict = oldrettype;
@@ -1692,15 +1707,7 @@ match_builtin_function_types (tree newtype, tree oldtype,
       tree oldtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
       tree newtype = TYPE_MAIN_VARIANT (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))
+      if (!types_close_enough_to_match (oldtype, newtype))
        return NULL_TREE;
 
       unsigned j = (sizeof (builtin_structptr_types)
@@ -1957,11 +1964,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          && !C_DECL_DECLARED_BUILTIN (olddecl))
        {
          /* 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.  */
+            as missing qualifiers or int vs long when they're the same
+            size.  However, with -Wextra in effect, diagnose return and
+            argument types that are incompatible according to language
+            rules.  */
          tree mismatch_expect;
          unsigned mismatch_argno;
 
@@ -1999,16 +2005,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
              /* If types match only loosely, print a warning but accept
                 the redeclaration.  */
              location_t newloc = DECL_SOURCE_LOCATION (newdecl);
+             bool warned = false;
              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);
+               warned = 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);
+               warned = warning_at (newloc, OPT_Wbuiltin_declaration_mismatch,
+                                    "mismatch in return type of built-in "
+                                    "function %qD; expected %qT",
+                                    newdecl, mismatch_expect);
+             const char *header = header_for_builtin_fn (olddecl);
+             if (warned && header)
+               {
+                 rich_location richloc (line_table, newloc);
+                 maybe_add_include_fixit (&richloc, header, true);
+                 inform (&richloc,
+                         "%qD is declared in header %qs", olddecl, header);
+               }
            }
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
index a6524beedefb65d3f1b6743f84473381155a54db..401c648819d40d3d5e1d1657be90968261226fdc 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-01  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/93926
+       * gcc.dg/Wbuiltin-declaration-mismatch-13.c: New test.
+
 2020-03-01  Martin Sebor  <msebor@redhat.com>
 
        PR c/93812
diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-13.c
new file mode 100644 (file)
index 0000000..f21f407
--- /dev/null
@@ -0,0 +1,78 @@
+/* PR middle-end/93926 - ICE on a built-in redeclaration returning an integer
+   instead of a pointer
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* ret_calloc (size_t n1, size_t n2)
+{
+  extern size_t calloc (size_t, size_t);    // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return (void *) calloc (n1, n2);
+}
+
+void* ret_malloc (size_t n)
+{
+  extern size_t malloc (size_t);            // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return (void *) malloc (n);
+}
+
+void* ret_realloc (void *p, size_t n)
+{
+  extern size_t realloc (void *p, size_t);  // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return (void *) realloc (p, n);
+}
+
+void* ret_strdup (const char *s)
+{
+  extern size_t strdup (const char*);       // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return (void *) strdup (s);
+}
+
+void* ret_strndup (const char *s, size_t n)
+{
+  extern size_t
+    strndup (const char*, size_t);          // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return (void *) strndup (s, n);
+}
+
+// For good measure also exerise strcmp return type (not part of the bug).
+
+char* ret_strcmp (const char *s, const char *t)
+{
+  extern char*
+    strcmp (const char*, const char*);      // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return strcmp (s, t);
+}
+
+// Exercise warnings for pointer/integer mismatches in argument types
+// (also not part of the bug).
+
+char* ret_strcat (size_t s, const char *t)
+{
+  extern char*
+    strcat (size_t, const char*);           // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return strcat (s, t);
+}
+
+char* ret_strcpy (char *s, size_t t)
+{
+  extern char* strcpy (char*, size_t);      // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return strcpy (s, t);
+}
+
+char* ret_strncpy (char *s, const char *t, size_t n)
+{
+  extern char*
+    strncpy (char*, size_t, const char*);   // { dg-warning "\\\[-Wbuiltin-declaration-mismatch" }
+
+  return strncpy (s, n, t);
+}