(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
attr-copy-6.c
       1  /* PR middle-end/88546 - Copy attribute unusable for weakrefs
       2     { dg-do compile }
       3     { dg-skip-if "Attributes not supported" { { hppa*-*-hpux* } && { ! lp64 } } }
       4     { dg-options "-O2 -Wall" }
       5     { dg-require-visibility "hidden" }
       6     { dg-require-alias "" }
       7     { dg-require-weak "" } */
       8  
       9  #define ATTR(...)   __attribute__ ((__VA_ARGS__))
      10  #define ASRT(expr)   _Static_assert (expr, #expr)
      11  
      12  #define ASMNAME(cname)  ASMNAME2 (__USER_LABEL_PREFIX__, cname)
      13  #define ASMNAME2(prefix, cname) STRING (prefix) cname
      14  #define STRING(x)    #x
      15  
      16  /* Variable that is local to this translation unit but that can
      17     be modified from other units by calling reset_unit_local().  */
      18  static int unit_local;
      19  
      20  void reset_unit_local (void)
      21  {
      22    unit_local = 0;
      23  }
      24  
      25  /* Attribute leaf implies that fleaf() doesn't modify unit_local().  */
      26  ATTR (leaf, returns_nonnull)
      27  void* fleaf_retnz (void);
      28  
      29  /* Verify both attributes have been applied.  */
      30  ASRT (__builtin_has_attribute (fleaf_retnz, leaf));
      31  ASRT (__builtin_has_attribute (fleaf_retnz, returns_nonnull));
      32  
      33  /* Verify that attribute leaf has the expected effect.  */
      34  void call_fleaf_retnz (void)
      35  {
      36    int i = unit_local;
      37    void *p = fleaf_retnz ();
      38  
      39    /* Expect both tests to be folded to false and the calls eliminated.  */
      40    extern void call_fleaf_retnz_test_leaf_eliminated (void);
      41    if (i != unit_local)
      42      call_fleaf_retnz_test_leaf_eliminated ();
      43  
      44    extern void call_fleaf_retnz_test_nonnull_eliminated (void);
      45    if (p == 0)
      46      call_fleaf_retnz_test_nonnull_eliminated ();
      47  }
      48  
      49  
      50  /* Verify that attribute copy copies the returns_nonnull attribute
      51     but doesn't try to copy attribute leaf which only applies to extern
      52     function.  */
      53  static ATTR (copy (fleaf_retnz), weakref ("fleaf_retnz"))
      54  void* fweakref_fleaf_retnz_copy (void);
      55  
      56  ASRT (!__builtin_has_attribute (fweakref_fleaf_retnz_copy, leaf));
      57  ASRT (__builtin_has_attribute (fweakref_fleaf_retnz_copy, returns_nonnull));
      58  
      59  void call_fweakref_fleaf_retnz_copy (void)
      60  {
      61    int i = unit_local;
      62    void *p = fweakref_fleaf_retnz_copy ();
      63  
      64    /* Since leaf is not copied, expect the following test not to be
      65       folded and the call to be emitted.  */
      66    extern void call_fweakref_test_leaf_emitted (void);
      67    if (i != unit_local)
      68      call_fweakref_test_leaf_emitted ();
      69  
      70    /* Expect the following test to be folded to false and the call
      71       eliminated.  */
      72    extern void call_fweakref_fleaf_nonnull_eliminated (void);
      73    if (p == 0)
      74      call_fweakref_fleaf_nonnull_eliminated ();
      75  }
      76  
      77  /* This is reduced from libgfortran/runtime/error.c.  Verify it
      78     doesn't trigger warnings and that the noreturn bit is copied
      79     to the alias by verifying that calling the alias in a non-void
      80     function with no return statement isn't diagnosed.  */
      81  
      82  extern _Noreturn void fnoreturn (void);
      83  
      84  extern __typeof (fnoreturn)
      85    ATTR (visibility ("hidden"))
      86    fnoreturn __asm__ (ASMNAME ("fnoreturn_name"));
      87  
      88  void fnoreturn (void)
      89  {
      90    __builtin_abort ();
      91  }
      92  
      93  extern __typeof (fnoreturn)
      94    ATTR (alias ("fnoreturn_name"), copy (fnoreturn))
      95    fnoreturn_alias;
      96  
      97  int call_fnoreturn_alias (void)
      98  {
      99    fnoreturn_alias ();
     100  }