/* PR middle-end/88546 - Copy attribute unusable for weakrefs { dg-do compile } { dg-skip-if "Attributes not supported" { { hppa*-*-hpux* } && { ! lp64 } } } { dg-options "-O2 -Wall" } { dg-require-visibility "hidden" } { dg-require-alias "" } { dg-require-weak "" } */ #define ATTR(...) __attribute__ ((__VA_ARGS__)) #define ASRT(expr) _Static_assert (expr, #expr) #define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname) #define ASMNAME2(prefix, cname) STRING (prefix) cname #define STRING(x) #x /* Variable that is local to this translation unit but that can be modified from other units by calling reset_unit_local(). */ static int unit_local; void reset_unit_local (void) { unit_local = 0; } /* Attribute leaf implies that fleaf() doesn't modify unit_local(). */ ATTR (leaf, returns_nonnull) void* fleaf_retnz (void); /* Verify both attributes have been applied. */ ASRT (__builtin_has_attribute (fleaf_retnz, leaf)); ASRT (__builtin_has_attribute (fleaf_retnz, returns_nonnull)); /* Verify that attribute leaf has the expected effect. */ void call_fleaf_retnz (void) { int i = unit_local; void *p = fleaf_retnz (); /* Expect both tests to be folded to false and the calls eliminated. */ extern void call_fleaf_retnz_test_leaf_eliminated (void); if (i != unit_local) call_fleaf_retnz_test_leaf_eliminated (); extern void call_fleaf_retnz_test_nonnull_eliminated (void); if (p == 0) call_fleaf_retnz_test_nonnull_eliminated (); } /* Verify that attribute copy copies the returns_nonnull attribute but doesn't try to copy attribute leaf which only applies to extern function. */ static ATTR (copy (fleaf_retnz), weakref ("fleaf_retnz")) void* fweakref_fleaf_retnz_copy (void); ASRT (!__builtin_has_attribute (fweakref_fleaf_retnz_copy, leaf)); ASRT (__builtin_has_attribute (fweakref_fleaf_retnz_copy, returns_nonnull)); void call_fweakref_fleaf_retnz_copy (void) { int i = unit_local; void *p = fweakref_fleaf_retnz_copy (); /* Since leaf is not copied, expect the following test not to be folded and the call to be emitted. */ extern void call_fweakref_test_leaf_emitted (void); if (i != unit_local) call_fweakref_test_leaf_emitted (); /* Expect the following test to be folded to false and the call eliminated. */ extern void call_fweakref_fleaf_nonnull_eliminated (void); if (p == 0) call_fweakref_fleaf_nonnull_eliminated (); } /* This is reduced from libgfortran/runtime/error.c. Verify it doesn't trigger warnings and that the noreturn bit is copied to the alias by verifying that calling the alias in a non-void function with no return statement isn't diagnosed. */ extern _Noreturn void fnoreturn (void); extern __typeof (fnoreturn) ATTR (visibility ("hidden")) fnoreturn __asm__ (ASMNAME ("fnoreturn_name")); void fnoreturn (void) { __builtin_abort (); } extern __typeof (fnoreturn) ATTR (alias ("fnoreturn_name"), copy (fnoreturn)) fnoreturn_alias; int call_fnoreturn_alias (void) { fnoreturn_alias (); }