https://gcc.gnu.org/g:4123f546d77c42287d2fcae6fb04df7b87193454
commit r14-10761-g4123f546d77c42287d2fcae6fb04df7b87193454 Author: Martin Uecker <uec...@tugraz.at> Date: Tue Sep 17 11:37:29 2024 +0200 c: fix crash when checking for compatibility of structures [PR116726] When checking for compatibility of structure or union types in tagged_types_tu_compatible_p, restore the old value of the pointer to the top of the temporary cache after recursively calling comptypes_internal when looping over the members of a structure of union. While the next iteration of the loop overwrites the pointer, I missed the fact that it can be accessed again when types of function arguments are compared as part of recursive type checking and the function is entered again. PR c/116726 gcc/c/ChangeLog: * c-typeck.cc (tagged_types_tu_compatible_p): Restore value of the cache after recursing into comptypes_internal. gcc/testsuite/ChangeLog: * gcc.dg/pr116726.c: New test. (cherry picked from commit 9227a64495d5594613604573b72422e8e3722fc5) Diff: --- gcc/c/c-typeck.cc | 5 ++++- gcc/testsuite/gcc.dg/pr116726.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 4567b114734b..ebc2c288f981 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -1611,8 +1611,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, data->anon_field = !DECL_NAME (s1); + const struct tagged_tu_seen_cache *cache = data->cache; data->cache = &entry; - if (!comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), data)) + bool ret = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), data); + data->cache = cache; + if (!ret) return false; tree st1 = TYPE_SIZE (TREE_TYPE (s1)); diff --git a/gcc/testsuite/gcc.dg/pr116726.c b/gcc/testsuite/gcc.dg/pr116726.c new file mode 100644 index 000000000000..bb25efca5864 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr116726.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c23" } */ + +struct s1 { + int f1; +}; +struct s2 { + int f2; +}; +struct s1 f(struct s2 *); + +struct s1 { + int f1; +}; +struct s2 { + int f2; +}; +struct s1 f(struct s2 *);