1 // RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 -fno-rtti > %t 2 // RUN: FileCheck %s < %t 3 // vftables are emitted very late, so do another pass to try to keep the checks 4 // in source order. 5 // RUN: FileCheck --check-prefix DTORS %s < %t 6 // RUN: FileCheck --check-prefix DTORS2 %s < %t 7 // RUN: FileCheck --check-prefix DTORS3 %s < %t 8 // 9 // RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s 10 11 namespace basic { 12 13 class A { 14 public: 15 A() { } 16 ~A(); 17 }; 18 19 void no_constructor_destructor_infinite_recursion() { 20 A a; 21 22 // CHECK: define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this) 23 // CHECK: [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4 24 // CHECK-NEXT: store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4 25 // CHECK-NEXT: [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"** [[THIS_ADDR]] 26 // CHECK-NEXT: ret %"class.basic::A"* [[T1]] 27 // CHECK-NEXT: } 28 } 29 30 A::~A() { 31 // Make sure that the destructor doesn't call itself: 32 // CHECK: define {{.*}} @"\01??1A@basic@@QAE@XZ" 33 // CHECK-NOT: call void @"\01??1A@basic@@QAE@XZ" 34 // CHECK: ret 35 } 36 37 struct B { 38 B(); 39 }; 40 41 // Tests that we can define constructors outside the class (PR12784). 42 B::B() { 43 // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this) 44 // CHECK: ret 45 } 46 47 struct C { 48 virtual ~C() { 49 // DTORS: define linkonce_odr x86_thiscallcc void @"\01??_GC@basic@@UAEPAXI@Z"(%"struct.basic::C"* %this, i32 %should_call_delete) 50 // DTORS: store i32 %should_call_delete, i32* %[[SHOULD_DELETE_VAR:[0-9a-z._]+]], align 4 51 // DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32* %[[SHOULD_DELETE_VAR]] 52 // DTORS: call x86_thiscallcc void @"\01??1C@basic@@UAE@XZ"(%"struct.basic::C"* %[[THIS:[0-9a-z]+]]) 53 // DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0 54 // DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]] 55 // 56 // DTORS: [[CALL_DELETE_LABEL]] 57 // DTORS-NEXT: %[[THIS_AS_VOID:[0-9a-z]+]] = bitcast %"struct.basic::C"* %[[THIS]] to i8* 58 // DTORS-NEXT: call void @"\01??3@YAXPAX@Z"(i8* %[[THIS_AS_VOID]]) 59 // DTORS-NEXT: br label %[[CONTINUE_LABEL]] 60 // 61 // DTORS: [[CONTINUE_LABEL]] 62 // DTORS-NEXT: ret void 63 64 // Check that we do the mangling correctly on x64. 65 // DTORS-X64: @"\01??_GC@basic@@UEAAPEAXI@Z" 66 } 67 virtual void foo(); 68 }; 69 70 // Emits the vftable in the output. 71 void C::foo() {} 72 73 void check_vftable_offset() { 74 C c; 75 // The vftable pointer should point at the beginning of the vftable. 76 // CHECK: [[THIS_PTR:%[0-9]+]] = bitcast %"struct.basic::C"* {{.*}} to [2 x i8*]** 77 // CHECK: store [2 x i8*]* @"\01??_7C@basic@@6B@", [2 x i8*]** [[THIS_PTR]] 78 } 79 80 void call_complete_dtor(C *obj_ptr) { 81 // CHECK: define void @"\01?call_complete_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr) 82 obj_ptr->~C(); 83 // CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4 84 // CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)*** 85 // CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]] 86 // CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 87 // CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]] 88 // CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 0) 89 // CHECK-NEXT: ret void 90 } 91 92 void call_deleting_dtor(C *obj_ptr) { 93 // CHECK: define void @"\01?call_deleting_dtor@basic@@YAXPAUC@1@@Z"(%"struct.basic::C"* %obj_ptr) 94 delete obj_ptr; 95 // CHECK: %[[OBJ_PTR_VALUE:.*]] = load %"struct.basic::C"** %{{.*}}, align 4 96 // CHECK: br i1 {{.*}}, label %[[DELETE_NULL:.*]], label %[[DELETE_NOTNULL:.*]] 97 98 // CHECK: [[DELETE_NOTNULL]] 99 // CHECK-NEXT: %[[PVTABLE:.*]] = bitcast %"struct.basic::C"* %[[OBJ_PTR_VALUE]] to void (%"struct.basic::C"*, i32)*** 100 // CHECK-NEXT: %[[VTABLE:.*]] = load void (%"struct.basic::C"*, i32)*** %[[PVTABLE]] 101 // CHECK-NEXT: %[[PVDTOR:.*]] = getelementptr inbounds void (%"struct.basic::C"*, i32)** %[[VTABLE]], i64 0 102 // CHECK-NEXT: %[[VDTOR:.*]] = load void (%"struct.basic::C"*, i32)** %[[PVDTOR]] 103 // CHECK-NEXT: call x86_thiscallcc void %[[VDTOR]](%"struct.basic::C"* %[[OBJ_PTR_VALUE]], i32 1) 104 // CHECK: ret void 105 } 106 107 struct D { 108 static int foo(); 109 110 D() { 111 static int ctor_static = foo(); 112 // CHECK that the static in the ctor gets mangled correctly: 113 // CHECK: @"\01?ctor_static@?1???0D@basic@@QAE@XZ@4HA" 114 } 115 ~D() { 116 static int dtor_static = foo(); 117 // CHECK that the static in the dtor gets mangled correctly: 118 // CHECK: @"\01?dtor_static@?1???1D@basic@@QAE@XZ@4HA" 119 } 120 }; 121 122 void use_D() { D c; } 123 124 } // end namespace basic 125 126 namespace dtor_in_second_nvbase { 127 128 struct A { 129 virtual void f(); // A needs vftable to be primary. 130 }; 131 struct B { 132 virtual ~B(); 133 }; 134 struct C : A, B { 135 virtual ~C(); 136 }; 137 138 C::~C() { 139 // CHECK-LABEL: define x86_thiscallcc void @"\01??1C@dtor_in_second_nvbase@@UAE@XZ" 140 // CHECK: (%"struct.dtor_in_second_nvbase::C"* %this) 141 // No this adjustment! 142 // CHECK-NOT: getelementptr 143 // CHECK: load %"struct.dtor_in_second_nvbase::C"** %{{.*}} 144 // Now we this-adjust before calling ~B. 145 // CHECK: bitcast %"struct.dtor_in_second_nvbase::C"* %{{.*}} to i8* 146 // CHECK: getelementptr inbounds i8* %{{.*}}, i64 4 147 // CHECK: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::B"* 148 // CHECK: call x86_thiscallcc void @"\01??1B@dtor_in_second_nvbase@@UAE@XZ" 149 // CHECK: (%"struct.dtor_in_second_nvbase::B"* %{{.*}}) 150 // CHECK: ret void 151 } 152 153 void foo() { 154 C c; 155 } 156 // DTORS2-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z" 157 // DTORS2: (%"struct.dtor_in_second_nvbase::C"* %this, i32 %should_call_delete) 158 // Do an adjustment from B* to C*. 159 // DTORS2: getelementptr i8* %{{.*}}, i32 -4 160 // DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"* 161 // DTORS2: call x86_thiscallcc void @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" 162 // DTORS2: ret void 163 164 } 165 166 namespace test2 { 167 // Just like dtor_in_second_nvbase, except put that in a vbase of a diamond. 168 169 // C's dtor is in the non-primary base. 170 struct A { virtual void f(); }; 171 struct B { virtual ~B(); }; 172 struct C : A, B { virtual ~C(); int c; }; 173 174 // Diamond hierarchy, with C as the shared vbase. 175 struct D : virtual C { int d; }; 176 struct E : virtual C { int e; }; 177 struct F : D, E { ~F(); int f; }; 178 179 F::~F() { 180 // CHECK-LABEL: define x86_thiscallcc void @"\01??1F@test2@@UAE@XZ"(%"struct.test2::F"*) 181 // Do an adjustment from C vbase subobject to F as though F was the 182 // complete type. 183 // CHECK: getelementptr inbounds i8* %{{.*}}, i32 -20 184 // CHECK: bitcast i8* %{{.*}} to %"struct.test2::F"* 185 // CHECK: store %"struct.test2::F"* 186 } 187 188 void foo() { 189 F f; 190 } 191 // DTORS3-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_DF@test2@@UAE@XZ" 192 // Do an adjustment from C* to F*. 193 // DTORS3: getelementptr i8* %{{.*}}, i32 20 194 // DTORS3: bitcast i8* %{{.*}} to %"struct.test2::F"* 195 // DTORS3: call x86_thiscallcc void @"\01??1F@test2@@UAE@XZ" 196 // DTORS3: ret void 197 198 } 199 200 namespace constructors { 201 202 struct A { 203 A() {} 204 }; 205 206 struct B : A { 207 B(); 208 ~B(); 209 }; 210 211 B::B() { 212 // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this) 213 // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) 214 // CHECK: ret 215 } 216 217 struct C : virtual A { 218 C(); 219 }; 220 221 C::C() { 222 // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived) 223 // TODO: make sure this works in the Release build too; 224 // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 225 // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]] 226 // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 227 // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] 228 // 229 // CHECK: [[INIT_VBASES]] 230 // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8* 231 // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 232 // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** 233 // CHECK-NEXT: store [2 x i32]* @"\01??_8C@constructors@@7B@", [2 x i32]** %[[vbptr]] 234 // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8* 235 // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 236 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* 237 // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) 238 // CHECK-NEXT: br label %[[SKIP_VBASES]] 239 // 240 // CHECK: [[SKIP_VBASES]] 241 // Class C does not define or override methods, so shouldn't change the vfptr. 242 // CHECK-NOT: @"\01??_7C@constructors@@6B@" 243 // CHECK: ret 244 } 245 246 void create_C() { 247 C c; 248 // CHECK: define void @"\01?create_C@constructors@@YAXXZ"() 249 // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %c, i32 1) 250 // CHECK: ret 251 } 252 253 struct D : C { 254 D(); 255 }; 256 257 D::D() { 258 // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr 259 // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 260 // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]] 261 // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 262 // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] 263 // 264 // CHECK: [[INIT_VBASES]] 265 // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8* 266 // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 267 // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** 268 // CHECK-NEXT: store [2 x i32]* @"\01??_8D@constructors@@7B@", [2 x i32]** %[[vbptr]] 269 // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8* 270 // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 271 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* 272 // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) 273 // CHECK-NEXT: br label %[[SKIP_VBASES]] 274 // 275 // CHECK: [[SKIP_VBASES]] 276 // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0) 277 // CHECK: ret 278 } 279 280 struct E : virtual C { 281 E(); 282 }; 283 284 E::E() { 285 // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr 286 // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 287 // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]] 288 // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 289 // CHECK: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] 290 // 291 // CHECK: [[INIT_VBASES]] 292 // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8* 293 // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 294 // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to [3 x i32]** 295 // CHECK-NEXT: store [3 x i32]* @"\01??_8E@constructors@@7B01@@", [3 x i32]** %[[vbptr_E]] 296 // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4 297 // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]** 298 // CHECK-NEXT: store [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", [2 x i32]** %[[vbptr_C]] 299 // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8* 300 // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 301 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* 302 // CHECK-NEXT: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}}) 303 // CHECK: call x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %{{.*}}, i32 0) 304 // CHECK-NEXT: br label %[[SKIP_VBASES]] 305 // 306 // CHECK: [[SKIP_VBASES]] 307 // CHECK: ret 308 } 309 310 // PR16735 - even abstract classes should have a constructor emitted. 311 struct F { 312 F(); 313 virtual void f() = 0; 314 }; 315 316 F::F() {} 317 // CHECK: define x86_thiscallcc %"struct.constructors::F"* @"\01??0F@constructors@@QAE@XZ" 318 319 } // end namespace constructors 320 321 namespace dtors { 322 323 struct A { 324 ~A(); 325 }; 326 327 void call_nv_complete(A *a) { 328 a->~A(); 329 // CHECK: define void @"\01?call_nv_complete@dtors@@YAXPAUA@1@@Z" 330 // CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ" 331 // CHECK: ret 332 } 333 334 // CHECK: declare x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ" 335 336 // Now try some virtual bases, where we need the complete dtor. 337 338 struct B : virtual A { ~B(); }; 339 struct C : virtual A { ~C(); }; 340 struct D : B, C { ~D(); }; 341 342 void call_vbase_complete(D *d) { 343 d->~D(); 344 // CHECK: define void @"\01?call_vbase_complete@dtors@@YAXPAUD@1@@Z" 345 // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) 346 // CHECK: ret 347 } 348 349 // The complete dtor should call the base dtors for D and the vbase A (once). 350 // CHECK: define linkonce_odr x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ" 351 // CHECK-NOT: call 352 // CHECK: call x86_thiscallcc void @"\01??1D@dtors@@QAE@XZ" 353 // CHECK-NOT: call 354 // CHECK: call x86_thiscallcc void @"\01??1A@dtors@@QAE@XZ" 355 // CHECK-NOT: call 356 // CHECK: ret 357 358 void destroy_d_complete() { 359 D d; 360 // CHECK: define void @"\01?destroy_d_complete@dtors@@YAXXZ" 361 // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) 362 // CHECK: ret 363 } 364 365 // FIXME: Clang manually inlines the deletion, so we don't get a call to the 366 // deleting dtor (_G). The only way to call deleting dtors currently is through 367 // a vftable. 368 void call_nv_deleting_dtor(D *d) { 369 delete d; 370 // CHECK: define void @"\01?call_nv_deleting_dtor@dtors@@YAXPAUD@1@@Z" 371 // CHECK: call x86_thiscallcc void @"\01??_DD@dtors@@QAE@XZ"(%"struct.dtors::D"* %{{[^,]+}}) 372 // CHECK: call void @"\01??3@YAXPAX@Z" 373 // CHECK: ret 374 } 375 376 } 377 378 namespace test1 { 379 struct A { }; 380 struct B : virtual A { 381 B(int *a); 382 B(const char *a, ...); 383 __cdecl B(short *a); 384 }; 385 B::B(int *a) {} 386 B::B(const char *a, ...) {} 387 B::B(short *a) {} 388 // CHECK: define x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z" 389 // CHECK: (%"struct.test1::B"* returned %this, i32* %a, i32 %is_most_derived) 390 // CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PBDZZ" 391 // CHECK: (%"struct.test1::B"* returned %this, i32 %is_most_derived, i8* %a, ...) 392 393 // FIXME: This should be x86_thiscallcc. MSVC ignores explicit CCs on structors. 394 // CHECK: define %"struct.test1::B"* @"\01??0B@test1@@QAA@PAF@Z" 395 // CHECK: (%"struct.test1::B"* returned %this, i16* %a, i32 %is_most_derived) 396 397 void construct_b() { 398 int a; 399 B b1(&a); 400 B b2("%d %d", 1, 2); 401 } 402 // CHECK-LABEL: define void @"\01?construct_b@test1@@YAXXZ"() 403 // CHECK: call x86_thiscallcc %"struct.test1::B"* @"\01??0B@test1@@QAE@PAH@Z" 404 // CHECK: (%"struct.test1::B"* {{.*}}, i32* {{.*}}, i32 1) 405 // CHECK: call %"struct.test1::B"* (%"struct.test1::B"*, i32, i8*, ...)* @"\01??0B@test1@@QAA@PBDZZ" 406 // CHECK: (%"struct.test1::B"* {{.*}}, i32 1, i8* {{.*}}, i32 1, i32 2) 407 } 408 409 // Dtor thunks for classes in anonymous namespaces should be internal, not 410 // linkonce_odr. 411 namespace { 412 struct A { 413 virtual ~A() { } 414 }; 415 } 416 void *getA() { 417 return (void*)new A(); 418 } 419 // CHECK: define internal x86_thiscallcc void @"\01??_GA@?A@@UAEPAXI@Z" 420 // CHECK: (%"struct.(anonymous namespace)::A"* %this, i32 %should_call_delete) 421 // CHECK: define internal x86_thiscallcc void @"\01??1A@?A@@UAE@XZ" 422 // CHECK: (%"struct.(anonymous namespace)::A"* %this) 423