Author Topic: CC no longer working for unique_ptr  (Read 24648 times)

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
CC no longer working for unique_ptr
« on: August 29, 2011, 11:34:27 pm »
Consider the following code in a console app's main.cpp :

Code
#include <iostream>
#include <memory>

class Test
{
public:
void doSomething();
};

int main()
{
std::unique_ptr<int> foo(new int());

foo.

std::unique_ptr<Test> bar(new Test());

bar->

    return 0;
}

1) When the "." after foo has been typed --> no CC suggestions (at least there should be get/release/...).
This used to work.

2) When the "->" after bar has been typed --> no CC suggestions ( there should be doSomething)
This used to work.

Could this be fixed ?

Tested on rev 7439

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC no longer working for unique_ptr
« Reply #1 on: August 30, 2011, 12:52:39 am »
Hm, Are you sure this has ever worked?
As far as I know the -> operator overloading is not parsed by the CC.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: CC no longer working for unique_ptr
« Reply #2 on: August 30, 2011, 01:24:44 am »
Make sure use --std=c++0x option?
Works well here.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: CC no longer working for unique_ptr
« Reply #3 on: August 30, 2011, 07:19:53 am »
Make sure use --std=c++0x option?
Works well here.
Does not work here (latest trunk on debian 64-bit, with some modifications not related to CC) with or without the option.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: CC no longer working for unique_ptr
« Reply #4 on: August 30, 2011, 07:33:27 am »
Make sure use --std=c++0x option?
Works well here.
@loaden
Did you think CC is respect to the compiler command option?
I don't think so.

I will test the latest trunk.

EDIT:
killerbot's test failed with both --std=c++0x or not.

« Last Edit: August 30, 2011, 07:50:46 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
Re: CC no longer working for unique_ptr
« Reply #5 on: August 30, 2011, 07:45:25 am »
Hm, Are you sure this has ever worked?
As far as I know the -> operator overloading is not parsed by the CC.

Yes I am sure. I remember that once I filed a request to support this, and the next day it was implemented by our CC gurus.
But I guess with all the latest modifications to CC, it got broken ?

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: CC no longer working for unique_ptr
« Reply #6 on: August 30, 2011, 07:56:08 am »
Hm, Are you sure this has ever worked?
As far as I know the -> operator overloading is not parsed by the CC.

Yes I am sure. I remember that once I filed a request to support this, and the next day it was implemented by our CC gurus.
But I guess with all the latest modifications to CC, it got broken ?
The operators "->" and "." were handled when doing the suggestion list.
But they were not handled in patch parsing stage.
The major work was done by "blueshake" to give the suggestion on templates. He is not active in this forum about one year (due to heavy work)

Yes, I guess it was broken some days later.
I'm not satisfied with those code. It was too complex and not easy to debug and trace.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: CC no longer working for unique_ptr
« Reply #7 on: August 30, 2011, 08:38:01 am »
Make sure use --std=c++0x option?
Works well here.
Does not work here (latest trunk on debian 64-bit, with some modifications not related to CC) with or without the option.
Remember reparse the project.
I am using Linux Mint 11 64-bit, it's works well.
And now I am test it on Windows 7 32-bit, And it's works too.

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: CC no longer working for unique_ptr
« Reply #8 on: August 30, 2011, 08:50:28 am »
I am only test it with MinGW TDM 4.5.2 and GCC 4.5.2.
I guess it's don't work with GCC 4.6.x, In GCC 4.6.x, there has more changes with namespace.
Maybe the unique_ptr is in global namespace.

So, try:
Code
#include <iostream>
#include <memory>

class Test
{
public:
void doSomething();
};

int main()
{
unique_ptr<int> foo(new int());

// foo.

unique_ptr<Test> bar(new Test());

// bar->

    return 0;
}

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5910
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: CC no longer working for unique_ptr
« Reply #9 on: August 30, 2011, 09:02:29 am »
It's still in std namespace.
It sounds like we should add some extra macro replacement rule, look at this:
D:\code\mingw_gcc4.6.1release_static_win32\lib\gcc\i686-pc-mingw32\4.6.1\include\c++\bits\unique_ptr.h
Code
// unique_ptr implementation -*- C++ -*-

// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file bits/unique_ptr.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly. @headername{memory}
 */

#ifndef _UNIQUE_PTR_H
#define _UNIQUE_PTR_H 1

#include <bits/c++config.h>
#include <debug/debug.h>
#include <type_traits>
#include <utility>
#include <tuple>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @addtogroup pointer_abstractions
   * @{
   */

  /// Primary template, default_delete.
  template<typename _Tp>
    struct default_delete
    {
      constexpr default_delete() = default;

      template<typename _Up, typename = typename
       std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
        default_delete(const default_delete<_Up>&) { }

      void
      operator()(_Tp* __ptr) const
      {
static_assert(sizeof(_Tp)>0,
      "can't delete pointer to incomplete type");
delete __ptr;
      }
    };

  // _GLIBCXX_RESOLVE_LIB_DEFECTS
  // DR 740 - omit specialization for array objects with a compile time length
  /// Specialization, default_delete.
  template<typename _Tp>
    struct default_delete<_Tp[]>
    {
      constexpr default_delete() = default;

      void
      operator()(_Tp* __ptr) const
      {
static_assert(sizeof(_Tp)>0,
      "can't delete pointer to incomplete type");
delete [] __ptr;
      }

      template<typename _Up> void operator()(_Up*) const = delete;
    };

  /// 20.7.12.2 unique_ptr for single objects.
  template <typename _Tp, typename _Dp = default_delete<_Tp> >
    class unique_ptr
    {
      // use SFINAE to determine whether _Del::pointer exists
      class _Pointer
      {
template<typename _Up>
  static typename _Up::pointer __test(typename _Up::pointer*);

template<typename _Up>
  static _Tp* __test(...);

typedef typename remove_reference<_Dp>::type _Del;

      public:
typedef decltype( __test<_Del>(0)) type;
      };

      typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
      __tuple_type                                      _M_t;

    public:
      typedef typename _Pointer::type   pointer;
      typedef _Tp                       element_type;
      typedef _Dp                       deleter_type;

      // Constructors.
      constexpr unique_ptr()
      : _M_t()
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      explicit
      unique_ptr(pointer __p)
      : _M_t(__p, deleter_type())
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      unique_ptr(pointer __p,
  typename std::conditional<std::is_reference<deleter_type>::value,
    deleter_type, const deleter_type&>::type __d)
      : _M_t(__p, __d) { }

      unique_ptr(pointer __p,
  typename std::remove_reference<deleter_type>::type&& __d)
      : _M_t(std::move(__p), std::move(__d))
      { static_assert(!std::is_reference<deleter_type>::value,
      "rvalue deleter bound to reference"); }

      constexpr unique_ptr(nullptr_t)
      : _M_t()
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      // Move constructors.
      unique_ptr(unique_ptr&& __u)
      : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }

      template<typename _Up, typename _Ep, typename = typename
std::enable_if
  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
       pointer>::value
   && !std::is_array<_Up>::value
   && ((std::is_reference<_Dp>::value
&& std::is_same<_Ep, _Dp>::value)
       || (!std::is_reference<_Dp>::value
   && std::is_convertible<_Ep, _Dp>::value))>
     ::type>
unique_ptr(unique_ptr<_Up, _Ep>&& __u)
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{ }

#if _GLIBCXX_USE_DEPRECATED
      template<typename _Up, typename = typename
std::enable_if<std::is_convertible<_Up*, _Tp*>::value
       && std::is_same<_Dp,
       default_delete<_Tp>>::value>::type>
unique_ptr(auto_ptr<_Up>&& __u)
: _M_t(__u.release(), deleter_type()) { }
#endif

      // Destructor.
      ~unique_ptr() { reset(); }

      // Assignment.
      unique_ptr&
      operator=(unique_ptr&& __u)
      {
reset(__u.release());
get_deleter() = std::forward<deleter_type>(__u.get_deleter());
return *this;
      }

      template<typename _Up, typename _Ep, typename = typename
std::enable_if
  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
       pointer>::value
   && !std::is_array<_Up>::value>::type>
unique_ptr&
operator=(unique_ptr<_Up, _Ep>&& __u)
{
  reset(__u.release());
  get_deleter() = std::forward<_Ep>(__u.get_deleter());
  return *this;
}

      unique_ptr&
      operator=(nullptr_t)
      {
reset();
return *this;
      }

      // Observers.
      typename std::add_lvalue_reference<element_type>::type
      operator*() const
      {
_GLIBCXX_DEBUG_ASSERT(get() != pointer());
return *get();
      }

      pointer
      operator->() const
      {
_GLIBCXX_DEBUG_ASSERT(get() != pointer());
return get();
      }

      pointer
      get() const
      { return std::get<0>(_M_t); }

      deleter_type&
      get_deleter()
      { return std::get<1>(_M_t); }

      const deleter_type&
      get_deleter() const
      { return std::get<1>(_M_t); }

      explicit operator bool() const
      { return get() == pointer() ? false : true; }

      // Modifiers.
      pointer
      release()
      {
pointer __p = get();
std::get<0>(_M_t) = pointer();
return __p;
      }

      void
      reset(pointer __p = pointer())
      {
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != pointer())
  get_deleter()(__p);
      }

      void
      swap(unique_ptr& __u)
      {
using std::swap;
swap(_M_t, __u._M_t);
      }

      // Disable copy from lvalue.
      unique_ptr(const unique_ptr&) = delete;
      unique_ptr& operator=(const unique_ptr&) = delete;
  };

  /// 20.7.12.3 unique_ptr for array objects with a runtime length
  // [unique.ptr.runtime]
  // _GLIBCXX_RESOLVE_LIB_DEFECTS
  // DR 740 - omit specialization for array objects with a compile time length
  template<typename _Tp, typename _Dp>
    class unique_ptr<_Tp[], _Dp>
    {
      typedef std::tuple<_Tp*, _Dp>  __tuple_type;
      __tuple_type _M_t;

    public:
      typedef _Tp* pointer;
      typedef _Tp element_type;
      typedef _Dp                       deleter_type;

      // Constructors.
      constexpr unique_ptr()
      : _M_t()
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      explicit
      unique_ptr(pointer __p)
      : _M_t(__p, deleter_type())
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      unique_ptr(pointer __p,
  typename std::conditional<std::is_reference<deleter_type>::value,
      deleter_type, const deleter_type&>::type __d)
      : _M_t(__p, __d) { }

      unique_ptr(pointer __p,
typename std::remove_reference<deleter_type>::type && __d)
      : _M_t(std::move(__p), std::move(__d))
      { static_assert(!std::is_reference<deleter_type>::value,
      "rvalue deleter bound to reference"); }

      constexpr unique_ptr(nullptr_t)
      : _M_t()
      { static_assert(!std::is_pointer<deleter_type>::value,
     "constructed with null function pointer deleter"); }

      // Move constructors.
      unique_ptr(unique_ptr&& __u)
      : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }

      template<typename _Up, typename _Ep>
unique_ptr(unique_ptr<_Up, _Ep>&& __u)
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
{ }

      // Destructor.
      ~unique_ptr() { reset(); }

      // Assignment.
      unique_ptr&
      operator=(unique_ptr&& __u)
      {
reset(__u.release());
get_deleter() = std::forward<deleter_type>(__u.get_deleter());
return *this;
      }

      template<typename _Up, typename _Ep>
unique_ptr&
operator=(unique_ptr<_Up, _Ep>&& __u)
{
  reset(__u.release());
  get_deleter() = std::forward<_Ep>(__u.get_deleter());
  return *this;
}

      unique_ptr&
      operator=(nullptr_t)
      {
reset();
return *this;
      }

      // Observers.
      typename std::add_lvalue_reference<element_type>::type
      operator[](size_t __i) const
      {
_GLIBCXX_DEBUG_ASSERT(get() != pointer());
return get()[__i];
      }

      pointer
      get() const
      { return std::get<0>(_M_t); }

      deleter_type&
      get_deleter()
      { return std::get<1>(_M_t); }

      const deleter_type&
      get_deleter() const
      { return std::get<1>(_M_t); }

      explicit operator bool() const
      { return get() == pointer() ? false : true; }

      // Modifiers.
      pointer
      release()
      {
pointer __p = get();
std::get<0>(_M_t) = pointer();
return __p;
      }

      void
      reset(pointer __p = pointer())
      {
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != nullptr)
  get_deleter()(__p);
      }

      void
      reset(nullptr_t)
      {
pointer __p = get();
std::get<0>(_M_t) = pointer();
if (__p != nullptr)
  get_deleter()(__p);
      }

      // DR 821.
      template<typename _Up>
void reset(_Up) = delete;

      void
      swap(unique_ptr& __u)
      {
using std::swap;
swap(_M_t, __u._M_t);
      }

      // Disable copy from lvalue.
      unique_ptr(const unique_ptr&) = delete;
      unique_ptr& operator=(const unique_ptr&) = delete;

      // Disable construction from convertible pointer types.
      // (N2315 - 20.6.5.3.1)
      template<typename _Up>
unique_ptr(_Up*, typename
   std::conditional<std::is_reference<deleter_type>::value,
   deleter_type, const deleter_type&>::type,
   typename std::enable_if<std::is_convertible<_Up*,
   pointer>::value>::type* = 0) = delete;

      template<typename _Up>
unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
   typename std::enable_if<std::is_convertible<_Up*,
   pointer>::value>::type* = 0) = delete;

      template<typename _Up>
explicit
unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
   pointer>::value>::type* = 0) = delete;
  };

  template<typename _Tp, typename _Dp>
    inline void
    swap(unique_ptr<_Tp, _Dp>& __x,
unique_ptr<_Tp, _Dp>& __y)
    { __x.swap(__y); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator==(const unique_ptr<_Tp, _Dp>& __x,
       const unique_ptr<_Up, _Ep>& __y)
    { return __x.get() == __y.get(); }

  template<typename _Tp, typename _Dp>
    inline bool
    operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    { return __x.get() == nullptr; }

  template<typename _Tp, typename _Dp>
    inline bool
    operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
    { return nullptr == __y.get(); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator!=(const unique_ptr<_Tp, _Dp>& __x,
       const unique_ptr<_Up, _Ep>& __y)
    { return !(__x.get() == __y.get()); }

  template<typename _Tp, typename _Dp>
    inline bool
    operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    { return __x.get() != nullptr; }

  template<typename _Tp, typename _Dp>
    inline bool
    operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
    { return nullptr != __y.get(); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator<(const unique_ptr<_Tp, _Dp>& __x,
      const unique_ptr<_Up, _Ep>& __y)
    { return __x.get() < __y.get(); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator<=(const unique_ptr<_Tp, _Dp>& __x,
       const unique_ptr<_Up, _Ep>& __y)
    { return !(__y.get() < __x.get()); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator>(const unique_ptr<_Tp, _Dp>& __x,
      const unique_ptr<_Up, _Ep>& __y)
    { return __y.get() < __x.get(); }

  template<typename _Tp, typename _Dp,
   typename _Up, typename _Ep>
    inline bool
    operator>=(const unique_ptr<_Tp, _Dp>& __x,
       const unique_ptr<_Up, _Ep>& __y)
    { return !(__x.get() < __y.get()); }

  /// std::hash specialization for unique_ptr.
  template<typename _Tp, typename _Dp>
    struct hash<unique_ptr<_Tp, _Dp>>
    : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
    {
      size_t
      operator()(const unique_ptr<_Tp, _Dp>& __u) const
      {
typedef unique_ptr<_Tp, _Dp> _UP;
return std::hash<typename _UP::pointer>()(__u.get());
      }
    };

  // @} group pointer_abstractions

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif /* _UNIQUE_PTR_H */


Code
_GLIBCXX_VISIBILITY(default)
should be replaced to none.

Unfortunately, I think we do not currently have such replacement rule.

My idea is: we should write such replacement rule like the macro definition. That need some code rewrite.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5490
Re: CC no longer working for unique_ptr
« Reply #10 on: August 30, 2011, 01:05:38 pm »
fyi : I discovered the issue yesterday on linux with gcc 4.6

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: CC no longer working for unique_ptr
« Reply #11 on: August 30, 2011, 02:10:07 pm »
fyi : I discovered the issue yesterday on linux with gcc 4.6
I also tested with gcc 4.6, but can test with 4.5 this evening.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC no longer working for unique_ptr
« Reply #12 on: August 30, 2011, 05:00:55 pm »
Code
Tokenizer::SetReplacementString(_T("_GLIBCXX_VISIBILITY"), _T("+"));
Is this '+' character correct?
What does it do?
Explanation please and maybe a commit with a comment about it:)
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Loaden

  • Lives here!
  • ****
  • Posts: 1014
Re: CC no longer working for unique_ptr
« Reply #13 on: August 30, 2011, 05:04:16 pm »
Code
Tokenizer::SetReplacementString(_T("_GLIBCXX_VISIBILITY"), _T("+"));
Is this '+' character correct?
What does it do?
Explanation please and maybe a commit with a comment about it:)
Sorry for my poor english. I think I can't explain clear.
The "+" is a flag for macro replace.
And the replace result is:
_GLIBCXX_VISIBILITY(...any...thing...) -> none
See test.h for more information.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: CC no longer working for unique_ptr
« Reply #14 on: August 30, 2011, 06:24:32 pm »
Understood  :lol:
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]