aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2023-06-26 09:57:21 -0700
committerIan Lance Taylor <iant@golang.org>2023-06-26 09:57:21 -0700
commitaa1e672b5d99102b03eb5fb9c51609c45f62bff7 (patch)
tree886212591b1c9d127eaaf234a4a2e22452ea384a /gcc/testsuite/gcc.dg
parent97e31a0a2a2d2273687fcdb4e5416aab1a2186e1 (diff)
parent3a39a31b8ae9c6465434aefa657f7fcc86f905c0 (diff)
downloadgcc-devel/gccgo.zip
gcc-devel/gccgo.tar.gz
gcc-devel/gccgo.tar.bz2
Merge from trunk revision 3a39a31b8ae9c6465434aefa657f7fcc86f905c0.devel/gccgo
Diffstat (limited to 'gcc/testsuite/gcc.dg')
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/data-model-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c5
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c40
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c13
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c24
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c55
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c29
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c82
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c53
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c43
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c110
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c30
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c45
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c45
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c40
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c125
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c36
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c34
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr101962.c2
-rw-r--r--gcc/testsuite/gcc.dg/missing-header-fixit-5.c10
-rw-r--r--gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c6
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c57
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c58
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c5
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c58
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c59
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c258
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr110332-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr110332-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr110381.c40
37 files changed, 1620 insertions, 15 deletions
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
index 86d1ccf..3c4a45f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
@@ -240,8 +240,8 @@ void test_16 (void)
__analyzer_eval (strlen (msg) == 11); /* { dg-warning "TRUE" } */
/* Out-of-bounds. */
- __analyzer_eval (msg[100] == 'e'); /* { dg-warning "UNKNOWN" } */
- // TODO: some kind of warning for the out-of-bounds access
+ __analyzer_eval (msg[100] == 'e'); /* { dg-warning "UNKNOWN" "eval result" } */
+ /* { dg-warning "buffer over-read" "out-of-bounds" { target *-*-* } .-1 } */
}
static const char *__attribute__((noinline))
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
index f08aee6..9134bb4 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
@@ -12,11 +12,6 @@ int test (void *ptr)
WRAPPED_FREE (ptr); /* { dg-message "in expansion of macro 'WRAPPED_FREE'" } */
WRAPPED_FREE (ptr); /* { dg-message "in expansion of macro 'WRAPPED_FREE'" } */
- /* Erase the spans indicating the header file
- (to avoid embedding path assumptions). */
- /* { dg-regexp "\[^|\]+/malloc-macro.h:\[0-9\]+:\[0-9\]+:" } */
- /* { dg-regexp "\[^|\]+/malloc-macro.h:\[0-9\]+:\[0-9\]+:" } */
-
/* { dg-begin-multiline-output "" }
NN | #define WRAPPED_FREE(PTR) free(PTR)
| ^~~~~~~~~
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c
new file mode 100644
index 0000000..5e6eadc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-ascii.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ +--------------------------------+
+ |write from 'x' (type: 'int32_t')|
+ +--------------------------------+
+ |
+ |
+ v
+ +--------+-----------------+---------++--------------------------------+
+ | [0] | ... | [9] || |
+ +--------+-----------------+---------+| after valid range |
+ | 'arr' (type: 'int32_t[10]') || |
+ +------------------------------------++--------------------------------+
+ |~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~|
+ | |
+ +---------+--------+ +---------+---------+
+ |capacity: 40 bytes| |overflow of 4 bytes|
+ +------------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c
new file mode 100644
index 0000000..4c4d9d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-debug.c
@@ -0,0 +1,40 @@
+/* Test of -fanalyzer-debug-text-art. */
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii -fanalyzer-debug-text-art" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+/* { dg-begin-multiline-output "" }
+
+ +---------+-----------+-----------+---+--------------------------------+
+ | tc0 | tc1 | tc2 |tc3| tc4 |
+ +---------+-----------+-----------+---+--------------------------------+
+ |bytes 0-3|bytes 4-35 |bytes 36-39| | bytes 40-43 |
+ +---------+-----------+-----------+ +--------------------------------+
+ +--------------------------------+
+ |write from 'x' (type: 'int32_t')|
+ +--------------------------------+
+ |
+ |
+ v
+ +---------+-----------+-----------+ +--------------------------------+
+ | [0] | ... | [9] | | |
+ +---------+-----------+-----------+ | after valid range |
+ | 'arr' (type: 'int32_t[10]') | | |
+ +---------------------------------+ +--------------------------------+
+ |~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~|
+ | |
+ +---------+--------+ +---------+---------+
+ |capacity: 40 bytes| |overflow of 4 bytes|
+ +------------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
new file mode 100644
index 0000000..1c61252
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=emoji" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────────┐
+ │write from 'x' (type: 'int32_t')│
+ └────────────────────────────────┘
+ │
+ │
+ v
+ ┌────────┬─────────────────┬─────────┐┌────────────────────────────────┐
+ │ [0] │ ... │ [9] ││ │
+ ├────────┴─────────────────┴─────────┤│ after valid range │
+ │ 'arr' (type: 'int32_t[10]') ││ │
+ └────────────────────────────────────┘└────────────────────────────────┘
+ ├─────────────────┬──────────────────┤├───────────────┬────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭───────────┴──────────╮
+ │capacity: 40 bytes│ │⚠️ overflow of 4 bytes│
+ ╰──────────────────╯ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c
new file mode 100644
index 0000000..0a2cc34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-json.c
@@ -0,0 +1,13 @@
+/* { dg-additional-options "-fdiagnostics-format=json-file" } */
+
+/* The custom JSON format doesn't support text art, so this is just a simple
+ smoketext. */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c
new file mode 100644
index 0000000..051a1ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-sarif.c
@@ -0,0 +1,24 @@
+/* We require -fdiagnostics-text-art-charset= to get any text art here
+ because of the test suite using -fdiagnostics-plain-output. */
+
+/* { dg-additional-options "-fdiagnostics-format=sarif-file -fdiagnostics-text-art-charset=ascii" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x;
+}
+
+/* Verify that some JSON was written to a file with the expected name.
+
+ { dg-final { verify-sarif-file } }
+
+ Expect the "alt-text" to be captured.
+ { dg-final { scan-sarif-file "\"text\": \"Diagram visualizing the predicted out-of-bounds access\"," } }
+
+ Expect the diagram to have 4 leading spaces (to indicate a code block),
+ and that at least part of the diagram was written out.
+ { dg-final { scan-sarif-file "\"markdown\": \" .*capacity: 40 bytes.*\"" } } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
new file mode 100644
index 0000000..71f66ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
@@ -0,0 +1,55 @@
+/* { dg-additional-options "-fdiagnostics-show-path-depths" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+
+int32_t arr[10];
+
+void int_arr_write_element_after_end_off_by_one(int32_t x)
+{
+ arr[10] = x; /* { dg-line line } */
+}
+/* { dg-warning "buffer overflow" "warning" { target *-*-* } line } */
+/* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } line } */
+
+
+/* { dg-begin-multiline-output "" }
+ arr[10] = x;
+ ~~~~~~~~^~~
+ event 1 (depth 0)
+ |
+ | int32_t arr[10];
+ | ^~~
+ | |
+ | (1) capacity: 40 bytes
+ |
+ +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+ |
+ | arr[10] = x;
+ | ~~~~~~~~^~~
+ | |
+ | (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+ |
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────────┐
+ │write from 'x' (type: 'int32_t')│
+ └────────────────────────────────┘
+ │
+ │
+ v
+ ┌────────┬─────────────────┬─────────┐┌────────────────────────────────┐
+ │ [0] │ ... │ [9] ││ │
+ ├────────┴─────────────────┴─────────┤│ after valid range │
+ │ 'arr' (type: 'int32_t[10]') ││ │
+ └────────────────────────────────────┘└────────────────────────────────┘
+ ├─────────────────┬──────────────────┤├───────────────┬────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 40 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c
new file mode 100644
index 0000000..4a7b8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-10.c
@@ -0,0 +1,29 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+int32_t int_vla_write_element_symbolic_before_start (int32_t x, size_t n)
+{
+ int32_t arr[n]; /* { dg-message "\\(1\\) capacity: 'n \\* 4' bytes" } */
+ arr[-2] = 42; /* { dg-warning "stack-based buffer underwrite" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────┐
+ │write of '(int) 42'│
+ └───────────────────┘
+ │
+ │
+ v
+ ┌───────────────────┐ ┌────────────────────────────────┐
+ │before valid range │ │buffer allocated on stack at (1)│
+ └───────────────────┘ └────────────────────────────────┘
+ ├─────────┬─────────┤├───────┬───────┤├───────────────┬────────────────┤
+ │ │ │
+ ╭─────────┴───────────╮ ╭───┴───╮ ╭───────────┴───────────╮
+ │underwrite of 4 bytes│ │4 bytes│ │capacity: 'n * 4' bytes│
+ ╰─────────────────────╯ ╰───────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c
new file mode 100644
index 0000000..f8eb158
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-11.c
@@ -0,0 +1,82 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+/* { dg-require-effective-target alloca } */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+void test6 (size_t size)
+{
+ int32_t *buf = __builtin_alloca (4 * size);
+ memset (buf, 0, 4 * size);
+ int32_t last = *(buf + 4 * size); /* { dg-warning "stack-based buffer over-read" } */
+}
+
+/* (size * 16) - (size * 4) leads to a gap of (size * 12). */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────┐
+ │ read of 4 bytes │
+ └─────────────────┘
+ ^
+ │
+ │
+ ┌────────────────────────────────┐ ┌─────────────────┐
+ │buffer allocated on stack at (1)│ │after valid range│
+ └────────────────────────────────┘ └─────────────────┘
+ ├───────────────┬────────────────┤├────────┬────────┤├────────┬────────┤
+ │ │ │
+ │ │ ╭──────────┴─────────╮
+ │ │ │over-read of 4 bytes│
+ │ │ ╰────────────────────╯
+ ╭───────────┴──────────╮ ╭────────┴────────╮
+ │size: 'size * 4' bytes│ │'size * 12' bytes│
+ ╰──────────────────────╯ ╰─────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+void test7 (size_t size)
+{
+ int32_t *buf = __builtin_alloca (4 * size + 3); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */
+ buf[size] = 42; /* { dg-warning "stack-based buffer overflow" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────────────────────────┐
+ │ write of '(int) 42' │
+ └───────────────────────────────────────┘
+ │ │
+ │ │
+ v v
+ ┌──────────────────────────────────────────────────┐┌──────────────────┐
+ │ buffer allocated on stack at (1) ││after valid range │
+ └──────────────────────────────────────────────────┘└──────────────────┘
+ ├────────────────────────┬─────────────────────────┤├────────┬─────────┤
+ │ │
+ ╭───────────────┴──────────────╮ ╭─────────┴────────╮
+ │capacity: 'size * 4 + 3' bytes│ │overflow of 1 byte│
+ ╰──────────────────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+
+/* We're currently not able to generate a diagram for this case;
+ make sure we handle this case gracefully. */
+
+char *test99 (const char *x, const char *y)
+{
+ size_t len_x = __builtin_strlen (x);
+ size_t len_y = __builtin_strlen (y);
+ /* BUG (root cause): forgot to add 1 for terminator. */
+ size_t sz = len_x + len_y;
+ char *result = __builtin_malloc (sz);
+ if (!result)
+ return NULL;
+ __builtin_memcpy (result, x, len_x);
+ __builtin_memcpy (result + len_x, y, len_y);
+ /* BUG (symptom): off-by-one out-of-bounds write to heap. */
+ result[len_x + len_y] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
+ return result;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c
new file mode 100644
index 0000000..3573750
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-12.c
@@ -0,0 +1,53 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+/* { dg-require-effective-target alloca } */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+void test8 (size_t size, size_t offset)
+{
+ char src[size];
+ char dst[size];
+ memcpy (dst, src, size + offset); /* { dg-line test8 } */
+ /* { dg-warning "over-read" "warning" { target *-*-* } test8 } */
+ /* { dg-warning "overflow" "warning" { target *-*-* } test8 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ read of 'size + offset' bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ ^ ^
+ │ │
+ │ │
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────────┴─────────────╮
+ │size: 'size' bytes│ │over-read of 'offset' bytes│
+ ╰──────────────────╯ ╰───────────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 'size + offset' bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │
+ │ │
+ v v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭───────────┴──────────╮ ╭─────────────┴────────────╮
+ │capacity: 'size' bytes│ │overflow of 'offset' bytes│
+ ╰──────────────────────╯ ╰──────────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c
new file mode 100644
index 0000000..dcd1263
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-13.c
@@ -0,0 +1,43 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[9];
+ strcpy (buf, "Liberté\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 10 bytes into a region of size 9 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* Example of non-ASCII UTF-8 that's short enough to fully quote, whilst
+ containing control characters. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬──────┬──────┬──────┬────┬────┬──────┐┌─────────────────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │[6] │[7] │ [8] ││ [9] │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┼────┼──────┤├─────────────────┤
+ │ 0x4c │ 0x69 │ 0x62 │ 0x65 │ 0x72 │ 0x74 │0xc3│0xa9│ 0x0a ││ 0x00 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┴────┼──────┤├─────────────────┤
+ │U+004c│U+0069│U+0062│U+0065│U+0072│U+0074│ U+00e9 │U+000a││ U+0000 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼─────────┼──────┤├─────────────────┤
+ │ L │ i │ b │ e │ r │ t │ é │ ││ NUL │
+ ├──────┴──────┴──────┴──────┴──────┴──────┴─────────┴──────┴┴─────────────────┤
+ │ string literal (type: 'char[10]') │
+ └─────────────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v
+ ┌──────┬────────────────────────────────────────────┬──────┐┌─────────────────┐
+ │ [0] │ ... │ [8] ││ │
+ ├──────┴────────────────────────────────────────────┴──────┤│after valid range│
+ │ 'buf' (type: 'char[9]') ││ │
+ └──────────────────────────────────────────────────────────┘└─────────────────┘
+ ├────────────────────────────┬─────────────────────────────┤├────────┬────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴────────╮
+ │capacity: 9 bytes│ │overflow of 1 byte│
+ ╰─────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c
new file mode 100644
index 0000000..3cedf06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-14.c
@@ -0,0 +1,110 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+
+extern int32_t arr_0[0]; /* { dg-message "capacity: 0 bytes" } */
+extern int32_t arr_1[1]; /* { dg-message "capacity: 4 bytes" } */
+extern int32_t arr_2[2]; /* { dg-message "capacity: 8 bytes" } */
+extern int32_t arr_3[3]; /* { dg-message "capacity: 12 bytes" } */
+extern int32_t arr_4[4]; /* { dg-message "capacity: 16 bytes" } */
+
+void test_immediately_after (int x)
+{
+ arr_0[0] = x; /* { dg-warning "buffer overflow" } */
+ arr_1[1] = x; /* { dg-warning "buffer overflow" } */
+ arr_2[2] = x; /* { dg-warning "buffer overflow" } */
+ arr_3[3] = x; /* { dg-warning "buffer overflow" } */
+ arr_4[4] = x; /* { dg-warning "buffer overflow" } */
+}
+
+/* Expect no diagram for the arr_0 case: there's no valid region
+to write to. */
+
+/* The arr_1 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write from 'x' (type: 'int') │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ [0] ││ │
+ ├──────────────────────────────────┤│ after valid range │
+ │ 'arr_1' (type: 'int32_t[1]') ││ │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 4 bytes│ │overflow of 4 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_2 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌────────────────────┬───────────────────┐┌────────────────────────────┐
+ │ [0] │ [1] ││ │
+ ├────────────────────┴───────────────────┤│ after valid range │
+ │ 'arr_2' (type: 'int32_t[2]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 8 bytes│ │overflow of 4 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_3 case. */
+// Perhaps we should show [1] rather than ellipsize here.
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌─────────────┬─────────────┬────────────┐┌────────────────────────────┐
+ │ [0] │ ... │ [2] ││ │
+ ├─────────────┴─────────────┴────────────┤│ after valid range │
+ │ 'arr_3' (type: 'int32_t[3]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 12 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The arr_4 case. */
+/* { dg-begin-multiline-output "" }
+
+ ┌────────────────────────────┐
+ │write from 'x' (type: 'int')│
+ └────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────┬──────────────────┬──────────┐┌────────────────────────────┐
+ │ [0] │ ... │ [3] ││ │
+ ├──────────┴──────────────────┴──────────┤│ after valid range │
+ │ 'arr_4' (type: 'int32_t[4]') ││ │
+ └────────────────────────────────────────┘└────────────────────────────┘
+ ├───────────────────┬────────────────────┤├─────────────┬──────────────┤
+ │ │
+ ╭─────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 16 bytes│ │overflow of 4 bytes│
+ ╰──────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c
new file mode 100644
index 0000000..e2a6381
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-15.c
@@ -0,0 +1,42 @@
+/* Regression test for ICE with short values of
+ --param=analyzer-text-art-string-ellipsis-threshold=. */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode --param=analyzer-text-art-string-ellipsis-threshold=0" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[9];
+ strcpy (buf, "Liberté\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 10 bytes into a region of size 9 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬──────┬──────┬──────┬────┬────┬──────┐┌─────────────────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │[6] │[7] │ [8] ││ [9] │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┼────┼──────┤├─────────────────┤
+ │ 0x4c │ 0x69 │ 0x62 │ 0x65 │ 0x72 │ 0x74 │0xc3│0xa9│ 0x0a ││ 0x00 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼────┴────┼──────┤├─────────────────┤
+ │U+004c│U+0069│U+0062│U+0065│U+0072│U+0074│ U+00e9 │U+000a││ U+0000 │
+ ├──────┼──────┼──────┼──────┼──────┼──────┼─────────┼──────┤├─────────────────┤
+ │ L │ i │ b │ e │ r │ t │ é │ ││ NUL │
+ ├──────┴──────┴──────┴──────┴──────┴──────┴─────────┴──────┴┴─────────────────┤
+ │ string literal (type: 'char[10]') │
+ └─────────────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v
+ ┌──────┬────────────────────────────────────────────┬──────┐┌─────────────────┐
+ │ [0] │ ... │ [8] ││ │
+ ├──────┴────────────────────────────────────────────┴──────┤│after valid range│
+ │ 'buf' (type: 'char[9]') ││ │
+ └──────────────────────────────────────────────────────────┘└─────────────────┘
+ ├────────────────────────────┬─────────────────────────────┤├────────┬────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴────────╮
+ │capacity: 9 bytes│ │overflow of 1 byte│
+ ╰─────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c
new file mode 100644
index 0000000..535dab1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-2.c
@@ -0,0 +1,30 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+void int_vla_write_element_after_end_off_by_one(int32_t x, size_t n)
+{
+ int32_t arr[n]; /* { dg-message "\\(1\\) capacity: 'n \\* 4' bytes" } */
+
+ arr[n] = x; /* { dg-warning "stack-based buffer overflow" } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write from 'x' (type: 'int32_t') │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on stack at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭───────────┴───────────╮ ╭─────────┴─────────╮
+ │capacity: 'n * 4' bytes│ │overflow of 4 bytes│
+ ╰───────────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c
new file mode 100644
index 0000000..064f3fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-3.c
@@ -0,0 +1,45 @@
+/* The multiline output assumes sizeof(size_t) == 8.
+ { dg-require-effective-target lp64 } */
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+struct str {
+ size_t len;
+ char data[];
+};
+
+struct str *
+make_str_badly (const char *src)
+{
+ size_t len = strlen(src);
+ struct str *str = malloc(sizeof(str) + len); /* { dg-message "\\(1\\) capacity: 'len \\+ 8' bytes" } */
+ if (!str)
+ return NULL;
+ str->len = len;
+ memcpy(str->data, src, len);
+ str->data[len] = '\0'; /* { dg-warning "heap-based buffer overflow" } */
+ return str;
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────┐
+ │ write of '(char) 0' │
+ └──────────────────────────────────┘
+ │
+ │
+ v
+ ┌──────────────────────────────────┐┌──────────────────────────────────┐
+ │ buffer allocated on heap at (1) ││ after valid range │
+ └──────────────────────────────────┘└──────────────────────────────────┘
+ ├────────────────┬─────────────────┤├────────────────┬─────────────────┤
+ │ │
+ ╭────────────┴────────────╮ ╭─────────┴────────╮
+ │capacity: 'len + 8' bytes│ │overflow of 1 byte│
+ ╰─────────────────────────╯ ╰──────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c
new file mode 100644
index 0000000..ec8e4ab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-4.c
@@ -0,0 +1,45 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+#define LOREM_IPSUM \
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod" \
+ " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim" \
+ " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea" \
+ " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate" \
+ " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint" \
+ " occaecat cupidatat non proident, sunt in culpa qui officia deserunt" \
+ " mollit anim id est laborum."
+
+void
+test_long_string ()
+{
+ char buf[100];
+ strcpy (buf, LOREM_IPSUM); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 446 bytes into a region of size 100 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───┬───┬───┬───┬───┬───┬──────────┬─────┬─────┬─────┬─────┬─────┬─────┐
+ │[0]│[1]│[2]│[3]│[4]│[5]│ │[440]│[441]│[442]│[443]│[444]│[445]│
+ ├───┼───┼───┼───┼───┼───┤ ... ├─────┼─────┼─────┼─────┼─────┼─────┤
+ │'L'│'o'│'r'│'e'│'m'│' '│ │ 'o' │ 'r' │ 'u' │ 'm' │ '.' │ NUL │
+ ├───┴───┴───┴───┴───┴───┴──────────┴─────┴─────┴─────┴─────┴─────┴─────┤
+ │ string literal (type: 'char[446]') │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v v v v v v
+ ┌───┬─────────────────────┬────┐┌──────────────────────────────────────┐
+ │[0]│ ... │[99]││ │
+ ├───┴─────────────────────┴────┤│ after valid range │
+ │ 'buf' (type: 'char[100]') ││ │
+ └──────────────────────────────┘└──────────────────────────────────────┘
+ ├──────────────┬───────────────┤├──────────────────┬───────────────────┤
+ │ │
+ ╭─────────┴─────────╮ ╭──────────┴──────────╮
+ │capacity: 100 bytes│ │overflow of 346 bytes│
+ ╰───────────────────╯ ╰─────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c
new file mode 100644
index 0000000..e82bce9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-ascii.c
@@ -0,0 +1,40 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[5];
+ strcpy (buf, "文字化け"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 13 bytes into a region of size 5 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* Without unicode support, we shouldn't show the printable unicode chars. */
+
+/* { dg-begin-multiline-output "" }
+
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ | [0] | [1] | [2] |[3] |[4] ||[5] |[6] |[7] |[8] |[9] |[10]|[11]| [12] |
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ |0xe6 |0x96 |0x87 |0xe5|0xad||0x97|0xe5|0x8c|0x96|0xe3|0x81|0x91| 0x00 |
+ +-----+-----+-----+----+----++----+----+----+----+----+----+----+------+
+ | U+6587 | U+5b57 | U+5316 | U+3051 |U+0000|
+ +-----------------+---------------+--------------+--------------+------+
+ | string literal (type: 'char[13]') |
+ +----------------------------------------------------------------------+
+ | | | | | | | | | | | | |
+ | | | | | | | | | | | | |
+ v v v v v v v v v v v v v
+ +-----+----------------+----++-----------------------------------------+
+ | [0] | ... |[4] || |
+ +-----+----------------+----+| after valid range |
+ | 'buf' (type: 'char[5]') || |
+ +---------------------------++-----------------------------------------+
+ |~~~~~~~~~~~~~+~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~|
+ | |
+ +--------+--------+ +---------+---------+
+ |capacity: 5 bytes| |overflow of 8 bytes|
+ +-----------------+ +-------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c
new file mode 100644
index 0000000..48fa12f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-5-unicode.c
@@ -0,0 +1,42 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_non_ascii ()
+{
+ char buf[5];
+ strcpy (buf, "文字化け"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 13 bytes into a region of size 5 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* With unicode support, we should show the printable unicode chars. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────┬─────┬─────┬────┬────┐┌────┬────┬────┬────┬────┬────┬────┬──────┐
+ │ [0] │ [1] │ [2] │[3] │[4] ││[5] │[6] │[7] │[8] │[9] │[10]│[11]│ [12] │
+ ├─────┼─────┼─────┼────┼────┤├────┼────┼────┼────┼────┼────┼────┼──────┤
+ │0xe6 │0x96 │0x87 │0xe5│0xad││0x97│0xe5│0x8c│0x96│0xe3│0x81│0x91│ 0x00 │
+ ├─────┴─────┴─────┼────┴────┴┴────┼────┴────┴────┼────┴────┴────┼──────┤
+ │ U+6587 │ U+5b57 │ U+5316 │ U+3051 │U+0000│
+ ├─────────────────┼───────────────┼──────────────┼──────────────┼──────┤
+ │ 文 │ 字 │ 化 │ け │ NUL │
+ ├─────────────────┴───────────────┴──────────────┴──────────────┴──────┤
+ │ string literal (type: 'char[13]') │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v v v v
+ ┌─────┬────────────────┬────┐┌─────────────────────────────────────────┐
+ │ [0] │ ... │[4] ││ │
+ ├─────┴────────────────┴────┤│ after valid range │
+ │ 'buf' (type: 'char[5]') ││ │
+ └───────────────────────────┘└─────────────────────────────────────────┘
+ ├─────────────┬─────────────┤├────────────────────┬────────────────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 5 bytes│ │overflow of 8 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c
new file mode 100644
index 0000000..25bf9d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-6.c
@@ -0,0 +1,125 @@
+/* { dg-require-effective-target lp64 }
+ Misbehaves with -m32 due to optimization turning the pointer arithmetic into:
+ _2 = &buf + 4294967246;
+ memcpy (_2, _1, 4096);
+*/
+
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+#define LOREM_IPSUM \
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod" \
+ " tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim" \
+ " veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea" \
+ " commodo consequat. Duis aute irure dolor in reprehenderit in voluptate" \
+ " velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint" \
+ " occaecat cupidatat non proident, sunt in culpa qui officia deserunt" \
+ " mollit anim id est laborum."
+
+/* This memcpy reads from both before and after the bounds of the
+ string literal, and writes to both before and after the bounds of "buf". */
+
+void
+test_bad_memcpy ()
+{
+ char buf[100];
+ memcpy (buf - 50, LOREM_IPSUM - 100, 4096); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "stack-based buffer underwrite" "" { target *-*-* } .-1 } */
+ /* { dg-warning "buffer under-read" "" { target *-*-* } .-2 } */
+ /* { dg-warning "buffer over-read" "" { target *-*-* } .-3 } */
+ /* { dg-warning "'memcpy' writing 4096 bytes into a region of size 0 overflows the destination" "" { target *-*-* } .-4 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ read of 4096 bytes │
+ └─────────────────────────────────────────────────────────────────────────┘
+ ^ ^ ^ ^ ^
+ │ │ │ │ │
+ │ │ │ │ │
+ ┌──────────────────┐┌──────────┬──────────┬────────────┐┌─────────────────┐
+ │ ││ [0] │ ... │ [445] ││ │
+ │before valid range│├──────────┴──────────┴────────────┤│after valid range│
+ │ ││string literal (type: 'char[446]')││ │
+ └──────────────────┘└──────────────────────────────────┘└─────────────────┘
+ ├────────┬─────────┤├────────────────┬─────────────────┤├────────┬────────┤
+ │ │ │
+ ╭────────┴──────────────╮ ╭───────┴───────╮ ╭───────────┴───────────╮
+ │under-read of 100 bytes│ │size: 446 bytes│ │over-read of 3550 bytes│
+ ╰───────────────────────╯ ╰───────────────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 4096 bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │
+ │ │ │ │ │
+ v v v v v
+ ┌──────────────────┐┌───────┬───────┬─────────┐┌───────────────────────┐
+ │ ││ [0] │ ... │ [99] ││ │
+ │before valid range│├───────┴───────┴─────────┤│ after valid range │
+ │ ││'buf' (type: 'char[100]')││ │
+ └──────────────────┘└─────────────────────────┘└───────────────────────┘
+ ├────────┬─────────┤├────────────┬────────────┤├───────────┬───────────┤
+ │ │ │
+ │ ╭─────────┴─────────╮ ╭───────────┴──────────╮
+ │ │capacity: 100 bytes│ │overflow of 3946 bytes│
+ │ ╰───────────────────╯ ╰──────────────────────╯
+ ╭────────┴─────────────╮
+ │underwrite of 50 bytes│
+ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* The read and write diagrams are each emitted twice: once for the "before"
+ and once for the "after" diagnostic. */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ read of 4096 bytes │
+ └─────────────────────────────────────────────────────────────────────────┘
+ ^ ^ ^ ^ ^
+ │ │ │ │ │
+ │ │ │ │ │
+ ┌──────────────────┐┌──────────┬──────────┬────────────┐┌─────────────────┐
+ │ ││ [0] │ ... │ [445] ││ │
+ │before valid range│├──────────┴──────────┴────────────┤│after valid range│
+ │ ││string literal (type: 'char[446]')││ │
+ └──────────────────┘└──────────────────────────────────┘└─────────────────┘
+ ├────────┬─────────┤├────────────────┬─────────────────┤├────────┬────────┤
+ │ │ │
+ ╭────────┴──────────────╮ ╭───────┴───────╮ ╭───────────┴───────────╮
+ │under-read of 100 bytes│ │size: 446 bytes│ │over-read of 3550 bytes│
+ ╰───────────────────────╯ ╰───────────────╯ ╰───────────────────────╯
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────────────────────────────────────────────────────────────────────┐
+ │ write of 4096 bytes │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │
+ │ │ │ │ │
+ v v v v v
+ ┌──────────────────┐┌───────┬───────┬─────────┐┌───────────────────────┐
+ │ ││ [0] │ ... │ [99] ││ │
+ │before valid range│├───────┴───────┴─────────┤│ after valid range │
+ │ ││'buf' (type: 'char[100]')││ │
+ └──────────────────┘└─────────────────────────┘└───────────────────────┘
+ ├────────┬─────────┤├────────────┬────────────┤├───────────┬───────────┤
+ │ │ │
+ │ ╭─────────┴─────────╮ ╭───────────┴──────────╮
+ │ │capacity: 100 bytes│ │overflow of 3946 bytes│
+ │ ╰───────────────────╯ ╰──────────────────────╯
+ ╭────────┴─────────────╮
+ │underwrite of 50 bytes│
+ ╰──────────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c
new file mode 100644
index 0000000..25a9acc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-7.c
@@ -0,0 +1,36 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <string.h>
+
+void
+test_string_with_control_chars ()
+{
+ char buf[8];
+ strcpy (buf, "\tone\n\ttwo\n"); /* { dg-warning "stack-based buffer overflow" } */
+ /* { dg-warning "'__builtin_memcpy' writing 11 bytes into a region of size 8 overflows the destination" "" { target *-*-* } .-1 } */
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──────┬──────┬──────┬─────┬─────┬─────┬─────┬─────┐┌─────┬─────┬──────┐
+ │ [0] │ [1] │ [2] │ [3] │ [4] │ [5] │ [6] │ [7] ││ [8] │ [9] │ [10] │
+ ├──────┼──────┼──────┼─────┼─────┼─────┼─────┼─────┤├─────┼─────┼──────┤
+ │ 0x09 │ 'o' │ 'n' │ 'e' │0x0a │0x09 │ 't' │ 'w' ││ 'o' │0x0a │ NUL │
+ ├──────┴──────┴──────┴─────┴─────┴─────┴─────┴─────┴┴─────┴─────┴──────┤
+ │ string literal (type: 'char[11]') │
+ └──────────────────────────────────────────────────────────────────────┘
+ │ │ │ │ │ │ │ │ │ │ │
+ │ │ │ │ │ │ │ │ │ │ │
+ v v v v v v v v v v v
+ ┌──────┬─────────────────────────────────────┬─────┐┌──────────────────┐
+ │ [0] │ ... │ [7] ││ │
+ ├──────┴─────────────────────────────────────┴─────┤│after valid range │
+ │ 'buf' (type: 'char[8]') ││ │
+ └──────────────────────────────────────────────────┘└──────────────────┘
+ ├────────────────────────┬─────────────────────────┤├────────┬─────────┤
+ │ │
+ ╭────────┴────────╮ ╭─────────┴─────────╮
+ │capacity: 8 bytes│ │overflow of 3 bytes│
+ ╰─────────────────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c
new file mode 100644
index 0000000..24d8735
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-8.c
@@ -0,0 +1,34 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+/* Gap of 4, then an overflow of 4. */
+
+void test2 (size_t size)
+{
+ int32_t *buf = __builtin_malloc (size * sizeof(int32_t)); /* { dg-message "\\(1\\) capacity: 'size \\* 4' bytes" } */
+ if (!buf) return;
+
+ buf[size + 1] = 42; /* { dg-warning "heap-based buffer overflow" } */
+ __builtin_free (buf);
+}
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────┐
+ │write of '(int) 42'│
+ └───────────────────┘
+ │
+ │
+ v
+ ┌───────────────────────────────┐ ┌───────────────────┐
+ │buffer allocated on heap at (1)│ │ after valid range │
+ └───────────────────────────────┘ └───────────────────┘
+ ├───────────────┬───────────────┤├───────┬────────┤├─────────┬─────────┤
+ │ │ │
+ ╭─────────────┴────────────╮ ╭───┴───╮ ╭─────────┴─────────╮
+ │capacity: 'size * 4' bytes│ │4 bytes│ │overflow of 4 bytes│
+ ╰──────────────────────────╯ ╰───────╯ ╰───────────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c
new file mode 100644
index 0000000..bb9ad66
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-9.c
@@ -0,0 +1,42 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode" } */
+
+#include <stdint.h>
+
+struct st
+{
+ char buf[16];
+ int32_t x;
+ int32_t y;
+};
+
+struct st arr[10];
+
+int32_t struct_arr_read_x_element_before_start_far(void)
+{
+ return arr[-100].x; /* { dg-warning "buffer under-read" "warning" } */
+ /* { dg-message "out-of-bounds read from byte -2384 till byte -2381 but 'arr' starts at byte 0" "final event" { target *-*-* } .-1 } */
+ /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[9\\\]'" "valid subscript note" { target *-*-* } .-2 } */
+}
+
+// TODO: show index of accessed element
+// TODO: show field of accessed element
+/* { dg-begin-multiline-output "" }
+
+ ┌───────────────────────────┐
+ │read of 'int32_t' (4 bytes)│
+ └───────────────────────────┘
+ ^
+ │
+ │
+ ┌───────────────────────────┐ ┌─────────┬─────────┬─────────┐
+ │ │ │ [0] │ ... │ [9] │
+ │ before valid range │ ├─────────┴─────────┴─────────┤
+ │ │ │'arr' (type: 'struct st[10]')│
+ └───────────────────────────┘ └─────────────────────────────┘
+ ├─────────────┬─────────────┤├────┬─────┤├──────────────┬──────────────┤
+ │ │ │
+ ╭──────────┴──────────╮ ╭─────┴────╮ ╭───────┴───────╮
+ │under-read of 4 bytes│ │2380 bytes│ │size: 240 bytes│
+ ╰─────────────────────╯ ╰──────────╯ ╰───────────────╯
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
index 7c8d1b3..5b8ff7b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pattern-test-2.c
@@ -26,7 +26,7 @@ void test_2 (void *p, void *q)
foo(p);
/* { dg-warning "pattern match on 'p != 0'" "p != 0" { target *-*-* } cond_2 } */
- /* { dg-warning "pattern match on 'tmp1 | tmp2 != 0'" "tmp1 | tmp2 != 0" { target *-*-* } cond_2 } */
+ /* { dg-warning "pattern match on 'p == 0 | q == 0 != 0'" "tmp1 | tmp2 != 0" { target *-*-* } cond_2 } */
/* { dg-warning "pattern match on 'q != 0'" "q != 0" { target *-*-* } cond_2 } */
}
@@ -42,6 +42,6 @@ void test_3 (void *p, void *q)
foo(p);
/* { dg-warning "pattern match on 'p == 0'" "p == 0" { target *-*-* } cond_3 } */
- /* { dg-warning "pattern match on 'tmp1 & tmp2 == 0'" "tmp1 & tmp2 == 0" { target *-*-* } cond_3 } */
+ /* { dg-warning "pattern match on 'p == 0 & q == 0 == 0'" "tmp1 & tmp2 == 0" { target *-*-* } cond_3 } */
/* { dg-warning "pattern match on 'q == 0'" "q == 0" { target *-*-* } cond_3 } */
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101962.c b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
index b878aad..5eb7cf0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101962.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101962.c
@@ -16,7 +16,7 @@ maybe_inc_int_ptr (int *ptr)
int
test_1 (void)
{
- int stack; /* { dg-message "region created on stack here" } */
+ int stack;
int *a = &stack;
a = maybe_inc_int_ptr (a);
a = maybe_inc_int_ptr (a);
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-5.c b/gcc/testsuite/gcc.dg/missing-header-fixit-5.c
index 916033c..bf44feb 100644
--- a/gcc/testsuite/gcc.dg/missing-header-fixit-5.c
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-5.c
@@ -12,14 +12,18 @@ foo (char *m, int i)
/* { dg-begin-multiline-output "" }
11 | if (isdigit (m[0]))
| ^~~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+++ |+#include <ctype.h>
1 |
{ dg-end-multiline-output "" } */
{
return abs (i); /* { dg-warning "implicit declaration of function" } */
/* { dg-begin-multiline-output "" }
- 19 | return abs (i);
+ 21 | return abs (i);
| ^~~
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+++ |+#include <stdlib.h>
1 |
{ dg-end-multiline-output "" } */
@@ -27,8 +31,10 @@ foo (char *m, int i)
else
putchar (m[0]); /* { dg-warning "implicit declaration of function" } */
/* { dg-begin-multiline-output "" }
- 28 | putchar (m[0]);
+ 32 | putchar (m[0]);
| ^~~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-begin-multiline-output "" }
+++ |+#include <stdio.h>
1 |
{ dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c
index e494315..e0fc9cd 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.c
@@ -155,7 +155,7 @@ class double_save_thread : public gil_diagnostic
return m_call == sub_other.m_call;
}
- bool emit (rich_location *rich_loc) final override
+ bool emit (rich_location *rich_loc, logger *) final override
{
return warning_at (rich_loc, get_controlling_option (),
"nested usage of %qs", "Py_BEGIN_ALLOW_THREADS");
@@ -194,7 +194,7 @@ class fncall_without_gil : public gil_diagnostic
&& m_arg_idx == sub_other.m_arg_idx);
}
- bool emit (rich_location *rich_loc) final override
+ bool emit (rich_location *rich_loc, logger *) final override
{
auto_diagnostic_group d;
if (m_callee_fndecl)
@@ -245,7 +245,7 @@ class pyobject_usage_without_gil : public gil_diagnostic
((const pyobject_usage_without_gil&)base_other).m_expr);
}
- bool emit (rich_location *rich_loc) final override
+ bool emit (rich_location *rich_loc, logger *) final override
{
auto_diagnostic_group d;
return warning_at (rich_loc, get_controlling_option (),
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c
new file mode 100644
index 0000000..e4239aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-bw.c
@@ -0,0 +1,57 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii -fdiagnostics-color=never" } */
+
+int non_empty;
+
+/* { dg-begin-multiline-output "" }
+
+ A
+ B
+ C
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
+ ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟
+
+
+
+
+ ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
+ ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ +--+
+ |🙂|
+ +--+
+
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+
+ +-------+-----+---------------+---------------------+-----------------------+-----------------------+
+ |Offsets|Octet| 0 | 1 | 2 | 3 |
+ +-------+-----+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | Octet | Bit |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
+ +-------+-----+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 0 | 0 |Version| IHL | DSCP | ECN | Total Length |
+ +-------+-----+-------+-------+---------------+-----+--------+--------------------------------------+
+ | 4 | 32 | Identification | Flags | Fragment Offset |
+ +-------+-----+---------------+---------------------+--------+--------------------------------------+
+ | 8 | 64 | Time To Live | Protocol | Header Checksum |
+ +-------+-----+---------------+---------------------+-----------------------------------------------+
+ | 12 | 96 | Source IP Address |
+ +-------+-----+-------------------------------------------------------------------------------------+
+ | 16 | 128 | Destination IP Address |
+ +-------+-----+-------------------------------------------------------------------------------------+
+ | 20 | 160 | |
+ +-------+-----+ |
+ | ... | ... | Options |
+ +-------+-----+ |
+ | 56 | 448 | |
+ +-------+-----+-------------------------------------------------------------------------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c
new file mode 100644
index 0000000..0650428
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-ascii-color.c
@@ -0,0 +1,58 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=ascii -fdiagnostics-color=always" } */
+
+int non_empty;
+
+/* { dg-begin-multiline-output "" }
+
+ A
+ B
+ C
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜ 
+ ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟ 
+         
+         
+         
+         
+ ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙ 
+ ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖ 
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ +--+
+ |🙂|
+ +--+
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ +-------+-----+---------------+---------------------+-----------------------+-----------------------+
+ |Offsets|Octet| 0 | 1 | 2 | 3 |
+ +-------+-----+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | Octet | Bit |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
+ +-------+-----+-+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 0 | 0 |Version| IHL | DSCP | ECN | Total Length |
+ +-------+-----+-------+-------+---------------+-----+--------+--------------------------------------+
+ | 4 | 32 | Identification | Flags | Fragment Offset |
+ +-------+-----+---------------+---------------------+--------+--------------------------------------+
+ | 8 | 64 | Time To Live | Protocol | Header Checksum |
+ +-------+-----+---------------+---------------------+-----------------------------------------------+
+ | 12 | 96 | Source IP Address |
+ +-------+-----+-------------------------------------------------------------------------------------+
+ | 16 | 128 | Destination IP Address |
+ +-------+-----+-------------------------------------------------------------------------------------+
+ | 20 | 160 | |
+ +-------+-----+ |
+ | ... | ... | Options |
+ +-------+-----+ |
+ | 56 | 448 | |
+ +-------+-----+-------------------------------------------------------------------------------------+
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c
new file mode 100644
index 0000000..c8118b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-none.c
@@ -0,0 +1,5 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=none" } */
+
+int non_empty;
+
+/* We expect no output. */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c
new file mode 100644
index 0000000..c9f5b36
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-bw.c
@@ -0,0 +1,58 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode -fdiagnostics-color=never" } */
+
+int non_empty;
+
+/* { dg-begin-multiline-output "" }
+
+ A
+ B
+ C
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜
+ ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟
+
+
+
+
+ ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙
+ ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──┐
+ │🙂│
+ └──┘
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────┬─────┬───────────────┬─────────────────────┬───────────────────────┬───────────────────────┐
+ │Offsets│Octet│ 0 │ 1 │ 2 │ 3 │
+ ├───────┼─────┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬──┬──┬──┬──┬──┬──┼──┬──┬──┬──┬──┬──┬──┬──┼──┬──┬──┬──┬──┬──┬──┬──┤
+ │ Octet │ Bit │0│1│2│3│4│5│6│7│8│9│10│11│12│13│14│15│16│17│18│19│20│21│22│23│24│25│26│27│28│29│30│31│
+ ├───────┼─────┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴──┴──┴──┴──┼──┴──┼──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┤
+ │ 0 │ 0 │Version│ IHL │ DSCP │ ECN │ Total Length │
+ ├───────┼─────┼───────┴───────┴───────────────┴─────┼────────┬──────────────────────────────────────┤
+ │ 4 │ 32 │ Identification │ Flags │ Fragment Offset │
+ ├───────┼─────┼───────────────┬─────────────────────┼────────┴──────────────────────────────────────┤
+ │ 8 │ 64 │ Time To Live │ Protocol │ Header Checksum │
+ ├───────┼─────┼───────────────┴─────────────────────┴───────────────────────────────────────────────┤
+ │ 12 │ 96 │ Source IP Address │
+ ├───────┼─────┼─────────────────────────────────────────────────────────────────────────────────────┤
+ │ 16 │ 128 │ Destination IP Address │
+ ├───────┼─────┼─────────────────────────────────────────────────────────────────────────────────────┤
+ │ 20 │ 160 │ │
+ ├───────┼─────┤ │
+ │ ... │ ... │ Options │
+ ├───────┼─────┤ │
+ │ 56 │ 448 │ │
+ └───────┴─────┴─────────────────────────────────────────────────────────────────────────────────────┘
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c
new file mode 100644
index 0000000..f402836
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-text-art-unicode-color.c
@@ -0,0 +1,59 @@
+/* { dg-additional-options "-fdiagnostics-text-art-charset=unicode -fdiagnostics-color=always" } */
+
+int non_empty;
+
+
+/* { dg-begin-multiline-output "" }
+
+ A
+ B
+ C
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ♜ ♞ ♝ ♛ ♚ ♝ ♞ ♜ 
+ ♟ ♟ ♟ ♟ ♟ ♟ ♟ ♟ 
+         
+         
+         
+         
+ ♙ ♙ ♙ ♙ ♙ ♙ ♙ ♙ 
+ ♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖ 
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌──┐
+ │🙂│
+ └──┘
+
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+
+ ┌───────┬─────┬───────────────┬─────────────────────┬───────────────────────┬───────────────────────┐
+ │Offsets│Octet│ 0 │ 1 │ 2 │ 3 │
+ ├───────┼─────┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬──┬──┬──┬──┬──┬──┼──┬──┬──┬──┬──┬──┬──┬──┼──┬──┬──┬──┬──┬──┬──┬──┤
+ │ Octet │ Bit │0│1│2│3│4│5│6│7│8│9│10│11│12│13│14│15│16│17│18│19│20│21│22│23│24│25│26│27│28│29│30│31│
+ ├───────┼─────┼─┴─┴─┴─┼─┴─┴─┴─┼─┴─┴──┴──┴──┴──┼──┴──┼──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┤
+ │ 0 │ 0 │Version│ IHL │ DSCP │ ECN │ Total Length │
+ ├───────┼─────┼───────┴───────┴───────────────┴─────┼────────┬──────────────────────────────────────┤
+ │ 4 │ 32 │ Identification │ Flags │ Fragment Offset │
+ ├───────┼─────┼───────────────┬─────────────────────┼────────┴──────────────────────────────────────┤
+ │ 8 │ 64 │ Time To Live │ Protocol │ Header Checksum │
+ ├───────┼─────┼───────────────┴─────────────────────┴───────────────────────────────────────────────┤
+ │ 12 │ 96 │ Source IP Address │
+ ├───────┼─────┼─────────────────────────────────────────────────────────────────────────────────────┤
+ │ 16 │ 128 │ Destination IP Address │
+ ├───────┼─────┼─────────────────────────────────────────────────────────────────────────────────────┤
+ │ 20 │ 160 │ │
+ ├───────┼─────┤ │
+ │ ... │ ... │ Options │
+ ├───────┼─────┤ │
+ │ 56 │ 448 │ │
+ └───────┴─────┴─────────────────────────────────────────────────────────────────────────────────────┘
+
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c
new file mode 100644
index 0000000..58b219b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_text_art.c
@@ -0,0 +1,258 @@
+/* { dg-options "-O" } */
+
+/* This plugin exercises the text_art code. */
+
+#define INCLUDE_VECTOR
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "diagnostic-diagram.h"
+#include "text-art/canvas.h"
+#include "text-art/table.h"
+
+int plugin_is_GPL_compatible;
+
+using namespace text_art;
+
+/* Canvas tests. */
+
+static void
+emit_canvas (const canvas &c, const char *alt_text)
+{
+ diagnostic_diagram diagram (c, alt_text);
+ diagnostic_emit_diagram (global_dc, diagram);
+}
+
+static void
+test_abc ()
+{
+ style_manager sm;
+ canvas c (canvas::size_t (3, 3), sm);
+ c.paint (canvas::coord_t (0, 0), styled_unichar ('A'));
+ c.paint (canvas::coord_t (1, 1), styled_unichar ('B'));
+ c.paint (canvas::coord_t (2, 2), styled_unichar ('C'));
+ emit_canvas (c, "test_abc");
+}
+
+/* Test of procedural art using 24-bit color: chess starting position. */
+
+static void
+test_chessboard ()
+{
+ /* With the exception of NONE, these are in order of the chess symbols
+ in the Unicode Miscellaneous Symbols block. */
+ enum class piece { KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN, NONE };
+ enum class color { BLACK, WHITE, NONE };
+
+ style_manager sm;
+
+ /* We assume double-column chars for the pieces, so allow two canvas
+ columns per square. */
+ canvas canvas (canvas::size_t (16, 8), sm);
+
+ for (int x = 0; x < 8; x++)
+ for (int y = 0; y < 8; y++)
+ {
+ enum piece piece_kind;
+ enum color piece_color;
+ switch (y)
+ {
+ case 0:
+ case 7:
+ switch (x)
+ {
+ default:
+ gcc_unreachable ();
+ case 0:
+ piece_kind = piece::ROOK;
+ break;
+ case 1:
+ piece_kind = piece::KNIGHT;
+ break;
+ case 2:
+ piece_kind = piece::BISHOP;
+ break;
+ case 3:
+ piece_kind = piece::QUEEN;
+ break;
+ case 4:
+ piece_kind = piece::KING;
+ break;
+ case 5:
+ piece_kind = piece::BISHOP;
+ break;
+ case 6:
+ piece_kind = piece::KNIGHT;
+ break;
+ case 7:
+ piece_kind = piece::ROOK;
+ break;
+ }
+ piece_color = (y == 0) ? color::BLACK : color::WHITE;
+ break;
+ case 1:
+ case 6:
+ piece_kind = piece::PAWN;
+ piece_color = (y == 1) ? color::BLACK : color::WHITE;
+ break;
+ default:
+ piece_kind = piece::NONE;
+ piece_color = color::NONE;
+ break;
+ }
+
+ style s;
+ const bool white_square = (x + y) % 2 == 0;
+ if (white_square)
+ s.m_bg_color = style::color (0xf0, 0xd9, 0xb5);
+ else
+ s.m_bg_color = style::color (0xb5, 0x88, 0x63);
+ switch (piece_color)
+ {
+ default:
+ gcc_unreachable ();
+ case color::WHITE:
+ s.m_fg_color = style::color (0xff, 0xff, 0xff);
+ break;
+ case color::BLACK:
+ s.m_fg_color = style::color (0x00, 0x00, 0x00);
+ break;
+ case color::NONE:
+ break;
+ }
+ style::id_t style_id = sm.get_or_create_id (s);
+
+ cppchar_t ch;
+ if (piece_kind == piece::NONE)
+ ch = ' ';
+ else
+ {
+ const cppchar_t WHITE_KING = 0x2654;
+ const cppchar_t BLACK_KING = 0x265A;
+ cppchar_t base ((piece_color == color::WHITE)
+ ? WHITE_KING : BLACK_KING);
+ ch = base + ((int)piece_kind - (int)piece::KING);
+ }
+ canvas.paint (canvas::coord_t (x * 2, y),
+ canvas::cell_t (ch, false, style_id));
+ canvas.paint (canvas::coord_t (x * 2 + 1, y),
+ canvas::cell_t (' ', false, style_id));
+ }
+ emit_canvas (canvas, "test_chessboard");
+}
+
+/* Table tests. */
+
+static void
+emit_table (const table &table, const style_manager &sm, const char *alt_text)
+{
+ const text_art::theme *theme = global_dc->m_diagrams.m_theme;
+ if (!theme)
+ return;
+ canvas c (table.to_canvas (*theme, sm));
+ emit_canvas (c, alt_text);
+}
+
+static void
+test_double_width_chars ()
+{
+ style_manager sm;
+ table table (table::size_t (1, 1));
+ table.set_cell (table::coord_t (0,0),
+ styled_string ((cppchar_t)0x1f642));
+
+ emit_table (table, sm, "test_double_width_chars");
+}
+
+static void
+test_ipv4_header ()
+{
+ style_manager sm;
+ table table (table::size_t (34, 10));
+ table.set_cell (table::coord_t (0, 0), styled_string (sm, "Offsets"));
+ table.set_cell (table::coord_t (1, 0), styled_string (sm, "Octet"));
+ table.set_cell (table::coord_t (0, 1), styled_string (sm, "Octet"));
+ for (int octet = 0; octet < 4; octet++)
+ table.set_cell_span (table::rect_t (table::coord_t (2 + (octet * 8), 0),
+ table::size_t (8, 1)),
+ styled_string::from_fmt (sm, nullptr, "%i", octet));
+ table.set_cell (table::coord_t (1, 1), styled_string (sm, "Bit"));
+ for (int bit = 0; bit < 32; bit++)
+ table.set_cell (table::coord_t (bit + 2, 1),
+ styled_string::from_fmt (sm, nullptr, "%i", bit));
+ for (int word = 0; word < 6; word++)
+ {
+ table.set_cell (table::coord_t (0, word + 2),
+ styled_string::from_fmt (sm, nullptr, "%i", word * 4));
+ table.set_cell (table::coord_t (1, word + 2),
+ styled_string::from_fmt (sm, nullptr, "%i", word * 32));
+ }
+
+ table.set_cell (table::coord_t (0, 8), styled_string (sm, "..."));
+ table.set_cell (table::coord_t (1, 8), styled_string (sm, "..."));
+ table.set_cell (table::coord_t (0, 9), styled_string (sm, "56"));
+ table.set_cell (table::coord_t (1, 9), styled_string (sm, "448"));
+
+#define SET_BITS(FIRST, LAST, NAME) \
+ do { \
+ const int first = (FIRST); \
+ const int last = (LAST); \
+ const char *name = (NAME); \
+ const int row = first / 32; \
+ gcc_assert (last / 32 == row); \
+ table::rect_t rect (table::coord_t ((first % 32) + 2, row + 2), \
+ table::size_t (last + 1 - first , 1)); \
+ table.set_cell_span (rect, styled_string (sm, name)); \
+ } while (0)
+
+ SET_BITS (0, 3, "Version");
+ SET_BITS (4, 7, "IHL");
+ SET_BITS (8, 13, "DSCP");
+ SET_BITS (14, 15, "ECN");
+ SET_BITS (16, 31, "Total Length");
+
+ SET_BITS (32 + 0, 32 + 15, "Identification");
+ SET_BITS (32 + 16, 32 + 18, "Flags");
+ SET_BITS (32 + 19, 32 + 31, "Fragment Offset");
+
+ SET_BITS (64 + 0, 64 + 7, "Time To Live");
+ SET_BITS (64 + 8, 64 + 15, "Protocol");
+ SET_BITS (64 + 16, 64 + 31, "Header Checksum");
+
+ SET_BITS (96 + 0, 96 + 31, "Source IP Address");
+ SET_BITS (128 + 0, 128 + 31, "Destination IP Address");
+
+ table.set_cell_span(table::rect_t (table::coord_t (2, 7),
+ table::size_t (32, 3)),
+ styled_string (sm, "Options"));
+
+ emit_table (table, sm, "test_ipv4_header");
+}
+
+static void
+show_diagrams ()
+{
+ test_abc ();
+ test_chessboard ();
+ test_double_width_chars ();
+ test_ipv4_header ();
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ show_diagrams ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 4d6304c..60723a2 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -114,6 +114,12 @@ set plugin_test_list [list \
diagnostic-path-format-inline-events-1.c \
diagnostic-path-format-inline-events-2.c \
diagnostic-path-format-inline-events-3.c } \
+ { diagnostic_plugin_test_text_art.c \
+ diagnostic-test-text-art-none.c \
+ diagnostic-test-text-art-ascii-bw.c \
+ diagnostic-test-text-art-ascii-color.c \
+ diagnostic-test-text-art-unicode-bw.c \
+ diagnostic-test-text-art-unicode-color.c } \
{ location_overflow_plugin.c \
location-overflow-test-1.c \
location-overflow-test-2.c \
diff --git a/gcc/testsuite/gcc.dg/torture/pr110332-1.c b/gcc/testsuite/gcc.dg/torture/pr110332-1.c
new file mode 100644
index 0000000..438993e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr110332-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+struct s { int lie; };
+struct s si7, si8;
+unsigned u9, u6;
+_Bool b3, b4;
+unsigned transferValues(struct s *End) {
+ unsigned RegIdx;
+ unsigned *t = b4 ? &u6 : &u9;
+ RegIdx = *t;
+ *End = *(b3 ? &si7 : &si8);
+ return RegIdx;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr110332-2.c b/gcc/testsuite/gcc.dg/torture/pr110332-2.c
new file mode 100644
index 0000000..18b656f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr110332-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+_Bool a;
+struct s { int t; } c, d;
+unsigned e, f;
+unsigned transferValues(struct s *End) {
+ unsigned RegIdx = *(a ? &e : &f);
+ *End = *(a ? &c : &d);
+ return RegIdx;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr110381.c b/gcc/testsuite/gcc.dg/vect/pr110381.c
new file mode 100644
index 0000000..2313dbf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr110381.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+
+struct FOO {
+ double a;
+ double b;
+ double c;
+};
+
+double __attribute__((noipa))
+sum_8_foos(const struct FOO* foos)
+{
+ double sum = 0;
+
+ for (int i = 0; i < 8; ++i)
+ {
+ struct FOO foo = foos[i];
+
+ /* Need to use an in-order reduction here, preserving
+ the load permutation. */
+ sum += foo.a;
+ sum += foo.c;
+ sum += foo.b;
+ }
+
+ return sum;
+}
+
+int main()
+{
+ struct FOO foos[8];
+
+ __builtin_memset (foos, 0, sizeof (foos));
+ foos[0].a = __DBL_MAX__;
+ foos[0].b = 5;
+ foos[0].c = -__DBL_MAX__;
+
+ if (sum_8_foos (foos) != 5)
+ __builtin_abort ();
+ return 0;
+}