(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Wdangling-pointer-2.c
       1  /* PR middle-end/63272 - GCC should warn when using pointer to dead scoped
       2     variable within the same function
       3     Exercise basic cases of -Wdangling-pointer with optimization.
       4     { dg-do compile }
       5     { dg-options "-O2 -Wall -Wno-uninitialized -Wno-return-local-addr -ftrack-macro-expansion=0" }
       6     { dg-require-effective-target alloca } */
       7  
       8  typedef __INTPTR_TYPE__ intptr_t;
       9  typedef __SIZE_TYPE__   size_t;
      10  
      11  #if __cplusplus
      12  #  define EXTERN_C extern "C"
      13  #else
      14  #  define EXTERN_C extern
      15  #endif
      16  
      17  #define NOIPA __attribute__ ((noipa))
      18  
      19  EXTERN_C void* alloca (size_t);
      20  EXTERN_C void* malloc (size_t);
      21  EXTERN_C void* memchr (const void*, int, size_t);
      22  EXTERN_C char* strchr (const char*, int);
      23  
      24  int sink (const void*, ...);
      25  #define sink(...) sink (0, __VA_ARGS__)
      26  
      27  
      28  NOIPA void nowarn_addr (void)
      29  {
      30    int *p;
      31    {
      32      int a[] = { 1, 2, 3 };
      33      p = a;
      34    }
      35  
      36    // This is suspect but not a clear error.
      37    sink (&p);
      38  }
      39  
      40  
      41  NOIPA char* nowarn_ptr (void)
      42  {
      43    char *p;
      44    sink (&p);
      45    return p;
      46  }
      47  
      48  
      49  NOIPA char* nowarn_cond_ptr (void)
      50  {
      51    // Distilled from a false positive in Glibc dlerror.c.
      52    char *q;
      53    if (sink (&q))
      54      return q;
      55  
      56    return 0;
      57  }
      58  
      59  
      60  NOIPA void nowarn_loop_ptr (int n, int *p)
      61  {
      62    // Distilled from a false positive in Glibc td_thr_get_info.c.
      63    for (int i = 0; i != 2; ++i)
      64      {
      65        int x;
      66        sink (&x);
      67        *p++ = x;
      68      }
      69  
      70    /* With the loop unrolled, Q is clobbered just before the call to
      71       sink(), making it indistinguishable from passing it a pointer
      72       to an out-of-scope variable.  Verify that the warning doesn't
      73       suffer from false positives due to this.
      74       int * q;
      75       int * q.1_17;
      76       int * q.1_26;
      77  
      78       <bb 2>:
      79       f (&q);
      80       q.1_17 = q;
      81       *p_5(D) = q.1_17;
      82       q ={v} {CLOBBER};
      83       f (&q);
      84       q.1_26 = q;
      85       MEM[(void * *)p_5(D) + 8B] = q.1_26;
      86       q ={v} {CLOBBER};
      87       return;
      88    */
      89  }
      90  
      91  
      92  NOIPA void nowarn_intptr_t (void)
      93  {
      94    intptr_t ip;
      95    {
      96      int a[] = { 1, 2, 3 };
      97      ip = (intptr_t)a;
      98    }
      99  
     100    // Using an intptr_t is not diagnosed.
     101    sink (0, ip);
     102  }
     103  
     104  
     105  NOIPA void nowarn_string_literal (void)
     106  {
     107    const char *s;
     108    {
     109      s = "123";
     110    }
     111  
     112    sink (s);
     113  }
     114  
     115  
     116  NOIPA void nowarn_extern_array (int x)
     117  {
     118    {
     119      /* This is a silly sanity check.  */
     120      extern int eia[];
     121      int *p;
     122      {
     123        p = eia;
     124      }
     125      sink (p);
     126    }
     127  }
     128  
     129  
     130  NOIPA void nowarn_static_array (int x)
     131  {
     132    {
     133      const char *s;
     134      {
     135        static const char sca[] = "123";
     136        s = sca;
     137      }
     138  
     139      sink (s);
     140    }
     141    {
     142      const int *p;
     143      {
     144        static const int sia[] = { 1, 2, 3 };
     145        p = sia;
     146      }
     147  
     148      sink (p);
     149    }
     150    {
     151      const int *p;
     152      {
     153        static const int sia[] = { 1, 2, 3 };
     154        p = (const int*)memchr (sia, x, sizeof sia);
     155      }
     156  
     157      sink (p);
     158    }
     159  }
     160  
     161  
     162  NOIPA void nowarn_alloca (unsigned n)
     163  {
     164    {
     165      char *p;
     166      {
     167        p = (char*)alloca (n);
     168      }
     169      sink (p);
     170    }
     171    {
     172      int *p;
     173      {
     174        p = (int*)alloca (n * sizeof *p);
     175        sink (p);
     176      }
     177      sink (p);
     178    }
     179    {
     180      long *p;
     181      {
     182        p = (long*)alloca (n * sizeof *p);
     183        sink (p);
     184        p = p + 1;
     185      }
     186      sink (p);
     187    }
     188  }
     189  
     190  
     191  #pragma GCC diagnostic push
     192  /* Verify that -Wdangling-pointer works with #pragma diagnostic.  */
     193  #pragma GCC diagnostic ignored "-Wdangling-pointer"
     194  
     195  
     196  NOIPA void* nowarn_return_local_addr (void)
     197  {
     198    int a[] = { 1, 2, 3 };
     199    int *p = a;
     200  
     201    /* This is a likely bug but it's not really one of using a dangling
     202       pointer but rather of returning the address of a local variable
     203       which is diagnosed by -Wreturn-local-addr.  */
     204    return p;
     205  }
     206  
     207  NOIPA void* warn_return_local_addr (void)
     208  {
     209    int *p = 0;
     210    {
     211      int a[] = { 1, 2, 3 };
     212      sink (a);
     213      p = a;
     214    }
     215  
     216    /* Unlike the above case, here the pointer is dangling when it's
     217       used.  */
     218    return p;                   // { dg-warning "using dangling pointer 'p' to 'a'" "pr??????" { xfail *-*-* } }
     219  }
     220  
     221  
     222  NOIPA void* nowarn_return_alloca (int n)
     223  {
     224    int *p = (int*)alloca (n);
     225    sink (p);
     226  
     227    /* This is a likely bug but it's not really one of using a dangling
     228       pointer but rather of returning the address of a local variable
     229       which is diagnosed by -Wreturn-local-addr.  */
     230    return p;
     231  }
     232  
     233  
     234  NOIPA void nowarn_scalar_call_ignored (void *vp)
     235  {
     236    int *p;
     237    {
     238      int i;
     239      p = &i;
     240    }
     241    sink (p);
     242  }
     243  
     244  #pragma GCC diagnostic pop
     245  
     246  NOIPA void warn_scalar_call (void)
     247  {
     248    int *p;
     249    {
     250      int i;                    // { dg-message "'i' declared" "note" }
     251      p = &i;
     252    }
     253    // When the 'p' is optimized away it's not mentioned in the warning.
     254    sink (p);                   // { dg-warning "using \(a \)?dangling pointer \('p' \)?to 'i'" "array" }
     255  }
     256  
     257  
     258  NOIPA void warn_array_call (void)
     259  {
     260    int *p;
     261    {
     262      int a[] = { 1, 2, 3 };    // { dg-message "'a' declared" "note" }
     263      p = a;
     264    }
     265    sink (p);                   // { dg-warning "using \(a \)?dangling pointer \('p' \)?to 'a'" "array" }
     266  }
     267  
     268  
     269  NOIPA void* warn_array_return (void)
     270  {
     271    int *p;
     272    {
     273      int a[] = { 1, 2, 3 };    // { dg-message "'a' declared" "note" }
     274      p = a;
     275    }
     276  
     277    return p;                   // { dg-warning "using \(a \)?dangling pointer \('p' \)?to 'a'" "array" }
     278  }
     279  
     280  
     281  NOIPA void warn_pr63272_c1 (int i)
     282  {
     283    int *p = 0;
     284  
     285    if (i)
     286      {
     287        int k = i;              // { dg-message "'k' declared" "note" }
     288        p = &k;
     289      }
     290  
     291    sink (p ? *p : 0);          // { dg-warning "dangling pointer 'p' to 'k' may be used" }
     292  }
     293  
     294  
     295  NOIPA void warn_pr63272_c4 (void)
     296  {
     297    int *p = 0;
     298  
     299    {
     300      int b;                    // { dg-message "'b' declared" "note" }
     301      p = &b;
     302    }
     303  
     304    sink (p);                   // { dg-warning "using \(a \)?dangling pointer \('p' \)?to 'b'" "scalar" }
     305  }
     306  
     307  
     308  NOIPA void warn_cond_if (int i, int n)
     309  {
     310    int *p;
     311    if (i)
     312      {
     313        int a[] = { 1, 2 };     // { dg-message "'a' declared" "note" }
     314        sink (a);
     315        p = a;
     316      }
     317    else
     318     {
     319       int *b = (int*)malloc (n);
     320       sink (b);
     321       p = b;
     322     }
     323  
     324    sink (p);                   // { dg-warning "dangling pointer 'p' to 'a' may be used" }
     325  }
     326  
     327  
     328  NOIPA void warn_cond_else (int i, int n)
     329  {
     330    int *p;
     331    if (i)
     332      {
     333        int *a = (int*)malloc (n);
     334        sink (a);
     335        p = a;
     336      }
     337    else
     338     {
     339       int b[] = { 2, 3 };
     340       sink (b);
     341       p = b;
     342     }
     343  
     344    sink (p);                   // { dg-warning "dangling pointer 'p' to 'b' may be used" }
     345  }
     346  
     347  
     348  NOIPA void warn_cond_if_else (int i)
     349  {
     350    int *p;
     351    if (i)
     352      {
     353        int a[] = { 1, 2 };     // { dg-message "'a' declared" "note" }
     354        sink (a);
     355        p = a;
     356      }
     357    else
     358     {
     359       int b[] = { 3, 4 };      // { dg-message "'b' declared" "pr??????" { xfail *-*-* } }
     360       sink (b);
     361       p = b;
     362     }
     363  
     364    /* With a PHI with more than invalid argument, only one use is diagnosed
     365       because after the first diagnostic the code suppresses subsequent
     366       ones for the same use.  This needs to be fixed.  */
     367    sink (p);                   // { dg-warning "dangling pointer 'p' to 'a' may be used" }
     368                                // { dg-warning "dangling pointer 'p' to 'b' may be used" "pr??????" { xfail *-*-* } .-1 }
     369  }
     370  
     371  
     372  NOIPA void nowarn_gcc_i386 (int i)
     373  {
     374    // Regression test reduced from gcc's i386.c.
     375    char a[32], *p;
     376  
     377    if (i != 1)
     378      p = a;
     379    else
     380      p = 0;
     381  
     382    if (i == 2)
     383      sink (p);
     384    else
     385      {
     386        if (p)
     387  	{
     388  	  sink (p);
     389  	  return;
     390  	}
     391        sink (p);
     392      }
     393  }
     394  
     395  
     396  NOIPA void warn_memchr (char c1, char c2, char c3, char c4)
     397  {
     398    char *p = 0;
     399    {
     400      char a[] = { c1, c2, c3 };// { dg-message "'a' declared" "note" }
     401      p = (char*)memchr (a, c4, 3);
     402      if (!p)
     403        return;
     404    }
     405  
     406    sink (p);                   // { dg-warning "using dangling pointer 'p' to 'a'" }
     407  }
     408  
     409  
     410  NOIPA void warn_strchr (char c1, char c2, char c3, char c4)
     411  {
     412    char *p = 0;
     413    {
     414      char a[] = { c1, c2, c3 }; // { dg-message "'a' declared" "note" }
     415      p = (char*)strchr (a, c4);
     416      if (!p)
     417        return;
     418    }
     419  
     420    sink (p);                   // { dg-warning "using dangling pointer 'p' to 'a'" }
     421  }
     422  
     423  
     424  static inline int* return_arg (int *p)
     425  {
     426    return p;
     427  }
     428  
     429  NOIPA void warn_inline (int i1, int i2, int i3)
     430  {
     431    int *p;
     432    {
     433      int a[] = { i1, i2, i3 }; // { dg-message "'a' declared" "note" }
     434      p = return_arg (a);
     435    }
     436  
     437    sink (p);                   // { dg-warning "using \(a \)?dangling pointer \('p' \)?to 'a'" "inline" }
     438  }