aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBogdan Harjoc <harjoc@gmail.com>2018-08-03 15:25:35 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2018-08-03 16:25:35 +0100
commite5e7e50d4f75749e3ad3af44d364ccfcb81ced9e (patch)
tree976a94aedd0a8d55a01a8027541c47a938e0e252
parentd198fc5a69964c1d1cf55dd30d1696e531dc12d9 (diff)
downloadgcc-e5e7e50d4f75749e3ad3af44d364ccfcb81ced9e.zip
gcc-e5e7e50d4f75749e3ad3af44d364ccfcb81ced9e.tar.gz
gcc-e5e7e50d4f75749e3ad3af44d364ccfcb81ced9e.tar.bz2
Avoid infinite loop with duplicate anonymous union fields (PR c/86690).
If a struct contains an anonymous union and both have a field with the same name, detect_field_duplicates_hash() will replace one of them with NULL. If compilation doesn't stop immediately, it may later call lookup_field() on the union, which falsely assumes the union's LANG_SPECIFIC array is sorted, and may loop indefinitely because of this. 2018-08-03 Bogdan Harjoc <harjoc@gmail.com> PR c/86690 gcc/c: * c-typeck.c (lookup_field): Do not use TYPE_LANG_SPECIFIC after errors. gcc/testsuite: * gcc.dg/union-duplicate-field.c: New test. From-SVN: r263294
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-typeck.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/union-duplicate-field.c21
4 files changed, 39 insertions, 2 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 6e682cd..40e56f3 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2018-08-03 Bogdan Harjoc <harjoc@gmail.com>
+
+ PR c/86690
+ * c-typeck.c (lookup_field): Do not use TYPE_LANG_SPECIFIC after
+ errors.
+
2018-08-01 Martin Sebor <msebor@redhat.com>
PR tree-optimization/86650
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index f6a326c..2e9338e 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2207,9 +2207,14 @@ lookup_field (tree type, tree component)
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
to the field elements. Use a binary search on this array to quickly
find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC
- will always be set for structures which have many elements. */
+ will always be set for structures which have many elements.
- if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
+ Duplicate field checking replaces duplicates with NULL_TREE so
+ TYPE_LANG_SPECIFIC arrays are potentially no longer sorted. In that
+ case just iterate using DECL_CHAIN. */
+
+ if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s
+ && !seen_error ())
{
int bot, top, half;
tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 966c13b..ba0c4c6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-08-03 Bogdan Harjoc <harjoc@gmail.com>
+
+ PR c/86690
+ * gcc.dg/union-duplicate-field.c: New test.
+
2018-08-03 Jason Merrill <jason@redhat.com>
PR c++/86706
diff --git a/gcc/testsuite/gcc.dg/union-duplicate-field.c b/gcc/testsuite/gcc.dg/union-duplicate-field.c
new file mode 100644
index 0000000..da9a945
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/union-duplicate-field.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+int a0;
+
+struct S
+{
+ int a1;
+ union {
+ int a0;
+ int a1; /* { dg-error "duplicate member" } */
+ int a2, a3, a4, a5, a6, a7, a8, a9;
+ int a10, a11, a12, a13, a14, a15;
+ };
+};
+
+int f()
+{
+ struct S s;
+ return s.a0;
+}