public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code
@ 2021-01-19 20:18 foss at grueninger dot de
  2021-01-19 20:55 ` [Bug c++/98753] " msebor at gcc dot gnu.org
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: foss at grueninger dot de @ 2021-01-19 20:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

            Bug ID: 98753
           Summary: -Wfree-nonheap-object on Bison generated code
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: foss at grueninger dot de
  Target Milestone: ---
             Build: 11.0.0 20210114 (experimental) [revision
                    08a4adcf2b6ded2fea97195c715757df61a23395] (SUSE Linux)

Created attachment 50005
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50005&action=edit
C++ file generated by Bison

While compiling CMake with GCC 11.0, I spot some -Wfree-nonheap-object
warnings. These came from files generated by Bison. I regenerated the C++ files
with the latest GNU Bison release and the problem persisted. So I asked on the
Bison user list and one of the developers claims, that Bison is right.

I don't know whether it is a false positive or whether Bison has a bug.

1.
Attached is the C++ file generated by Bison (cmCommandArgumentParser.cxx).

2.
The warning I get from G++:

[ 54%] Building CXX object
Source/CMakeFiles/CMakeLib.dir/LexerParser/cmCommandArgumentParser.cxx.o
cmCommandArgumentParser.cxx: In function ‘int
cmCommandArgument_yyparse(yyscan_t)’:
cmCommandArgumentParser.cxx:1838:18: warning: ‘void free(void*)’ called on
unallocated object ‘yyssa’ [-Wfree-nonheap-object]
cmCommandArgumentParser.cxx:1203:16: note: declared here

3.
The explanation / reduced code from one of the Bison developers, why the code
is correct:

> GCC 11 is wrong here.  The full story (taken from your file) is:
>
>> // Create.
>>     yy_state_t yyssa[YYINITDEPTH];
>>     yy_state_t *yyss = yyssa;
>> [...]
>> // Grow.
>>       yystacksize *= 2;
>>      {
>>         yy_state_t *yyss1 = yyss;
>>         union yyalloc *yyptr =
>>           YY_CAST (union yyalloc *,
>>                    YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES 
>> (yystacksize))));
>>         if (! yyptr)
>>           goto yyexhaustedlab;
>>         YYSTACK_RELOCATE (yyss_alloc, yyss);
>>         if (yyss1 != yyssa)
>>           YYSTACK_FREE (yyss1);
>>       }
>> [...]
>> // Clean up
>>   if (yyss != yyssa)
>>     YYSTACK_FREE (yyss);
>
> Or, in words, we use a stack-allocated stack until it's too small and
> then we use a heap-allocated stack, and in that case, and that case
> only, we free it at the end.  Said another way: we never ever call
> free(yyssa).
> 
> So GCC's warning is a false positive.

Source: https://lists.gnu.org/archive/html/help-bison/2021-01/msg00021.html

4.
My GCC version is:

> gcc-11 -v
Using built-in specs.
COLLECT_GCC=gcc-11
COLLECT_LTO_WRAPPER=/usr/lib64/gcc/x86_64-suse-linux/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info
--mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64
--enable-languages=c,c++,objc,fortran,obj-c++,ada,go,d
--enable-offload-targets=nvptx-none,amdgcn-amdhsa, --without-cuda-driver
--enable-checking=release --disable-werror
--with-gxx-include-dir=/usr/include/c++/11 --enable-ssp --disable-libssp
--disable-libvtv --enable-cet=auto --disable-libcc1 --disable-plugin
--with-bugurl=https://bugs.opensuse.org/ --with-pkgversion='SUSE Linux'
--with-slibdir=/lib64 --with-system-zlib --enable-libstdcxx-allocator=new
--disable-libstdcxx-pch --enable-libphobos
--enable-version-specific-runtime-libs --with-gcc-major-version-only
--enable-linker-build-id --enable-linux-futex --enable-gnu-indirect-function
--program-suffix=-11 --without-system-libunwind --enable-multilib
--with-arch-32=x86-64 --with-tune=generic --build=x86_64-suse-linux
--host=x86_64-suse-linux
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.0.0 20210114 (experimental) [revision
08a4adcf2b6ded2fea97195c715757df61a23395] (SUSE Linux)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
@ 2021-01-19 20:55 ` msebor at gcc dot gnu.org
  2021-01-20  5:22 ` akim.demaille at gmail dot com
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-01-19 20:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |WAITING
   Last reconfirmed|                            |2021-01-19
     Ever confirmed|0                           |1
                 CC|                            |msebor at gcc dot gnu.org

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The attached file depends on a number of headers.  To reproduce a problem we
need a standalone test case that can be compiled on its own.  One way to do
that is to use the -E option to GCC to obtain the translation unit and
attaching that.

That said, based on the description I suspect the warning is a false positive
with the same root cause as pr54202.  Until a better solution is available in
GCC the workaround is to suppress the warning, either by #pragma GCC
diagnostic, or by using -Wno-free-nonheap-object on the command line.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
  2021-01-19 20:55 ` [Bug c++/98753] " msebor at gcc dot gnu.org
@ 2021-01-20  5:22 ` akim.demaille at gmail dot com
  2021-01-20  7:31 ` rguenth at gcc dot gnu.org
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: akim.demaille at gmail dot com @ 2021-01-20  5:22 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

Akim Demaille <akim.demaille at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |akim.demaille at gmail dot com

--- Comment #2 from Akim Demaille <akim.demaille at gmail dot com> ---
Hi,

I can't tell if it's the same bug of not, but there have never complaints about
this piece of code before GCC11, so something has most likely changed recently.
 Note also that the 'free' is under an 'if' that clearly makes the diagnostic
wrong (I mean, there's no need to solve the halting problem here, all the
information is statically available).

Besides, I would like to stress something that was said in the other PR
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54202#c6):

> If you can't fix GCC so that it can prove that the free is on a non-heap object, then please change the warning to indicate that GCC may be wrong. For example:
> 
> warning: free() may be called with non-heap object 'name'

Thiago Macieira is right: the warning claims "there is an error", but it only
*suspects* that there is one.  The wording is misleading and should be fixed.

Cheers!

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
  2021-01-19 20:55 ` [Bug c++/98753] " msebor at gcc dot gnu.org
  2021-01-20  5:22 ` akim.demaille at gmail dot com
@ 2021-01-20  7:31 ` rguenth at gcc dot gnu.org
  2021-01-20  7:40 ` foss at grueninger dot de
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: rguenth at gcc dot gnu.org @ 2021-01-20  7:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
The issue is that we isolate a path that is impossible to take but on that
path we have p = &foo; free (p); and thus a "proved" mistake.  But in
reality it is guarded by an effective if (false) condition.  So it's not as
simple as you think.  (we also emit diagnostics on function bodies we do not
know are actually never called)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (2 preceding siblings ...)
  2021-01-20  7:31 ` rguenth at gcc dot gnu.org
@ 2021-01-20  7:40 ` foss at grueninger dot de
  2021-01-20 16:48 ` msebor at gcc dot gnu.org
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: foss at grueninger dot de @ 2021-01-20  7:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #4 from Christoph <foss at grueninger dot de> ---
Created attachment 50010
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50010&action=edit
C++ file generated by Bison run with -E

Including all dependencies, created by GCC 11 with added -E

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (3 preceding siblings ...)
  2021-01-20  7:40 ` foss at grueninger dot de
@ 2021-01-20 16:48 ` msebor at gcc dot gnu.org
  2021-01-20 17:00 ` foss at grueninger dot de
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-01-20 16:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #5 from Martin Sebor <msebor at gcc dot gnu.org> ---
I can't reproduce the warning with the default options.  There are just two
calls to free() in the dump.  In each instance its argument resolves to the
yymsg pointer and not to the yyssa array as in the warning message in comment
#0.  We would also need to see the command line options you use to compile the
file (please review https://gcc.gnu.org/bugs/#need for the full details we ask
for).

In GCC 11, -Wfree-nonheap-object was enhanced to validate every argument to
every deallocation function.  Prior to GCC 11 it only considered a negligible
subset of arguments (basically just straight addresses of variables).  The
warning was prone to false positives then (as is evident from pr54202), and the
enhancement hasn't changed that.

Different optimization options produce different intermediate representation. 
Some result in constants substituted for what would otherwise be variables. 
When a constant is substituted into an expression that it's not valid for it
might trigger a warning because in the IL it's indistinguishable from a bug in
the original source code.  There's nothing a warning designed to detect such
invalid expressions can do about it.  Changing this message alone to say
"free() may be called with non-heap object" wouldn't be appropriate without
also changing all the other messages that are subject to the same problem (all
flow-sensitive warnings are).

At least two solutions are theoretically possible: a) make the warning
"smarter" than the optimization it depends on that does the substitution, and
have it figure out that the invalid code was synthesized by it, doesn't occur
in the source code, and cannot be reached in the program given the
preconditions, or b) make the optimizations "smarter" either by not
substituting constants into contexts where they're invalid, or by figuring out
that these invalid expressions cannot be reached based on their preconditions. 
The two sets of preconditions need not be the same.  Both approaches are worth
exploring but both are hard and neither will ever be perfect.  Which is partly
why GCC documents that "Warnings are diagnostic messages that report
constructions that are not inherently erroneous but that are risky or suggest
there may have been an error."  If the warning gets it wrong #pragma GCC
diagnostic can be used to avoid the false positive.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug c++/98753] -Wfree-nonheap-object on Bison generated code
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (4 preceding siblings ...)
  2021-01-20 16:48 ` msebor at gcc dot gnu.org
@ 2021-01-20 17:00 ` foss at grueninger dot de
  2021-01-20 17:34 ` [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0 msebor at gcc dot gnu.org
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: foss at grueninger dot de @ 2021-01-20 17:00 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #6 from Christoph <foss at grueninger dot de> ---
Sorry for not providing the command line argument and the new output.

> gcc-11 -std=c++17 cmCommandArgumentParser_complete.cxx 
cmCommandArgumentParser.cxx: In function ‘int
cmCommandArgument_yyparse(yyscan_t)’:
cmCommandArgumentParser.cxx:1838:10: warning: ‘void free(void*)’ called on
unallocated object ‘yyssa’ [-Wfree-nonheap-object]
cmCommandArgumentParser.cxx:1203:16: note: declared here
/usr/lib64/gcc/x86_64-suse-linux/11/../../../../x86_64-suse-linux/bin/ld:
/usr/lib64/gcc/x86_64-suse-linux/11/../../../../lib64/crt1.o: in function
`_start':
/home/abuild/rpmbuild/BUILD/glibc-2.26/csu/../sysdeps/x86_64/start.S:110:
undefined reference to `main'
...

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (5 preceding siblings ...)
  2021-01-20 17:00 ` foss at grueninger dot de
@ 2021-01-20 17:34 ` msebor at gcc dot gnu.org
  2021-01-20 17:34 ` akim.demaille at gmail dot com
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-01-20 17:34 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|-Wfree-nonheap-object on    |-Wfree-nonheap-object on
                   |Bison generated code        |unreachable code with -O0
      Known to fail|                            |11.0
             Status|WAITING                     |NEW
          Component|c++                         |middle-end

--- Comment #7 from Martin Sebor <msebor at gcc dot gnu.org> ---
I can reproduce the warning with no optimization, thanks.  At -O0, there are
three calls to free in the IL when the warning runs.  The second one that
triggers it

  # .MEM_218 = VDEF <.MEM_216>
  free (yymsg.17_83);

is eliminated by copy propagation at -O1.  It's not eliminated at -O0 because
the optimization isn't done then.  So the ultimate root cause of the problem is
the same as in pr54202, except at -O0 (the test case there depends on
inlining).

It would be possible to disable the warning at -O0 to avoid this false positive
at the expense of some false negatives.  I'm not sure that would be a good
solution based on a single report.  If more bugs like this are reported we
might reconsider.  Let me keep this bug open until then.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (6 preceding siblings ...)
  2021-01-20 17:34 ` [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0 msebor at gcc dot gnu.org
@ 2021-01-20 17:34 ` akim.demaille at gmail dot com
  2021-01-20 17:40 ` akim.demaille at gmail dot com
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: akim.demaille at gmail dot com @ 2021-01-20 17:34 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #8 from Akim Demaille <akim.demaille at gmail dot com> ---
Hi Richard,

(In reply to Richard Biener from comment #3)
> The issue is that we isolate a path that is impossible to take but on that
> path we have p = &foo; free (p); and thus a "proved" mistake.  But in
> reality it is guarded by an effective if (false) condition.  So it's not as
> simple as you think.

Point taken, thanks (though I'm not sure I understand why it would explore
branches below an 'if (false)', but I definitely don't know the details).

> (we also emit diagnostics on function bodies we do not
> know are actually never called)

I will not dispute that this is a hard job (I was just pointing that it should
not impossible in that precise case).  But it just emphasizes again that the
*wording* is wrong.

> warning: ‘void free(void*)’ called on unallocated object ‘yyssa’

This is plain false.  Free is provably *never* called with yyssa.  The wording
should stop being so affirmative, so that the users don't get the wrong
impression.

Cheers!

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (7 preceding siblings ...)
  2021-01-20 17:34 ` akim.demaille at gmail dot com
@ 2021-01-20 17:40 ` akim.demaille at gmail dot com
  2021-01-26 19:37 ` slyfox at gcc dot gnu.org
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: akim.demaille at gmail dot com @ 2021-01-20 17:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #9 from Akim Demaille <akim.demaille at gmail dot com> ---
Hi Martin,

Thanks for the detailed explanation.

(In reply to Martin Sebor from comment #5)
> Changing this message alone to say "free() may be called with non-heap
> object" wouldn't be appropriate without also changing all the other messages
> that are subject to the same problem (all flow-sensitive warnings are).

And I definitely believe this should be done.  All the messages
that claim "you _have_ this problem" should be reworded to
"you _may have_ this problem"–unless of course that the problem
can be proven to exist.

But I agree this is beyond the scope of this issue.

Cheers

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (8 preceding siblings ...)
  2021-01-20 17:40 ` akim.demaille at gmail dot com
@ 2021-01-26 19:37 ` slyfox at gcc dot gnu.org
  2021-01-29 11:29 ` boris at kolpackov dot net
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: slyfox at gcc dot gnu.org @ 2021-01-26 19:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

Sergei Trofimovich <slyfox at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |eike@sf-mail.de,
                   |                            |slyfox at gcc dot gnu.org

--- Comment #10 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
Smaller example built from a similar code to cmake:

  // gcc-11.0.0 -c bug.c
  // `void free(void*)` called on unallocated object `b`
[-Wfree-nonheap-object]
  #include <stdlib.h>

  int main(void) {
    char b[1234];
    char * p = b;
  #if 0 /* enabled in debug only */
    p = (char*)malloc(42);
  #endif
    if (p != b)
        free (p);
  }

$ LANG=C gcc-11.0.0 -c bug.c
bug.c: In function 'main':
bug.c:12:9: warning: 'free' called on unallocated object 'b'
[-Wfree-nonheap-object]
   12 |         free (p);
      |         ^~~~~~~~
bug.c:6:10: note: declared here
    6 |     char b[1234];
      |          ^

gcc version 11.0.0 20210112 (experimental) (commit
cfaaa6a1ca744c1a93fa08a3e7ab2a821383cac1)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (9 preceding siblings ...)
  2021-01-26 19:37 ` slyfox at gcc dot gnu.org
@ 2021-01-29 11:29 ` boris at kolpackov dot net
  2021-01-29 11:30 ` boris at kolpackov dot net
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: boris at kolpackov dot net @ 2021-01-29 11:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

Boris Kolpackov <boris at kolpackov dot net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |boris at kolpackov dot net

--- Comment #11 from Boris Kolpackov <boris at kolpackov dot net> ---
I believe I am encountering a similar false positive so I will attach the test
cases to this bug (but let me know if I should instead attach them to 54202 or
create a new bug). The attached test.cxx is a cleaned-up original code while
test-simplified.cxx is its further simplified version (thanks to Matthew
Krupcale for coming up with both):

g++ -O1 -c test.cxx 

In member function ‘void small_allocator<T, N, B>::deallocate(void*,
std::size_t) [with T = f()::expr; long unsigned int N = 1; B =
small_allocator_buffer<f()::expr, 1>]’,
    inlined from ‘std::vector<_Tp, _Alloc>::pointer std::vector<_Tp,
_Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type,
_ForwardIterator, _ForwardIterator) [with _ForwardIterator = const f()::expr*;
_Tp = f()::expr; _Alloc = small_allocator<f()::expr, 1,
small_allocator_buffer<f()::expr, 1> >]’ at
/home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/11.0.0/bits/alloc_traits.h:341:23,
    inlined from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp,
_Alloc>::size_type) [with _Tp = f()::expr; _Alloc = small_allocator<f()::expr,
1, small_allocator_buffer<f()::expr, 1> >]’ at
/home/boris/work/build2/tests/modules/gcc2/gcc-install/include/c++/11.0.0/bits/vector.tcc:85:36,
    inlined from ‘void small_vector<T, N>::reserve(std::size_t) [with T =
f()::expr; long unsigned int N = 1]’ at test.cxx:234:26,
    inlined from ‘small_vector<T, N>::small_vector() [with T = f()::expr; long
unsigned int N = 1]’ at test.cxx:163:15,
    inlined from ‘void f()’ at test.cxx:1472:27:
test.cxx:121:27: warning: ‘void operator delete(void*)’ called on unallocated
object ‘exprs’ [-Wfree-nonheap-object]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (10 preceding siblings ...)
  2021-01-29 11:29 ` boris at kolpackov dot net
@ 2021-01-29 11:30 ` boris at kolpackov dot net
  2021-01-29 11:30 ` boris at kolpackov dot net
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: boris at kolpackov dot net @ 2021-01-29 11:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #12 from Boris Kolpackov <boris at kolpackov dot net> ---
Created attachment 50080
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50080&action=edit
Reproducer test.cxx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (11 preceding siblings ...)
  2021-01-29 11:30 ` boris at kolpackov dot net
@ 2021-01-29 11:30 ` boris at kolpackov dot net
  2021-01-29 11:36 ` boris at kolpackov dot net
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: boris at kolpackov dot net @ 2021-01-29 11:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #13 from Boris Kolpackov <boris at kolpackov dot net> ---
Created attachment 50081
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50081&action=edit
Reproducer test-simplified.cxx

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (12 preceding siblings ...)
  2021-01-29 11:30 ` boris at kolpackov dot net
@ 2021-01-29 11:36 ` boris at kolpackov dot net
  2021-01-29 16:48 ` msebor at gcc dot gnu.org
  2024-01-02 16:08 ` stefan at bytereef dot org
  15 siblings, 0 replies; 17+ messages in thread
From: boris at kolpackov dot net @ 2021-01-29 11:36 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #14 from Boris Kolpackov <boris at kolpackov dot net> ---
If this cannot be fixed for 11 (and judging by the age of 54202 I feel it's not
likely), perhaps it makes sense not to enable this warning by default? Now that
C++ operator delete() is covered by this check (see bug 57111), it's reasonable
to expect more false positives like these.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (13 preceding siblings ...)
  2021-01-29 11:36 ` boris at kolpackov dot net
@ 2021-01-29 16:48 ` msebor at gcc dot gnu.org
  2024-01-02 16:08 ` stefan at bytereef dot org
  15 siblings, 0 replies; 17+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-01-29 16:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #15 from Martin Sebor <msebor at gcc dot gnu.org> ---
The problem in attachment 50081 is different from the one reported in comment
#0.  The warning there is issued for the call to operator delete in the IL
below as a result of the the test in bb 4 not being folded to false.  The
reason for that is that the call to std::__uninitialized_copy_a.isra() is not
inlined.  Forcing it to expand inline (e.g., by bumping up the -finline-limit=
value) ends up with the desired result.   The inability to propagate constant
values across out-of-line function calls is a general problem, not something
specific to this warning (or any others), and as far as I know doing something
about it isn't on anyone's radar.

What the IL does suggest though is that functions like __uninitialized_copy_a()
might benefit from an annotation indicating that they have no effects unless
the range delineated by their arguments is nonempty.  With that, the call below
could be eliminated altogether even without inlining.  I'm not sure if it would
be realistic to expect the IPA optimizer to do this without an annotation.

GCC doesn't have such an annotation yet so the only way to avoid the warning
here is by changing the code or compiler options.  Using #pragma GCC diagnostic
to suppress the warning should work.  An alternative might be to explore
providing an inline specialization of the std::uninitialized_copy template for
the small_vector::iterator (which would mean defining it as a user-defined
type) that returns when the range is empty.  I didn't take the time to try
that.

Yet another possibility is to change libstdc++ to either declare
std::__uninitialized_copy_a() inline, or change it to an inline wrapper around
an std::__uninitialized_copy_a_impl() that returns immediately when the range
is empty or calls the _impl() otherwise.  Both seem to work.

  <bb 2> [local count: 1073741824]:
  sv_sv_ints ={v} {CLOBBER};
  MEM[(struct _Vector_impl *)&sv_sv_ints + 48B].D.19786.buf_ =
&sv_sv_ints.D.20517;
  MEM[(struct _Vector_impl_data *)&sv_sv_ints + 56B] ={v} {CLOBBER};
  MEM[(struct _Vector_impl_data *)&sv_sv_ints + 56B]._M_start = 0B;
  MEM[(struct _Vector_impl_data *)&sv_sv_ints + 56B]._M_finish = 0B;
  MEM[(struct _Vector_impl_data *)&sv_sv_ints + 56B]._M_end_of_storage = 0B;
  MEM[(struct buffer_type *)&sv_sv_ints].free_ = 0;
  std::__uninitialized_copy_a.isra (0B, 0B, &MEM[(struct buffer_type
*)&sv_sv_ints].data_);

  <bb 3> [local count: 354334802]:
  _29 = MEM[(struct vector *)&sv_sv_ints +
48B].D.20479._M_impl.D.19787._M_finish;
  _30 = MEM[(struct vector *)&sv_sv_ints +
48B].D.20479._M_impl.D.19787._M_start;
  if (_29 != _30)
    goto <bb 9>; [89.00%]
  else
    goto <bb 15>; [11.00%]

  <bb 4> [count: 0]:
<L5>:
  _48 = __builtin_eh_pointer (11);
  __cxa_begin_catch (_48);
  _57 = MEM[(struct small_allocator *)&sv_sv_ints + 48B].buf_;
  if (&sv_sv_ints == _57)
    goto <bb 5>; [0.00%]
  else
    goto <bb 6>; [0.00%]

  <bb 5> [count: 0]:
  MEM[(struct buffer_type *)&sv_sv_ints].free_ = 1;
  goto <bb 7>; [0.00%]

  <bb 6> [count: 0]:
  operator delete (&MEM[(struct buffer_type *)&sv_sv_ints].data_);

  <bb 7> [count: 0]:
  __cxa_rethrow ();

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0
  2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
                   ` (14 preceding siblings ...)
  2021-01-29 16:48 ` msebor at gcc dot gnu.org
@ 2024-01-02 16:08 ` stefan at bytereef dot org
  15 siblings, 0 replies; 17+ messages in thread
From: stefan at bytereef dot org @ 2024-01-02 16:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98753

--- Comment #16 from Stefan Krah <stefan at bytereef dot org> ---
I have encountered the same issue (gcc emits a false positive warning when
free() is called conditionally) in the mpdecimal project when compiled with
-flto.

Worse, mpdecimal itself as well as a large test suite compile without warnings,
so distributions will think everything is fine.

Until a user uses the static libmpdec.a for a trivial program:


wget
https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.tar.gz
tar xvf mpdecimal-2.5.1.tar.gz
cd mpdecimal-2.5.1
./configure CFLAGS="-flto=auto" CXXFLAGS="-flto=auto" LDFLAGS="-flto=auto"
LDXXFLAGS="-flto=auto"
make

# The trivial program:
$ cd libmpdec
$ make bench
gcc -Wall -Wextra -Wno-unknown-pragmas -std=c99 -pedantic -DNDEBUG -O2
-flto=auto -o bench bench.c libmpdec.a -lm
In function ‘mpd_del’,
    inlined from ‘_mpd_qaddsub.constprop’ at mpdecimal.c:3471:5:
mpdecimal.c:470:9: warning: attempt to free a non-heap object ‘big_aligned’
[-Wfree-nonheap-object]
         mpd_free(dec);


Here, the user will get a static library to which he may not even have the
source code readily available and gets a false positive warning for code in
that library.

Like others, I think this warning should be under a category -Wmaybe and be
less decisive in its message.

For the next mpdecimal release the Makefile will filter out -flto for the
static library build.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2024-01-02 16:08 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-19 20:18 [Bug c++/98753] New: -Wfree-nonheap-object on Bison generated code foss at grueninger dot de
2021-01-19 20:55 ` [Bug c++/98753] " msebor at gcc dot gnu.org
2021-01-20  5:22 ` akim.demaille at gmail dot com
2021-01-20  7:31 ` rguenth at gcc dot gnu.org
2021-01-20  7:40 ` foss at grueninger dot de
2021-01-20 16:48 ` msebor at gcc dot gnu.org
2021-01-20 17:00 ` foss at grueninger dot de
2021-01-20 17:34 ` [Bug middle-end/98753] -Wfree-nonheap-object on unreachable code with -O0 msebor at gcc dot gnu.org
2021-01-20 17:34 ` akim.demaille at gmail dot com
2021-01-20 17:40 ` akim.demaille at gmail dot com
2021-01-26 19:37 ` slyfox at gcc dot gnu.org
2021-01-29 11:29 ` boris at kolpackov dot net
2021-01-29 11:30 ` boris at kolpackov dot net
2021-01-29 11:30 ` boris at kolpackov dot net
2021-01-29 11:36 ` boris at kolpackov dot net
2021-01-29 16:48 ` msebor at gcc dot gnu.org
2024-01-02 16:08 ` stefan at bytereef dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).