aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2020-12-03 18:35:00 -0500
committerMarek Polacek <polacek@redhat.com>2020-12-07 11:54:30 -0500
commit1cac89da2cb1f2a7c2d93f7f325484c2d1619ca8 (patch)
treed83a2760dce18de383aec51214737555dd9ad222 /gcc/testsuite
parentffb268ffcf9f21e2981a71887324eb0aec245eea (diff)
downloadgcc-1cac89da2cb1f2a7c2d93f7f325484c2d1619ca8.zip
gcc-1cac89da2cb1f2a7c2d93f7f325484c2d1619ca8.tar.gz
gcc-1cac89da2cb1f2a7c2d93f7f325484c2d1619ca8.tar.bz2
c-family: Fix hang with -Wsequence-point [PR98126]
verify_sequence_points uses verify_tree to recursively walk the subexpressions of an expression, and while recursing, it also keeps lists of expressions found after/before a sequence point. For a large expression, the list can grow significantly. And merge_tlist is at least N(n^2): for a list of length n it will iterate n(n -1) times, and call candidate_equal_p each time, and that can recurse further. warn_for_collision also has to go through the whole list. With a large-enough expression, the compilation can easily get stuck here for 24 hours. This patch is a simple kludge: if we see that the expression is overly complex, don't even try. gcc/c-family/ChangeLog: PR c++/98126 * c-common.c (verify_tree_lim_r): New function. (verify_sequence_points): Use it. Use nullptr instead of 0. gcc/testsuite/ChangeLog: PR c++/98126 * g++.dg/warn/Wsequence-point-4.C: New test.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsequence-point-4.C53
1 files changed, 53 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C b/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C
new file mode 100644
index 0000000..b3d9cf1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsequence-point-4.C
@@ -0,0 +1,53 @@
+// PR c++/98126
+// { dg-do compile }
+// { dg-options "-Wsequence-point" }
+// Make sure we don't hang when verify_tree processes a large expression.
+
+struct T { bool operator==(const T &ot) const; };
+
+#define CMP(M, N, L) t[100 * M + 10 * N + L] == ot.t[100 * M + 10 * N + L] &&
+
+#define CMP1(M, N) \
+ CMP(M, N, 0) \
+ CMP(M, N, 1) \
+ CMP(M, N, 2) \
+ CMP(M, N, 3) \
+ CMP(M, N, 4) \
+ CMP(M, N, 5) \
+ CMP(M, N, 6) \
+ CMP(M, N, 7) \
+ CMP(M, N, 8) \
+ CMP(M, N, 9)
+
+#define CMP2(M) \
+ CMP1(M, 0) \
+ CMP1(M, 1) \
+ CMP1(M, 2) \
+ CMP1(M, 3) \
+ CMP1(M, 4) \
+ CMP1(M, 5) \
+ CMP1(M, 6) \
+ CMP1(M, 7) \
+ CMP1(M, 8) \
+ CMP1(M, 9)
+
+#define GENERATE_CMPS \
+ CMP2(0) \
+ CMP2(1) \
+ CMP2(2) \
+ CMP2(3) \
+ CMP2(4) \
+ CMP2(5) \
+ CMP2(6) \
+ CMP2(7) \
+ CMP2(8) \
+ CMP2(9)
+
+struct C {
+ bool operator==(const C &ot) const {
+ return
+ GENERATE_CMPS
+ true;
+ }
+ T t[999];
+};