1 // { dg-do "run" }
2 #include <cassert>
3 
4 struct A
5 {
6   double a;
7   double b;
8 };
9 
10 struct B
11 {
12   A a;
13 };
14 
15 struct C
16 : public A { };
17 
18 struct D
19 {
operator =D20   D& operator=(const D&) throw() { return *this; }
21 };
22 
23 struct E
24 {
operator =E25   E& operator=(const E&) throw(int) { return *this; }
26 };
27 
28 struct E1
29 {
operator =E130   E1& operator=(const E1&) throw(int) { throw int(); return *this; }
31 };
32 
33 struct F
34 {
FF35   F() throw(int) { }
36 };
37 
38 struct G
39 {
GG40   G() throw(int) { throw int(); }
41 };
42 
43 struct H
44 {
operator =H45   H& operator=(H&) throw(int) { return *this; }
46 };
47 
48 struct H1
49 {
operator =H150   H1& operator=(H1&) throw(int) { throw int(); return *this; }
51 };
52 
53 struct I
54 {
operator =I55   I& operator=(I&) throw(int) { return *this; }
operator =I56   I& operator=(const I&) throw() { return *this; }
57 };
58 
59 struct I1
60 {
operator =I161   I1& operator=(I1&) throw(int) { throw int(); return *this; }
operator =I162   I1& operator=(const I1&) throw() { return *this; }
63 };
64 
65 struct J
66 {
operator =J67   J& operator=(J&) throw() { return *this; }
operator =J68   J& operator=(const J&) throw() { return *this; }
operator =J69   J& operator=(volatile J&) throw() { return *this; }
operator =J70   J& operator=(const volatile J&) throw() { return *this; }
71 };
72 
73 struct K
74 {
operator =K75   K& operator=(K&) throw() { return *this; }
76 };
77 
78 struct L
79 {
operator =L80   L& operator=(const L&) throw() { return *this; }
81 };
82 
83 template<typename T>
84   bool
f()85   f()
86   { return __has_nothrow_assign(T); }
87 
88 template<typename T>
89   class My
90   {
91   public:
92     bool
f()93     f()
94     { return !!__has_nothrow_assign(T); }
95   };
96 
97 template<typename T>
98   class My2
99   {
100   public:
101     static const bool trait = __has_nothrow_assign(T);
102   };
103 
104 template<typename T>
105   const bool My2<T>::trait;
106 
107 template<typename T, bool b = __has_nothrow_assign(T)>
108   struct My3_help
109   { static const bool trait = b; };
110 
111 template<typename T, bool b>
112   const bool My3_help<T, b>::trait;
113 
114 template<typename T>
115   class My3
116   {
117   public:
118     bool
f()119     f()
120     { return My3_help<T>::trait; }
121   };
122 
123 #define PTEST(T) (__has_nothrow_assign(T) && f<T>() \
124                   && My<T>().f() && My2<T>::trait && My3<T>().f())
125 
126 #define NTEST(T) (!__has_nothrow_assign(T) && !f<T>() \
127                   && !My<T>().f() && !My2<T>::trait && !My3<T>().f())
128 
main()129 int main()
130 {
131   assert (PTEST (int));
132   assert (NTEST (int (int)));
133   assert (NTEST (void));
134   assert (PTEST (A));
135   assert (PTEST (B));
136   assert (PTEST (C));
137   assert (NTEST (C[]));
138   assert (PTEST (D));
139   assert (NTEST (E));
140   assert (NTEST (E1));
141   assert (PTEST (F));
142   assert (PTEST (G));
143   assert (NTEST (H));
144   assert (NTEST (H1));
145   assert (NTEST (I));
146   assert (NTEST (I1));
147   assert (PTEST (J));
148   assert (NTEST (const K));
149   assert (NTEST (const L));
150 
151   return 0;
152 }
153