mclow.lists created this revision.
mclow.lists added a reviewer: EricWF.
mclow.lists added a subscriber: cfe-commits.

http://llvm.org/show_bug.cgi?id=28929 shows a scenario where `make_shared` of a 
class with a protected constructor compiles successfully (it should fail).

This is because we apply an empty-base class optimization to the shared_ptr.

This is one way to solve the problem; there are probably others.
However, this works, and passes all the tests (including the two new ones I 
just added).


https://reviews.llvm.org/D28253

Files:
  include/memory
  test/libcxx/test/config.py
  
test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.private.fail.cpp
  
test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp

Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
===================================================================
--- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
+++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.protected.fail.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
+
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct S {
+protected:
+   S () {};  // ctor is protected
+};
+
+int main()
+{
+    std::shared_ptr<S> p = std::make_shared<S>();
+}
Index: test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.private.fail.cpp
===================================================================
--- test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.private.fail.cpp
+++ test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.private.fail.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// shared_ptr
+
+// template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
+
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct S {
+private:
+   S () {};  // ctor is private
+};
+
+int main()
+{
+    std::shared_ptr<S> p = std::make_shared<S>();
+}
Index: test/libcxx/test/config.py
===================================================================
--- test/libcxx/test/config.py
+++ test/libcxx/test/config.py
@@ -412,6 +412,8 @@
             self.lit_config.fatal("cxx_headers='%s' is not a directory."
                                   % cxx_headers)
         self.cxx.compile_flags += ['-I' + cxx_headers]
+        if self.libcxx_obj_root is None:
+            return
         cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include', 'c++-build')
         if os.path.isdir(cxxabi_headers):
             self.cxx.compile_flags += ['-I' + cxxabi_headers]
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -4435,6 +4435,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::make_shared(_Args&& ...__args)
 {
+    static_assert( is_constructible<_Tp, _Args...>::value, "Can't construct object in make_shared" );
     typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
     typedef allocator<_CntrlBlk> _A2;
     typedef __allocator_destructor<_A2> _D2;
@@ -4453,6 +4454,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _Args&& ...__args)
 {
+    static_assert( is_constructible<_Tp, _Args...>::value, "Can't construct object in allocate_shared" );
     typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
     typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2;
     typedef __allocator_destructor<_A2> _D2;
@@ -4473,6 +4475,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::make_shared()
 {
+    static_assert((is_constructible<_Tp>::value), "Can't construct object in make_shared" );
     typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
     typedef allocator<_CntrlBlk> _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4491,6 +4494,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::make_shared(_A0& __a0)
 {
+    static_assert((is_constructible<_Tp, _A0>::value), "Can't construct object in make_shared" );
     typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
     typedef allocator<_CntrlBlk> _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4509,6 +4513,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::make_shared(_A0& __a0, _A1& __a1)
 {
+    static_assert((is_constructible<_Tp, _A0, _A1>::value), "Can't construct object in make_shared" );
     typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
     typedef allocator<_CntrlBlk> _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4527,6 +4532,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::make_shared(_A0& __a0, _A1& __a1, _A2& __a2)
 {
+    static_assert((is_constructible<_Tp, _A0, _A1, _A2>::value), "Can't construct object in make_shared" );
     typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
     typedef allocator<_CntrlBlk> _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4545,6 +4551,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::allocate_shared(const _Alloc& __a)
 {
+    static_assert((is_constructible<_Tp>::value), "Can't construct object in allocate_shared" );
     typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
     typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4564,6 +4571,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0)
 {
+    static_assert((is_constructible<_Tp, _A0>::value), "Can't construct object in allocate_shared" );
     typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
     typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4583,6 +4591,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1)
 {
+    static_assert((is_constructible<_Tp, _A0, _A1>::value), "Can't construct object in allocate_shared" );
     typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
     typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
@@ -4602,6 +4611,7 @@
 shared_ptr<_Tp>
 shared_ptr<_Tp>::allocate_shared(const _Alloc& __a, _A0& __a0, _A1& __a1, _A2& __a2)
 {
+    static_assert((is_constructible<_Tp, _A0, _A1, _A2>::value), "Can't construct object in allocate_shared" );
     typedef __shared_ptr_emplace<_Tp, _Alloc> _CntrlBlk;
     typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _Alloc2;
     typedef __allocator_destructor<_Alloc2> _D2;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D28253: static_asser... Marshall Clow via Phabricator via cfe-commits

Reply via email to