]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: add option -fanalyzer-assume-nothrow [PR122623]
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 27 Jan 2026 21:36:29 +0000 (16:36 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 27 Jan 2026 21:36:29 +0000 (16:36 -0500)
As of r16-264-g7a39e0ca0652ff, -fanalyzer assumes that a call to an
external function not marked with attribute "nothrow" could throw an
exception, if -fexceptions is enabled.

PR analyzer/122623 notes that testing -fanalyzer with GCC 16 on Fedora
packages turned up some new leak warnings due to -fexceptions being
passed to all C code (for interoperability with C++), due to C headers
typically not having their entrypoints being marked with "nothrow".
Some of these are false positives.  Others are arguably true positives,
such as the case in the above report, but highly surprising to
end-users, and of dubious value.

I don't have data on the scale of the problem, but I am worried that
the C++ exception support added in GCC 16 could cause a big regression
in analyzer signal:noise when compiling C code with distro build flags.

To provide a workaround for distro mass analysis runs, this patch adds a
new option: -fanalyzer-assume-nothrow, which when enabled assumes that
external functions do not throw exceptions.  This may be something of a
blunt hammer, but may be useful to distros to add to build flags for C.

gcc/analyzer/ChangeLog:
PR analyzer/122623
* analyzer.opt (fanalyzer-assume-nothrow): New.
* analyzer.opt.urls: Regenerate.
* region-model.cc (can_throw_p): Bail out if the user specified
-fanalyzer-assume-nothrow.

gcc/ChangeLog:
PR analyzer/122623
* doc/invoke.texi (-fanalyzer-assume-nothrow): New option.

gcc/testsuite/ChangeLog:
PR analyzer/122623
* gcc.dg/analyzer/fexceptions-1.c: New test.
* gcc.dg/analyzer/fexceptions-2.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/analyzer.opt
gcc/analyzer/analyzer.opt.urls
gcc/analyzer/region-model.cc
gcc/doc/invoke.texi
gcc/testsuite/gcc.dg/analyzer/fexceptions-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/fexceptions-2.c [new file with mode: 0644]

index cceee1015015cc9667a04a399107689e8b35b433..3c5dd0849c60b1a662c324f125111ca597587995 100644 (file)
@@ -278,6 +278,10 @@ Wanalyzer-too-complex
 Common Var(warn_analyzer_too_complex) Init(0) Warning
 Warn if the code is too complicated for the analyzer to fully explore.
 
+fanalyzer-assume-nothrow
+Common Var(flag_analyzer_assume_nothrow) Init(0)
+Assume that no function calls can throw exceptions.
+
 fanalyzer-checker=
 Common Joined RejectNegative Var(flag_analyzer_checker)
 Restrict the analyzer to run just the named checker.
index 0ad321e77f57c281a97d021f57d91c6afb7ab7d3..1a698f9c6d9a39403e818c210a331cd6a0021d00 100644 (file)
@@ -156,6 +156,9 @@ UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-symbol-too-complex)
 Wanalyzer-too-complex
 UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-too-complex)
 
+fanalyzer-assume-nothrow
+UrlSuffix(gcc/Static-Analyzer-Options.html#index-fanalyzer-assume-nothrow)
+
 fanalyzer-checker=
 UrlSuffix(gcc/Static-Analyzer-Options.html#index-fanalyzer-checker)
 
index c6b22706c7b1687df8dc148eda736579a66fc6a3..1efb19b07761bd22da114a924c1f53df074d563d 100644 (file)
@@ -2198,6 +2198,13 @@ can_throw_p (const gcall &call, tree fndecl)
   if (!flag_exceptions)
     return false;
 
+  /* Compatibility flag to allow the user to assume external functions
+     never throw exceptions.  This may be useful when using the analyzer
+     on C code that is compiled with -fexceptions, but for which the headers
+     haven't yet had "nothrow" attributes systematically added.  */
+  if (flag_analyzer_assume_nothrow)
+    return false;
+
   if (gimple_call_nothrow_p (&call))
     return false;
 
index 87c0470c3dbcb760b2a4e0294337fc2fd1dea4b1..8234133131f540ac762bc950b9934f7f1645025f 100644 (file)
@@ -483,6 +483,7 @@ Objective-C and Objective-C++ Dialects}.
 @item Static Analyzer Options
 @gccoptlist{
 -fanalyzer
+-fanalyzer-assume-nothrow
 -fanalyzer-call-summaries
 -fanalyzer-checker=@var{name}
 -fno-analyzer-feasibility
@@ -12501,6 +12502,21 @@ The following options control the analyzer.
 
 @table @gcctabopt
 
+@opindex fanalyzer-assume-nothrow
+@opindex fno-analyzer-assume-nothrow
+@item -fanalyzer-assume-nothrow
+By default, if @option{-fexceptions} is enabled, the analyzer will assume
+that a call to any function without attribute @code{nothrow} could throw
+an exception.  This can help detect execution paths that leak due to
+exceptions bypassing clean-up code, but could lead to false positives when
+using headers where the author has not added the @code{nothrow} attribute.
+
+If @option{-fanalyzer-assume-nothrow} is enabled, then the analyzer will
+assume that external functions do not throw exceptions.  This may be useful
+for reducing ``noise'' from the analyzer when enabling
+@option{-fexceptions} on C code, but could hide true issues if an
+exception could be raised by something the C code calls.
+
 @opindex fanalyzer-call-summaries
 @opindex fno-analyzer-call-summaries
 @item -fanalyzer-call-summaries
diff --git a/gcc/testsuite/gcc.dg/analyzer/fexceptions-1.c b/gcc/testsuite/gcc.dg/analyzer/fexceptions-1.c
new file mode 100644 (file)
index 0000000..052265d
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-additional-options "-fexceptions" } */
+
+extern void do_something ();
+extern void do_something_nothrow () __attribute__ ((nothrow));
+
+void test ()
+{
+  void *p = __builtin_malloc (1024);
+
+  do_something (); /* { dg-warning "leak of 'p'" } */
+  /* { dg-message "if 'do_something' throws an exception\.\.\." "exception event" { target *-*-* } .-1 } */
+
+  __builtin_free (p);
+}
+
+void test_nothrow ()
+{
+  void *p = __builtin_malloc (1024);
+
+  do_something_nothrow (); /* { dg-bogus "leak of 'p'" } */
+
+  __builtin_free (p);
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/fexceptions-2.c b/gcc/testsuite/gcc.dg/analyzer/fexceptions-2.c
new file mode 100644 (file)
index 0000000..78d463c
--- /dev/null
@@ -0,0 +1,26 @@
+/* Verify that -fanalyzer-assume-nothrow suppresses warnings about
+   exceptions being thrown in called function, even those not
+   marked with "nothrow".  */
+
+/* { dg-additional-options "-fexceptions -fanalyzer-assume-nothrow" } */
+
+extern void do_something ();
+extern void do_something_nothrow () __attribute__ ((nothrow));
+
+void test ()
+{
+  void *p = __builtin_malloc (1024);
+
+  do_something (); /* { dg-bogus "leak of 'p'" } */
+
+  __builtin_free (p);
+}
+
+void test_nothrow ()
+{
+  void *p = __builtin_malloc (1024);
+
+  do_something_nothrow (); /* { dg-bogus "leak of 'p'" } */
+
+  __builtin_free (p);
+}