1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03
10 
11 #include <memory>
12 
13 template <int> struct Tag {};
14 
15 template <int ID>
16 using SPtr = std::shared_ptr<void(Tag<ID>)>;
17 
18 template <int ID>
19 using FnType = void(Tag<ID>);
20 
21 template <int ID>
TestFn(Tag<ID>)22 void TestFn(Tag<ID>) {}
23 
24 template <int ID>
getFn()25 FnType<ID>* getFn() {
26   return &TestFn<ID>;
27 }
28 
29 struct Deleter {
30   template <class Tp>
operator ()Deleter31   void operator()(Tp) const {
32     using RawT = typename std::remove_pointer<Tp>::type;
33     static_assert(std::is_function<RawT>::value ||
34                   std::is_same<typename std::remove_cv<RawT>::type,
35                                std::nullptr_t>::value,
36                   "");
37   }
38 };
39 
main(int,char **)40 int main(int, char**) {
41   {
42     SPtr<0> s; // OK
43     SPtr<1> s1(nullptr); // OK
44     SPtr<2> s2(getFn<2>(), Deleter{}); // OK
45     SPtr<3> s3(nullptr, Deleter{}); // OK
46   }
47 
48   // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed{{.*}}default_delete cannot be instantiated for function types}}
49   std::default_delete<FnType<5>> deleter{}; // expected-note {{requested here}}
50 
51   return 0;
52 }
53