| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // RUN: cxx_compiler -c %s cxx_rtti -o %t1.o |
| // RUN: linker -o %t%exeext %t1.o |
| // RUN: runtool %t%exeext | grep "PASSED" |
| |
| |
| |
| |
| // check that __cxa_guard_acuire, __cxa_gaurd_release and __cxa_guard_abort are doing |
| // their jobs |
| // |
| // |
| |
| extern "C" { |
| int printf(const char *, ...); |
| int __cxa_guard_acquire(long long *); |
| void __cxa_guard_release(long long *); |
| void __cxa_guard_abort(long long *); |
| } |
| |
| #if 0 |
| |
| extern "C" int __cxa_guard_acquire ( __int64_t *guard_object ); |
| |
| Returns 1 if the initialization is not yet complete; 0 otherwise. This function is called before initialization takes place. If this function returns 1, either __cxa_guard_release or __cxa_guard_abort must be called with the same argument. The first byte of the guard_object is not modified by this function. |
| |
| A thread-safe implementation will probably guard access to the first byte of the guard_object with a mutex. If this function returns 1, the mutex will have been acquired by the calling thread. |
| |
| extern "C" void __cxa_guard_release ( __int64_t *guard_object ); |
| |
| Sets the first byte of the guard object to a non-zero value. This function is called after initialization is complete. |
| |
| A thread-safe implementation will release the mutex acquired by __cxa_guard_acquire after setting the first byte of the guard object. |
| |
| extern "C" void __cxa_guard_abort ( __int64_t *guard_object ); |
| |
| This function is called if the initialization terminates by throwing an exception. |
| |
| A thread-safe implementation will release the mutex acquired by __cxa_guard_acquire. |
| |
| <b>NOTE</b>: |
| |
| #endif |
| |
| static int nerr; |
| #define ERR(a) {printf("@%d %s\n", __LINE__, a); nerr++;} |
| |
| int main() |
| { |
| long long gv = 0, gv2 = 0; |
| unsigned char *gp = (unsigned char *) &gv; |
| // simple case aquire should succeed and return 1. |
| |
| if (!__cxa_guard_acquire(&gv)) ERR("FAILED TO ACQUIRE"); |
| |
| if (gp[0]) ERR("Lowest byte of the Guard var set prematurely"); |
| // other buytes could be set at this point |
| |
| // now release |
| __cxa_guard_release(&gv); |
| if (!gv) ERR("Guard var not set"); |
| if (!gp[0]) ERR("first byte 0"); |
| if (gp[1]||gp[2]||gp[3]||gp[4]||gp[5]||gp[6]||gp[7]) ERR("Other bytes set"); |
| |
| long long gs = gv; |
| |
| // A second call should fail |
| if (__cxa_guard_acquire(&gv)) ERR("Acquired again") |
| |
| // should not change gv |
| if (gs != gv) ERR("gv changed by a failing call"); |
| |
| // now test abort |
| gp = (unsigned char *)&gv2; |
| if (!__cxa_guard_acquire(&gv2)) ERR("FAILED TO ACQUIRE gv2"); |
| if (gp[0]) ERR("Lowest byte of the Guard var set prematurely"); |
| |
| __cxa_guard_abort(&gv2); |
| if (gv2) ERR("Guard var set by abort "); |
| if (!__cxa_guard_acquire(&gv2)) ERR("FAILED TO ACQUIRE gv2"); |
| if (gp[0]) ERR("Lowest byte of the Guard var set prematurely"); |
| |
| // now release |
| __cxa_guard_release(&gv2); |
| if (!gv2) ERR("Guard var not set"); |
| if (!gp[0]) ERR("first byte 0"); |
| if (gp[1]||gp[2]||gp[3]||gp[4]||gp[5]||gp[6]||gp[7]) ERR("Other bytes set"); |
| printf("%s\n", nerr ? "FAILED" : "PASSED"); |
| return nerr; |
| } |