]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
testsuite: add some libstdc++ -fanalyzer test coverage (PR 125236)
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 20 May 2026 14:24:40 +0000 (10:24 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 20 May 2026 14:26:21 +0000 (10:26 -0400)
This patch adds some test coverage for -fanalyzer's handling of
basic usage of libstdc++ to g++.dg/analyzer/torture, providing
end-to-end testing of the interaction of -fanalyzer and libstdc++ at
various optimization levels.

Currently this is rather minimal (to ensure the tests pass).
I'm working on debugging -fanalyzer issues with other usage patterns
and hope to extend this further as more start working.

gcc/testsuite/ChangeLog:
PR analyzer/125236
* g++.dg/analyzer/torture/README.txt: New.
* g++.dg/analyzer/torture/std-string-ctor-large-literal.C: New
test.
* g++.dg/analyzer/torture/std-string-ctor-small-literal.C: New
test.
* g++.dg/analyzer/torture/std-string-default-ctor.C: New test.
* g++.dg/analyzer/torture/std-unique-ptr-1.C: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/testsuite/g++.dg/analyzer/torture/README.txt [new file with mode: 0644]
gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-large-literal.C [new file with mode: 0644]
gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-small-literal.C [new file with mode: 0644]
gcc/testsuite/g++.dg/analyzer/torture/std-string-default-ctor.C [new file with mode: 0644]
gcc/testsuite/g++.dg/analyzer/torture/std-unique-ptr-1.C [new file with mode: 0644]

diff --git a/gcc/testsuite/g++.dg/analyzer/torture/README.txt b/gcc/testsuite/g++.dg/analyzer/torture/README.txt
new file mode 100644 (file)
index 0000000..88965be
--- /dev/null
@@ -0,0 +1,16 @@
+Various tests in this directory directly use the libstdc++ headers,
+providing an end-to-end test of the interaction of -fanalyzer and
+libstdc++ at various optimization levels.
+
+libstdc++-v3/doc/xml/manual/using.xml
+(https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html)
+notes that by default, glibcxx assertions are enabled at -O0, and
+disabled at -O1 and above.
+
+We will explicitly disable them in some tests via:
+  // { dg-additional-options "-D_GLIBCXX_NO_ASSERTIONS" }
+
+With optimizations, many tests simplify to be within the analyzer's
+normal limits, however at -O0 we may need to turn up
+  --param=analyzer-supernode-explosion-factor=
+for the analyzer to fully explore the code.
diff --git a/gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-large-literal.C b/gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-large-literal.C
new file mode 100644 (file)
index 0000000..8802c53
--- /dev/null
@@ -0,0 +1,23 @@
+/* Verify that the analyzer is silent on correct usage of std::string,
+   using <string>.  */
+
+// { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } }
+
+/* Leaving assertions at default: we seem to need assertions at -O0
+   for the test to pass.  */
+
+// { dg-additional-options "--param=analyzer-supernode-explosion-factor=10" }
+
+#include "../../../gcc.dg/analyzer/analyzer-decls.h"
+#include <string>
+
+void
+test_ctor_large ()
+{
+  std::string s {"0123456789012345678901234567890123456789"
+                "0123456789012345678901234567890123456789"};
+  __analyzer_eval (s.length () == 80); // { dg-warning "TRUE" }
+  __analyzer_eval (s.size () == 80); // { dg-warning "TRUE" }
+  __analyzer_eval (__builtin_strlen (s.c_str ()) == 80); // { dg-warning "TRUE" "ideal" { xfail *-*-* } }
+  // { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-small-literal.C b/gcc/testsuite/g++.dg/analyzer/torture/std-string-ctor-small-literal.C
new file mode 100644 (file)
index 0000000..05a2f58
--- /dev/null
@@ -0,0 +1,22 @@
+/* Verify that the analyzer is silent on correct usage of std::string,
+   using <string>.  */
+
+// { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } }
+
+/* Leaving assertions at default: we seem to need assertions at -O0
+   for the test to pass.  */
+
+// { dg-additional-options "--param=analyzer-supernode-explosion-factor=10" }
+
+#include "../../../gcc.dg/analyzer/analyzer-decls.h"
+#include <string>
+
+void
+test_ctor_small ()
+{
+  std::string s {"abc"};
+  __analyzer_eval (s.length () == 3); // { dg-warning "TRUE" }
+  __analyzer_eval (s.size () == 3); // { dg-warning "TRUE" }
+  __analyzer_eval (__builtin_strlen (s.c_str ()) == 3); // { dg-warning "TRUE" "ideal" { xfail *-*-* } }
+  // { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/torture/std-string-default-ctor.C b/gcc/testsuite/g++.dg/analyzer/torture/std-string-default-ctor.C
new file mode 100644 (file)
index 0000000..dd9ce32
--- /dev/null
@@ -0,0 +1,19 @@
+/* Verify that the analyzer is silent on correct usage of std::string,
+   using <string>.  */
+
+// { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } }
+
+/* Leaving assertions at default: we seem to need assertions at -O0
+   for the test to pass.  */
+
+#include "../../../gcc.dg/analyzer/analyzer-decls.h"
+#include <string>
+
+void
+test_ctor_empty ()
+{
+  std::string s;
+  __analyzer_eval (s.length () == 0); // { dg-warning "TRUE" }
+  __analyzer_eval (s.size () == 0); // { dg-warning "TRUE" }
+  __analyzer_eval (__builtin_strlen (s.c_str()) == 0); // { dg-warning "TRUE" }
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/torture/std-unique-ptr-1.C b/gcc/testsuite/g++.dg/analyzer/torture/std-unique-ptr-1.C
new file mode 100644 (file)
index 0000000..0e37a6b
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
+
+// { dg-additional-options "-D_GLIBCXX_NO_ASSERTIONS" }
+// { dg-additional-options "--param=analyzer-supernode-explosion-factor=10" }
+
+#include "../../../gcc.dg/analyzer/analyzer-decls.h"
+#include <memory>
+
+void
+test_null_deref_1 ()
+{
+  std::unique_ptr<int> p;
+  __analyzer_eval (*p == 42); // { dg-warning "null-dereference" }
+}
+
+void
+test_null_deref_2 ()
+{
+  auto p = std::make_unique<int> (42);
+  __analyzer_eval (*p == 42); // { dg-warning "TRUE" }
+  p = nullptr;
+  __analyzer_eval (*p); // { dg-warning "null-dereference" }
+}
+
+void
+test_use_after_free ()
+{
+  auto p = std::make_unique<int> (42);
+  __analyzer_eval (*p == 42); // { dg-warning "TRUE" }
+  int *ptr = p.get ();
+  p = nullptr;
+  __analyzer_eval (*ptr); // { dg-warning "use after 'delete'" }
+}