1 | // RUN: %clangxx_cfi -c -DTU1 -o %t1.o %s |
2 | // RUN: %clangxx_cfi -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp |
3 | // RUN: %clangxx_cfi -o %t1 %t1.o %t2.o |
4 | // RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s |
5 | |
6 | // RUN: %clangxx_cfi -c -DTU1 -DB32 -o %t1.o %s |
7 | // RUN: %clangxx_cfi -c -DTU2 -DB32 -o %t2.o %S/../cfi/anon-namespace.cpp |
8 | // RUN: %clangxx_cfi -o %t2 %t1.o %t2.o |
9 | // RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s |
10 | |
11 | // RUN: %clangxx_cfi -c -DTU1 -DB64 -o %t1.o %s |
12 | // RUN: %clangxx_cfi -c -DTU2 -DB64 -o %t2.o %S/../cfi/anon-namespace.cpp |
13 | // RUN: %clangxx_cfi -o %t3 %t1.o %t2.o |
14 | // RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s |
15 | |
16 | // RUN: %clangxx_cfi -c -DTU1 -DBM -o %t1.o %s |
17 | // RUN: %clangxx_cfi -c -DTU2 -DBM -o %t2.o %S/../cfi/anon-namespace.cpp |
18 | // RUN: %clangxx_cfi -o %t4 %t1.o %t2.o |
19 | // RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s |
20 | |
21 | // RUN: %clangxx -c -DTU1 -o %t1.o %s |
22 | // RUN: %clangxx -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp |
23 | // RUN: %clangxx -o %t5 %t1.o %t2.o |
24 | // RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s |
25 | |
26 | // RUN: %clangxx_cfi_diag -c -DTU1 -o %t1.o %s |
27 | // RUN: %clangxx_cfi_diag -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp |
28 | // RUN: %clangxx_cfi_diag -o %t6 %t1.o %t2.o |
29 | // RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s |
30 | |
31 | // Tests that the CFI mechanism treats classes in the anonymous namespace in |
32 | // different translation units as having distinct identities. This is done by |
33 | // compiling two translation units TU1 and TU2 containing a class named B in an |
34 | // anonymous namespace, and testing that the program crashes if TU2 attempts to |
35 | // use a TU1 B as a TU2 B. |
36 | |
37 | // FIXME: This test should not require that the paths supplied to the compiler |
38 | // are different. It currently does so because bitset names have global scope |
39 | // so we have to mangle the file path into the bitset name. |
40 | |
41 | // REQUIRES: cxxabi |
42 | |
43 | #include <stdio.h> |
44 | #include "utils.h" |
45 | |
46 | struct A { |
47 | virtual void f() = 0; |
48 | }; |
49 | |
50 | namespace { |
51 | |
52 | struct B : A { |
53 | virtual void f() {} |
54 | }; |
55 | |
56 | } |
57 | |
58 | A *mkb(); |
59 | |
60 | #ifdef TU1 |
61 | |
62 | A *mkb() { |
63 | return new B; |
64 | } |
65 | |
66 | #endif // TU1 |
67 | |
68 | #ifdef TU2 |
69 | |
70 | int main() { |
71 | create_derivers<B>(); |
72 | |
73 | A *a = mkb(); |
74 | break_optimization(a); |
75 | |
76 | // CFI: 1 |
77 | // NCFI: 1 |
78 | fprintf(stderr, "1\n" ); |
79 | |
80 | // CFI-DIAG: runtime error: control flow integrity check for type '(anonymous namespace)::B' failed during base-to-derived cast |
81 | // CFI-DIAG-NEXT: note: vtable is of type '{{.*}}anonymous namespace{{.*}}::B' |
82 | // CFI-DIAG: runtime error: control flow integrity check for type '(anonymous namespace)::B' failed during virtual call |
83 | // CFI-DIAG-NEXT: note: vtable is of type '{{.*}}anonymous namespace{{.*}}::B' |
84 | ((B *)a)->f(); // UB here |
85 | |
86 | // CFI-NOT: {{^2$}} |
87 | // NCFI: {{^2$}} |
88 | fprintf(stderr, "2\n" ); |
89 | } |
90 | |
91 | #endif // TU2 |
92 | |