1  /* Test various diagnostics of ill-formed constructs involving labels.  */
       2  /* { dg-do compile } */
       3  /* { dg-options "-Wunused" } */
       4  
       5  extern void dummy(void);
       6  
       7  /* labels must be defined */
       8  void a(void)
       9  {
      10    goto l;   /* { dg-error "used but not defined" "no label" } */
      11  }
      12  
      13  /* warnings for labels defined but not used, or declared but not defined */
      14  void b(void)
      15  {
      16    __label__ l;
      17   l:  /* { dg-warning "defined but not used"  "no goto 1" } */
      18   m:  /* { dg-warning "defined but not used"  "no goto 2" } */
      19    dummy();
      20  }
      21  
      22  void c(void)
      23  {
      24    __label__ l;  /* { dg-warning "declared but not defined" "only __label__" } */
      25    dummy();
      26  }
      27  
      28  /* can't have two labels with the same name in the same function */
      29  void d(void)
      30  {
      31   l: dummy();  /* { dg-message "note: previous definition" "prev def same scope" } */
      32   l: dummy();  /* { dg-error "duplicate label" "dup label same scope" } */
      33   goto l;
      34  }
      35  
      36  /* even at different scopes */
      37  void e(void)
      38  {
      39   l: dummy();	/* { dg-message "note: previous definition"  "prev def diff scope" } */
      40    {
      41    l: dummy();	/* { dg-error "duplicate label" "dup label diff scope" } */
      42    }
      43    goto l;
      44  }
      45  
      46  /* but, with __label__, you can */
      47  void f(void)
      48  {
      49   l: dummy();
      50    {
      51      __label__ l;
      52      l: dummy();	  /* { dg-warning "defined but not used" "unused shadow 1" } */
      53    };
      54    goto l;  /* this reaches the outer l */
      55  }
      56  
      57  /* a __label__ is not visible outside its scope */
      58  void g(void)
      59  {
      60    dummy();
      61    {
      62      __label__ l;
      63      l: dummy();
      64      goto l;
      65    }
      66    goto l;  /* { dg-error "used but not defined" "label ref out of scope" } */
      67  }
      68  
      69  /* __label__ can appear at top level of a function, too...
      70     ... but doesn't provide a definition of the label */
      71  void h(void)
      72  {
      73    __label__ l;
      74    dummy ();
      75  
      76    goto l;  /* { dg-error "used but not defined" "used, only __label__" } */
      77  }
      78  
      79  /* A nested function may not goto a label outside itself  */
      80  void i(void)
      81  {
      82    auto void nest(void);
      83  
      84   l: nest();
      85    
      86    void nest(void)
      87      {
      88        goto l;  /* { dg-error "used but not defined" "nest use outer label" } */
      89      }
      90  
      91    goto l; /* reaches the outer l */
      92  }
      93  
      94  /* which means that a nested function may have its own label with the
      95     same name as the outer function */
      96  void j(void)
      97  {
      98    auto void nest(void);
      99  
     100   l: nest();
     101    
     102    void nest(void)
     103      {
     104      l: dummy(); /* { dg-warning "defined but not used" "nest label same name" } */
     105      }
     106  
     107    goto l; /* reaches the outer l */
     108  }
     109  
     110  /* and, turnabout, an outer function may not goto a label in a nested
     111     function */
     112  void k(void)
     113  {
     114    void nest(void)
     115    {
     116    l: dummy();  /* { dg-warning "defined but not used" "outer use nest label" } */
     117    }
     118  
     119    goto l; /* { dg-error "used but not defined" "outer use nest label" } */
     120    nest();
     121  }
     122  
     123  /* not even with __label__ */
     124  void l(void)
     125  {
     126    void nest(void)
     127    {
     128      __label__ l;
     129    l: dummy(); /* { dg-warning "defined but not used" "outer use nest __label__" } */
     130    }
     131  
     132    goto l; /* { dg-error "used but not defined" "outer use nest __label__" } */
     133    nest();
     134  }
     135  
     136  
     137  /* but if the outer label is declared with __label__, then a nested
     138     function can goto that label (accomplishing a longjmp) */
     139  void m(void)
     140  {
     141    __label__ l;
     142    void nest(void) { goto l; }
     143    nest();
     144    dummy();
     145   l:;
     146  }
     147  
     148  /* and that means the nested function cannot have its own label with
     149     the same name as an outer label declared with __label__ */
     150  
     151  void n(void)
     152  {
     153    __label__ l; /* { dg-message "note: previous declaration" "outer label decl" } */
     154    void nest(void)
     155      {
     156      l: goto l;  /* { dg-error "duplicate label" "inner label defn" } */
     157      }
     158  
     159   l:
     160    nest();
     161  }
     162  
     163  /* unless the nested function uses __label__ too!  */
     164  void o(void)
     165  {
     166    __label__ l;
     167    void nest(void)
     168      {
     169        __label__ l;
     170      l: goto l;
     171      }
     172  
     173   l: goto l;
     174   nest();
     175  }