1 // { dg-do run }
2 // { dg-require-effective-target tls_runtime }
3 
4 #include <omp.h>
5 #include <assert.h>
6 
7 #define N 10
8 #define THR 4
9 
10 struct B
11 {
12   B();
13   B(const B &);
14   ~B();
15   B& operator=(const B &);
16   void doit();
17   static B *base;
18   static B *threadbase;
19 #pragma omp threadprivate(threadbase)
20 };
21 
22 B *B::base;
23 B *B::threadbase;
24 static unsigned cmask[THR];
25 static unsigned dmask[THR];
26 
B()27 B::B()
28 {
29   assert (base == 0);
30 }
31 
B(const B & b)32 B::B(const B &b)
33 {
34   unsigned index = &b - base;
35   assert (index < N);
36   cmask[omp_get_thread_num()] |= 1u << index;
37 }
38 
~B()39 B::~B()
40 {
41   if (threadbase)
42     {
43       unsigned index = this - threadbase;
44       assert (index < N);
45       dmask[omp_get_thread_num()] |= 1u << index;
46     }
47 }
48 
foo()49 void foo()
50 {
51   B b[N];
52 
53   B::base = b;
54 
55   #pragma omp parallel firstprivate(b)
56     {
57       assert (omp_get_num_threads () == THR);
58       B::threadbase = b;
59     }
60 
61   B::threadbase = 0;
62 }
63 
main()64 int main()
65 {
66   omp_set_dynamic (0);
67   omp_set_num_threads (THR);
68   foo();
69 
70   for (int i = 0; i < THR; ++i)
71     {
72       unsigned xmask = (1u << N) - 1;
73       assert (cmask[i] == xmask);
74       assert (dmask[i] == xmask);
75     }
76 
77   return 0;
78 }
79