forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AtExit.C
124 lines (108 loc) · 3 KB
/
AtExit.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
// RUN: cat %s | %cling -Xclang -verify 2>&1 | FileCheck %s
// FIXME: cat %s | %cling -fsyntax-only -Xclang -verify 2>&1
// Test to check functions registered via atexit are intercepted, and __dso_handle
// is properly overridden in for child interpreters.
#include <cstdlib>
#include "cling/Interpreter/Interpreter.h"
static void atexit_1() {
printf("atexit_1\n");
}
static void atexit_2() {
printf("atexit_2\n");
}
static void atexit_3() {
printf("atexit_3\n");
}
atexit(atexit_1);
.undo
// Undoing the registration should call the function
// CHECK: atexit_1
at_quick_exit(atexit_2);
.undo
// Make sure at_quick_exit is resolved correctly (mangling issues on gcc < 5)
// CHECK-NEXT: atexit_2
// Test reverse ordering in a single transaction.
static void atexitA() { printf("atexitA\n"); }
static void atexitB() { printf("atexitB\n"); }
static void atexitC() { printf("atexitC\n"); }
{
std::atexit(atexitA);
std::atexit(atexitB);
std::atexit(atexitC);
}
.undo
// CHECK-NEXT: atexitC
// CHECK-NEXT: atexitB
// CHECK-NEXT: atexitA
atexit(atexit_3);
cling::Interpreter * gChild = 0;
{
const char* kArgV[1] = {"cling"};
cling::Interpreter ChildInterp(*gCling, 1, kArgV);
gChild = &ChildInterp;
ChildInterp.declare("static void atexit_c() { printf(\"atexit_c %d\\n\", gChild==__dso_handle); }");
ChildInterp.execute("atexit(atexit_c);");
}
// ChildInterp
// CHECK: atexit_c 1
static void atexit_f() {
printf("atexit_f %s\n", gCling==__dso_handle ? "true" : "false");
}
at_quick_exit(atexit_f);
void atExit0 () {
printf("atExit0\n");
}
void atExit1 () {
printf("atExit1\n");
}
void atExit2 () {
printf("atExit2\n");
}
void atExitA () {
printf("atExitA\n");
std::atexit(&atExit0);
}
void atExitB () {
printf("atExitB\n");
std::atexit(&atExit1);
std::atexit(&atExit2);
}
// Recursion in a Transaction
{
std::atexit(&atExitA);
std::atexit(&atExitB);
}
.undo
// CHECK-NEXT: atExitB
// CHECK-NEXT: atExit2
// CHECK-NEXT: atExit1
// CHECK-NEXT: atExitA
// CHECK-NEXT: atExit0
// Recusion at shutdown
struct ShutdownRecursion {
static void DtorAtExit0() { printf("ShutdownRecursion0\n"); }
static void DtorAtExit1() { printf("ShutdownRecursion1\n"); }
static void DtorAtExit2() { printf("ShutdownRecursion2\n"); }
~ShutdownRecursion() {
printf("~ShutdownRecursion\n");
atexit(&DtorAtExit0);
atexit(&DtorAtExit1);
atexit(&DtorAtExit2);
}
} Out;
// expected-no-diagnostics
.q
// Reversed registration order
// CHECK-NEXT: ~ShutdownRecursion
// CHECK-NEXT: ShutdownRecursion2
// CHECK-NEXT: ShutdownRecursion1
// CHECK-NEXT: ShutdownRecursion0
// CHECK-NEXT: atexit_f true
// CHECK-NEXT: atexit_3