aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-03-13 10:28:26 -0600
committerMartin Sebor <msebor@redhat.com>2020-03-13 10:28:26 -0600
commitf2e9fe5f97d88fc876c44e6ffa57a2e85150adf9 (patch)
tree4efc5313286608ccae0b5b9224a5c4381b76064c /gcc/c
parent9ae8bc027743d7c2d25f90d6752a1f4e0dc153cf (diff)
downloadgcc-f2e9fe5f97d88fc876c44e6ffa57a2e85150adf9.zip
gcc-f2e9fe5f97d88fc876c44e6ffa57a2e85150adf9.tar.gz
gcc-f2e9fe5f97d88fc876c44e6ffa57a2e85150adf9.tar.bz2
PR c/94040 - ICE on a call to an invalid redeclaration of strftime
gcc/c/ChangeLog: PR c/94040 * c-decl.c (builtin_structptr_type_count): New constant. (match_builtin_function_types): Reject decls that are incompatible in types pointed to by pointers. (diagnose_mismatched_decls): Adjust comments. gcc/testsuite/ChangeLog: PR c/94040 * gcc.dg/Wbuiltin-declaration-mismatch-12.c: Relax test to look for warning name rather than the exact text. * gcc.dg/Wbuiltin-declaration-mismatch-14.c: New test. * gcc.dg/Wbuiltin-declaration-mismatch-15.c: New test. * gcc.dg/pr62090.c: Prune expected warning. * gcc.dg/pr89314.c: Look for warning name rather than text.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog8
-rw-r--r--gcc/c/c-decl.c66
2 files changed, 50 insertions, 24 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 5b8236d..d3a3b2f 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,11 @@
+2020-03-13 Martin Sebor <msebor@redhat.com>
+
+ PR c/94040
+ * c-decl.c (builtin_structptr_type_count): New constant.
+ (match_builtin_function_types): Reject decls that are incompatible
+ in types pointed to by pointers.
+ (diagnose_mismatched_decls): Adjust comments.
+
2020-03-05 Joseph Myers <joseph@codesourcery.com>
PR c/93577
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index c819fd0..87a0734 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1641,13 +1641,17 @@ c_bind (location_t loc, tree decl, bool is_global)
}
-/* 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).
+/* 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, corresponding
+ to the builtin_structptr_types array. 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_structptr_types[6];
+static const unsigned builtin_structptr_type_count
+ = sizeof builtin_structptr_types / sizeof builtin_structptr_types[0];
+
+static GTY(()) tree last_structptr_types[builtin_structptr_type_count];
/* Returns true if types T1 and T2 representing return types or types
of function arguments are close enough to be considered interchangeable
@@ -1692,10 +1696,13 @@ match_builtin_function_types (tree newtype, tree 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])));
+ const unsigned nlst
+ = sizeof last_structptr_types / sizeof last_structptr_types[0];
+ const unsigned nbst
+ = sizeof builtin_structptr_types / sizeof builtin_structptr_types[0];
+
+ gcc_checking_assert (nlst == nbst);
+
for (unsigned i = 1; oldargs || newargs; ++i)
{
if (!oldargs
@@ -1710,11 +1717,12 @@ match_builtin_function_types (tree newtype, tree oldtype,
if (!types_close_enough_to_match (oldtype, newtype))
return NULL_TREE;
- unsigned j = (sizeof (builtin_structptr_types)
- / sizeof (builtin_structptr_types[0]));
+ unsigned j = nbst;
if (POINTER_TYPE_P (oldtype))
- for (j = 0; j < (sizeof (builtin_structptr_types)
- / sizeof (builtin_structptr_types[0])); ++j)
+ /* Iterate over well-known struct types like FILE (whose types
+ aren't known to us) and compare the pointer to each to
+ the pointer argument. */
+ for (j = 0; j < nbst; ++j)
{
if (TREE_VALUE (oldargs) != builtin_structptr_types[j].node)
continue;
@@ -1734,13 +1742,26 @@ match_builtin_function_types (tree newtype, tree oldtype,
last_structptr_types[j] = newtype;
break;
}
- if (j == (sizeof (builtin_structptr_types)
- / sizeof (builtin_structptr_types[0]))
- && !*strict
- && !comptypes (oldtype, newtype))
+
+ if (j == nbst && !comptypes (oldtype, newtype))
{
- *argno = i;
- *strict = oldtype;
+ if (POINTER_TYPE_P (oldtype))
+ {
+ /* For incompatible pointers, only reject differences in
+ the unqualified variants of the referenced types but
+ consider differences in qualifiers as benign (report
+ those to caller via *STRICT below). */
+ tree oldref = TYPE_MAIN_VARIANT (TREE_TYPE (oldtype));
+ tree newref = TYPE_MAIN_VARIANT (TREE_TYPE (newtype));
+ if (!comptypes (oldref, newref))
+ return NULL_TREE;
+ }
+
+ if (!*strict)
+ {
+ *argno = i;
+ *strict = oldtype;
+ }
}
oldargs = TREE_CHAIN (oldargs);
@@ -1965,9 +1986,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
/* Accept "harmless" mismatches in function types such
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. */
+ size. However, diagnose return and argument types that are
+ incompatible according to language rules. */
tree mismatch_expect;
unsigned mismatch_argno;
@@ -2002,8 +2022,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (mismatch_expect && extra_warnings)
{
- /* 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)