Changeset 128203 in webkit


Ignore:
Timestamp:
Sep 11, 2012 10:39:08 AM (12 years ago)
Author:
enne@google.com
Message:

Clang doesn't optimize away undefined OwnPtr copy constructor
https://bugs.webkit.org/show_bug.cgi?id=74625

Reviewed by Anders Carlsson.

Original patch by Anders Carlsson, with a minor edit.

The publicly declared-but-not-defined copy constructor is a compiler
optimization-dependent landmine. Clang often fails to optimize the use
of this function out, leading to internal linkage errors for the missing
definition. gcc doesn't have this problem and optimizes that function
out, leading to code that inconsistently fails to link across platforms.

As a partial fix for this problem, on any compiler that supports C++11
move semantics, replace the bogus copy constructor with the move
constructors. In the future, if all compilers support this, then the
copy constructor can be removed.

This still leaves other compilers that don't support move semantics
like Visual Studio vulnerable to linking inconsistencies.

  • wtf/OwnPtr.h:

(OwnPtr):
(WTF):
(WTF::::OwnPtr):
(WTF::=):

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r128191 r128203  
     12012-09-11  Adrienne Walker  <enne@google.com>
     2
     3        Clang doesn't optimize away undefined OwnPtr copy constructor
     4        https://bugs.webkit.org/show_bug.cgi?id=74625
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Original patch by Anders Carlsson, with a minor edit.
     9
     10        The publicly declared-but-not-defined copy constructor is a compiler
     11        optimization-dependent landmine. Clang often fails to optimize the use
     12        of this function out, leading to internal linkage errors for the missing
     13        definition. gcc doesn't have this problem and optimizes that function
     14        out, leading to code that inconsistently fails to link across platforms.
     15
     16        As a partial fix for this problem, on any compiler that supports C++11
     17        move semantics, replace the bogus copy constructor with the move
     18        constructors.  In the future, if all compilers support this, then the
     19        copy constructor can be removed.
     20
     21        This still leaves other compilers that don't support move semantics
     22        like Visual Studio vulnerable to linking inconsistencies.
     23
     24        * wtf/OwnPtr.h:
     25        (OwnPtr):
     26        (WTF):
     27        (WTF::::OwnPtr):
     28        (WTF::=):
     29
    1302012-09-11  Raphael Kubo da Costa  <rakuco@webkit.org>
    231
  • trunk/Source/WTF/wtf/OwnPtr.h

    r111778 r128203  
    2323
    2424#include <wtf/Assertions.h>
     25#include <wtf/Noncopyable.h>
    2526#include <wtf/NullPtr.h>
    2627#include <wtf/OwnPtrCommon.h>
     
    3738
    3839    template<typename T> class OwnPtr {
     40#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
     41        // If rvalue references are not supported, the copy constructor is
     42        // public so OwnPtr cannot be marked noncopyable. See note below.
     43        WTF_MAKE_NONCOPYABLE(OwnPtr);
     44#endif
    3945    public:
    4046        typedef typename RemovePointer<T>::Type ValueType;
     
    4753        template<typename U> OwnPtr(const PassOwnPtr<U>& o);
    4854
     55#if !COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
    4956        // This copy constructor is used implicitly by gcc when it generates
    5057        // transients for assigning a PassOwnPtr<T> object to a stack-allocated
     
    5259        // should optimize away the constructor when generating code.
    5360        OwnPtr(const OwnPtr<ValueType>&);
     61#endif
    5462
    5563        ~OwnPtr() { deleteOwnedPtr(m_ptr); }
     
    7482        template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
    7583
     84#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
     85        OwnPtr(OwnPtr&&);
     86        template<typename U> OwnPtr(OwnPtr<U>&&);
     87
     88        OwnPtr& operator=(OwnPtr&&);
     89        template<typename U> OwnPtr& operator=(OwnPtr<U>&&);
     90#endif
     91
    7692        void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
    7793
    7894    private:
    79         OwnPtr& operator=(const OwnPtr<T>&);
     95#if !COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
     96        // If rvalue references are supported, noncopyable takes care of this.
     97        OwnPtr& operator=(const OwnPtr&);
     98#endif
    8099
    81100        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
     
    133152    }
    134153
     154#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
     155    template<typename T> inline OwnPtr<T>::OwnPtr(OwnPtr<T>&& o)
     156        : m_ptr(o.leakPtr())
     157    {
     158    }
     159
     160    template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(OwnPtr<U>&& o)
     161        : m_ptr(o.leakPtr())
     162    {
     163    }
     164
     165    template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<T>&& o)
     166    {
     167        PtrType ptr = m_ptr;
     168        m_ptr = o.leakPtr();
     169        ASSERT(!ptr || m_ptr != ptr);
     170        deleteOwnedPtr(ptr);
     171
     172        return *this;
     173    }
     174
     175    template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(OwnPtr<U>&& o)
     176    {
     177        PtrType ptr = m_ptr;
     178        m_ptr = o.leakPtr();
     179        ASSERT(!ptr || m_ptr != ptr);
     180        deleteOwnedPtr(ptr);
     181
     182        return *this;
     183    }
     184#endif
     185
    135186    template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
    136187    {
Note: See TracChangeset for help on using the changeset viewer.