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