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

--- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> ---
Not having to annotate _M_create is also helpful when the call isn't inlined. 
For example, neither of the following functions is diagnosed because in both
cases GCC  emits a call equivalent to:

  std::__cxx11::basic_string<char>::_M_construct.isra (&str, "abc", &MEM <const
char[4]> [(void *)"abc" + 3B]);

and from that there's no way for the warning to determine how the string buffer
was allocated.

#include <string>

void f ()
{
    std::string str ("abc");
    char *p = &str[0];
    __builtin_free (p);
}

void g ()
{
    std::string str ("def");
    char *p = &str[0];
    __builtin_free (p);
}

The IL for both f() and g() ends up looking alike (below) but in both cases the
calls to free() and operator delete() are evidently made with the same pointer.
 (Technically, the use of str._M_dataplus._M_p in the assignment right after
the call to free() will be grounds for issuing -Wuse-after-free once the
warning is implemented.)

void f ()
{
  struct string str;
  char * _7;
  char * _9;
  long unsigned int _11;
  long unsigned int _12;

  <bb 2> [local count: 1073741824]:
  MEM[(struct basic_string *)&str] ={v} {CLOBBER};
  MEM[(struct _Alloc_hider *)&str] ={v} {CLOBBER};
  MEM[(struct _Alloc_hider *)&str]._M_p = &str.D.24447._M_local_buf;
  std::__cxx11::basic_string<char>::_M_construct.isra (&str, "abc", &MEM <const
char[4]> [(void *)"abc" + 3B]);
  _7 = str._M_dataplus._M_p;
  __builtin_free (_7);
  _9 = str._M_dataplus._M_p;
  if (&str.D.24447._M_local_buf != _9)
    goto <bb 3>; [53.47%]
  else
    goto <bb 4>; [46.53%]

  <bb 3> [local count: 574129753]:
  _11 = str.D.24447._M_allocated_capacity;
  _12 = _11 + 1;
  operator delete (_9, _12);

  <bb 4> [local count: 1073741824]:
  str ={v} {CLOBBER};
  str ={v} {CLOBBER};
  return;

}

Reply via email to