re PR c/86125 (missing -Wbuiltin-declaration-mismatch on a mismatched return type)
authorJakub Jelinek <jakub@redhat.com>
Mon, 28 Jan 2019 23:21:10 +0000 (00:21 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 28 Jan 2019 23:21:10 +0000 (00:21 +0100)
PR c/86125
* c-decl.c (last_fileptr_type): Remove.
(last_structptr_types): New variable.
(match_builtin_function_types): Compare TYPE_MAIN_VARIANT of
{old,new}rettype instead of the types themselves.  Assert
last_structptr_types array has the same number of elements
as builtin_structptr_types array.  Use TYPE_MAIN_VARIANT for
argument oldtype and newtype.  Instead of handling
just fileptr_type_node specially, handle all builtin_structptr_types
pointer nodes.  Formatting fix.

* c-common.c (c_common_nodes_and_builtins): Build type variants for
builtin_structptr_types types even for C.

* gcc.dg/Wbuiltin-declaration-mismatch-7.c: Guard testcase for
lp64, ilp32 and llp64 only.
(fputs): Use unsigned long long instead of size_t for return type.
(vfprintf, vfscanf): Accept arbitrary target specific type for
va_list.

From-SVN: r268348

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

index f955449ec1c9b95293479a04209c9300365fcc3b..3c55209ef3409ab001df513351e44ef35c7346b5 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/86125
+       * c-common.c (c_common_nodes_and_builtins): Build type variants for
+       builtin_structptr_types types even for C.
+
 2019-01-28  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * c-warn.c (check_address_or_pointer_of_packed_member): Handle the case
index 2a5a8e7defb3ed6b45c36cfaf2ea87818e61ad0b..d3b5879a2b2ee6cd0c5ec5ad3dbf94dd9afe1f16 100644 (file)
@@ -4296,18 +4296,13 @@ c_common_nodes_and_builtins (void)
                         COMPLEX_FLOATN_NX_TYPE_NODE (i)));
        }
 
-  if (c_dialect_cxx ())
-    {
-      /* For C++, make fileptr_type_node a distinct void * type until
-        FILE type is defined.  Likewise for const struct tm*.  */
-      for (unsigned i = 0;
-          i < sizeof (builtin_structptr_types)
-              / sizeof (builtin_structptr_type);
-          ++i)
-       builtin_structptr_types[i].node =
-         build_variant_type_copy (builtin_structptr_types[i].base);
-
-    }
+  /* Make fileptr_type_node a distinct void * type until
+     FILE type is defined.  Likewise for const struct tm*.  */
+  for (unsigned i = 0;
+       i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
+       ++i)
+    builtin_structptr_types[i].node
+      = build_variant_type_copy (builtin_structptr_types[i].base);
 
   record_builtin_type (RID_VOID, NULL, void_type_node);
 
index cb89cd881e50639b92a4a8f11c1967195be0bd7d..e6bff9c064b48d344c2cc539eb692ebf8ea39ff3 100644 (file)
@@ -1,3 +1,16 @@
+2019-01-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/86125
+       * c-decl.c (last_fileptr_type): Remove.
+       (last_structptr_types): New variable.
+       (match_builtin_function_types): Compare TYPE_MAIN_VARIANT of
+       {old,new}rettype instead of the types themselves.  Assert
+       last_structptr_types array has the same number of elements
+       as builtin_structptr_types array.  Use TYPE_MAIN_VARIANT for
+       argument oldtype and newtype.  Instead of handling
+       just fileptr_type_node specially, handle all builtin_structptr_types
+       pointer nodes.  Formatting fix.
+
 2019-01-24  Martin Sebor  <msebor@redhat.com>
 
        PR c/86125
index b60f1557e9e0e3449b679ad62932fb86720372b9..593b34e00470678bb35e8aaf02a1953742daeda2 100644 (file)
@@ -1632,13 +1632,13 @@ c_bind (location_t loc, tree decl, bool is_global)
 }
 \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).
+/* Stores the first FILE*, const struct tm* etc. argument type (whatever it
+   is) seen in a declaration of a file I/O etc. built-in.  Subsequent
+   declarations of such built-ins are expected to refer to it rather than to
+   fileptr_type_node etc. which is just void* (or to any other type).
    Used only by match_builtin_function_types.  */
 
-static GTY(()) tree last_fileptr_type;
+static GTY(()) tree last_structptr_types[6];
 
 /* Subroutine of compare_decls.  Allow harmless mismatches in return
    and argument types provided that the type modes match.  Set *STRICT
@@ -1660,13 +1660,18 @@ match_builtin_function_types (tree newtype, tree oldtype,
   if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
     return NULL_TREE;
 
-  if (!comptypes (oldrettype, newrettype))
+  if (!comptypes (TYPE_MAIN_VARIANT (oldrettype),
+                 TYPE_MAIN_VARIANT (newrettype)))
     *strict = oldrettype;
 
   tree oldargs = TYPE_ARG_TYPES (oldtype);
   tree newargs = TYPE_ARG_TYPES (newtype);
   tree tryargs = newargs;
 
+  gcc_checking_assert ((sizeof (last_structptr_types)
+                       / sizeof (last_structptr_types[0]))
+                      == (sizeof (builtin_structptr_types)
+                          / sizeof (builtin_structptr_types[0])));
   for (unsigned i = 1; oldargs || newargs; ++i)
     {
       if (!oldargs
@@ -1675,8 +1680,8 @@ match_builtin_function_types (tree newtype, tree oldtype,
          || !TREE_VALUE (newargs))
        return NULL_TREE;
 
-      tree oldtype = TREE_VALUE (oldargs);
-      tree newtype = TREE_VALUE (newargs);
+      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))
@@ -1684,28 +1689,39 @@ match_builtin_function_types (tree newtype, tree oldtype,
        return NULL_TREE;
 
       /* Fail for function and object pointer mismatches.  */
-      if (FUNCTION_POINTER_TYPE_P (oldtype) != FUNCTION_POINTER_TYPE_P (newtype)
+      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))
+      unsigned j = (sizeof (builtin_structptr_types)
+                   / sizeof (builtin_structptr_types[0]));
+      if (POINTER_TYPE_P (oldtype))
+       for (j = 0; j < (sizeof (builtin_structptr_types)
+                        / sizeof (builtin_structptr_types[0])); ++j)
+         {
+           if (TREE_VALUE (oldargs) != builtin_structptr_types[j].node)
+             continue;
+           /* Store the first FILE* etc. argument type (whatever it is), and
+              expect any subsequent declarations of file I/O etc. built-ins
+              to refer to it rather than to fileptr_type_node etc. which is
+              just void* (or const void*).  */
+           if (last_structptr_types[j])
+             {
+               if (!comptypes (last_structptr_types[j], newtype))
+                 {
+                   *argno = i;
+                   *strict = last_structptr_types[j];
+                 }
+             }
+           else
+             last_structptr_types[j] = newtype;
+           break;
+         }
+      if (j == (sizeof (builtin_structptr_types)
+               / sizeof (builtin_structptr_types[0]))
+         && !*strict
+         && !comptypes (oldtype, newtype))
        {
          *argno = i;
          *strict = oldtype;
index 7af76a148c859c6b80c81386c226b2c020f3d180..2e97ef3ae463b01005280b14c9e7462b3cda3b93 100644 (file)
@@ -1,3 +1,12 @@
+2019-01-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/86125
+       * gcc.dg/Wbuiltin-declaration-mismatch-7.c: Guard testcase for
+       lp64, ilp32 and llp64 only.
+       (fputs): Use unsigned long long instead of size_t for return type.
+       (vfprintf, vfscanf): Accept arbitrary target specific type for
+       va_list.
+
 2019-01-28  Marek Polacek  <polacek@redhat.com>
 
        PR c++/88358 - name wrongly treated as type.
diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-11.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-11.c
new file mode 100644 (file)
index 0000000..0c62c61
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR c/86125 */
+/* { dg-do compile } */
+/* { dg-options "-Wbuiltin-declaration-mismatch -Wextra -Wno-ignored-qualifiers" } */
+
+typedef __SIZE_TYPE__ size_t;
+struct FILE;
+struct tm;
+struct fenv_t;
+struct fexcept_t;
+typedef struct FILE FILE;
+typedef struct fenv_t fenv_t;
+typedef struct fexcept_t fexcept_t;
+typedef const int cint;
+size_t strftime (char *__restrict, const size_t, const char *__restrict,       /* { dg-bogus "mismatch in argument 1 type of built-in function" } */
+                 const struct tm *__restrict) __attribute__((nothrow));
+int fprintf (struct FILE *, const char *const, ...);                           /* { dg-bogus "mismatch in argument 2 type of built-in function" } */
+cint putc (int, struct FILE *);                                                        /* { dg-bogus "mismatch in return type of built-in function" } */
+cint fegetenv (fenv_t *);                                                      /* { dg-bogus "mismatch in argument 1 type of built-in function" } */
+cint fesetenv (const fenv_t *);                                                        /* { dg-bogus "mismatch in return type of built-in function" } */
+int fegetexceptflag (fexcept_t *, const int);                                  /* { dg-bogus "mismatch in argument 1 type of built-in function" } */
+int fesetexceptflag (const fexcept_t *, const int);                            /* { dg-bogus "mismatch in argument 1 type of built-in function" } */
index 77a4bfff4d385e473b711f5db39a8bf96cc40aaa..7f6644edb58efcfe305ad5582012a45c36dd6845 100644 (file)
@@ -2,7 +2,7 @@
    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-do compile { target { { lp64 || ilp32 } || llp64 } } }
    { dg-options "-Wbuiltin-declaration-mismatch" } */
 
 struct StdioFile;
@@ -13,14 +13,14 @@ 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 vfprintf (struct StdioFile*, const char*, ...);   /* { dg-warning "conflicting types for built-in function .vfprintf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \[^\n\r,\\\)\]+\\\)." } */
 
 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_\]+ \\\*\\\)." } */
+unsigned long long 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_\]+ \\\*\\\)." } */
+int vfscanf (struct StdioFile*, const char*, ...);   /* { dg-warning "conflicting types for built-in function .vfscanf.; expected .int\\\(\[a-z_\]+ \\\*, const char \\\*, \[^\n\r,\\\)\]+\\\)." } */
 
 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_\]+ \\\*\\\)." } */