aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/analyzer/pr103892.c
blob: a17c3b7e119e12bc53a304a8456059a3cc188570 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* { dg-additional-options "-O2 -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */

/* C only: C++ FE optimizes argstr_get_word completely away
   and therefore the number of SN diminishes compared to C,
   making the analysis bails out early.  */

extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__));

enum pipecmd_tag
{
 PIPECMD_PROCESS,
 PIPECMD_SEQUENCE
};

struct pipecmd {
 enum pipecmd_tag tag;
 union pipecmd_union_t {
  struct pipecmd_process {
   int argc;
   int argv_max;
   char **argv;
  } process;
  struct pipecmd_sequence {
   int ncommands;
   int commands_max;
   struct pipecmd **commands;
  } sequence;
 } u;
};

#ifdef __cplusplus
typedef pipecmd::pipecmd_union_t::pipecmd_process pipecmd_process_t;
typedef pipecmd::pipecmd_union_t::pipecmd_sequence pipecmd_sequence_t;
#else
typedef struct pipecmd_process pipecmd_process_t;
typedef struct pipecmd_sequence pipecmd_sequence_t;
#endif

static char *argstr_get_word (const char **argstr)
{
 while (**argstr) { /* { dg-warning "infinite loop" } */
  switch (**argstr) {
   case ' ':
   case '\t':
    return (char *) ((void *) 0);
  }
 }
 return (char *) ((void *) 0);
}

struct pipecmd *pipecmd_new_argstr (const char *argstr)
{
 argstr_get_word (&argstr);
 return (struct pipecmd *) ((void *) 0);
}

void pipecmd_free (struct pipecmd *cmd)
{
 int i;

 if (!cmd)
  return;

 switch (cmd->tag) {
  case PIPECMD_PROCESS: {
   pipecmd_process_t *cmdp = &cmd->u.process;

   for (i = 0; i < cmdp->argc; ++i)
    free (cmdp->argv[i]);
   free (cmdp->argv);

   break;
  }

  case PIPECMD_SEQUENCE: {
   pipecmd_sequence_t *cmds = &cmd->u.sequence;

   for (i = 0; i < cmds->ncommands; ++i)
    pipecmd_free (cmds->commands[i]);
   free (cmds->commands);

   break;
  }
 }

 free (cmd);
}