Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/libctf/ctf-decl.c
Line
Count
Source (jump to first uncovered line)
1
/* C declarator syntax glue.
2
   Copyright (C) 2019-2025 Free Software Foundation, Inc.
3
4
   This file is part of libctf.
5
6
   libctf is free software; you can redistribute it and/or modify it under
7
   the terms of the GNU General Public License as published by the Free
8
   Software Foundation; either version 3, or (at your option) any later
9
   version.
10
11
   This program is distributed in the hope that it will be useful, but
12
   WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
   See the GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; see the file COPYING.  If not see
18
   <http://www.gnu.org/licenses/>.  */
19
20
/* CTF Declaration Stack
21
22
   In order to implement ctf_type_name(), we must convert a type graph back
23
   into a C type declaration.  Unfortunately, a type graph represents a storage
24
   class ordering of the type whereas a type declaration must obey the C rules
25
   for operator precedence, and the two orderings are frequently in conflict.
26
   For example, consider these CTF type graphs and their C declarations:
27
28
   CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
29
   CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]
30
31
   In each case, parentheses are used to raise operator * to higher lexical
32
   precedence, so the string form of the C declaration cannot be constructed by
33
   walking the type graph links and forming the string from left to right.
34
35
   The functions in this file build a set of stacks from the type graph nodes
36
   corresponding to the C operator precedence levels in the appropriate order.
37
   The code in ctf_type_name() can then iterate over the levels and nodes in
38
   lexical precedence order and construct the final C declaration string.  */
39
40
#include <ctf-impl.h>
41
#include <string.h>
42
43
void
44
ctf_decl_init (ctf_decl_t *cd)
45
0
{
46
0
  int i;
47
48
0
  memset (cd, 0, sizeof (ctf_decl_t));
49
50
0
  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
51
0
    cd->cd_order[i] = CTF_PREC_BASE - 1;
52
53
0
  cd->cd_qualp = CTF_PREC_BASE;
54
0
  cd->cd_ordp = CTF_PREC_BASE;
55
0
}
56
57
void
58
ctf_decl_fini (ctf_decl_t *cd)
59
0
{
60
0
  ctf_decl_node_t *cdp, *ndp;
61
0
  int i;
62
63
0
  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
64
0
    {
65
0
      for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp)
66
0
  {
67
0
    ndp = ctf_list_next (cdp);
68
0
    free (cdp);
69
0
  }
70
0
    }
71
0
  free (cd->cd_buf);
72
0
}
73
74
void
75
ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
76
0
{
77
0
  ctf_decl_node_t *cdp;
78
0
  ctf_decl_prec_t prec;
79
0
  uint32_t kind, n = 1;
80
0
  int is_qual = 0;
81
82
0
  const ctf_type_t *tp;
83
0
  ctf_arinfo_t ar;
84
85
0
  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
86
0
    {
87
0
      cd->cd_err = fp->ctf_errno;
88
0
      return;
89
0
    }
90
91
0
  switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info))
92
0
    {
93
0
    case CTF_K_ARRAY:
94
0
      (void) ctf_array_info (fp, type, &ar);
95
0
      ctf_decl_push (cd, fp, ar.ctr_contents);
96
0
      n = ar.ctr_nelems;
97
0
      prec = CTF_PREC_ARRAY;
98
0
      break;
99
100
0
    case CTF_K_TYPEDEF:
101
0
      if (ctf_strptr (fp, tp->ctt_name)[0] == '\0')
102
0
  {
103
0
    ctf_decl_push (cd, fp, tp->ctt_type);
104
0
    return;
105
0
  }
106
0
      prec = CTF_PREC_BASE;
107
0
      break;
108
109
0
    case CTF_K_FUNCTION:
110
0
      ctf_decl_push (cd, fp, tp->ctt_type);
111
0
      prec = CTF_PREC_FUNCTION;
112
0
      break;
113
114
0
    case CTF_K_POINTER:
115
0
      ctf_decl_push (cd, fp, tp->ctt_type);
116
0
      prec = CTF_PREC_POINTER;
117
0
      break;
118
119
0
    case CTF_K_SLICE:
120
      /* Slices themselves have no print representation and should not appear in
121
   the decl stack.  */
122
0
      ctf_decl_push (cd, fp, ctf_type_reference (fp, type));
123
0
      return;
124
125
0
    case CTF_K_VOLATILE:
126
0
    case CTF_K_CONST:
127
0
    case CTF_K_RESTRICT:
128
0
      ctf_decl_push (cd, fp, tp->ctt_type);
129
0
      prec = cd->cd_qualp;
130
0
      is_qual++;
131
0
      break;
132
133
0
    default:
134
0
      prec = CTF_PREC_BASE;
135
0
    }
136
137
0
  if ((cdp = malloc (sizeof (ctf_decl_node_t))) == NULL)
138
0
    {
139
0
      cd->cd_err = EAGAIN;
140
0
      return;
141
0
    }
142
143
0
  cdp->cd_type = type;
144
0
  cdp->cd_kind = kind;
145
0
  cdp->cd_n = n;
146
147
0
  if (ctf_list_next (&cd->cd_nodes[prec]) == NULL)
148
0
    cd->cd_order[prec] = cd->cd_ordp++;
149
150
  /* Reset cd_qualp to the highest precedence level that we've seen so
151
     far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).  */
152
153
0
  if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
154
0
    cd->cd_qualp = prec;
155
156
  /* By convention qualifiers of base types precede the type specifier (e.g.
157
     const int vs. int const) even though the two forms are equivalent.  */
158
159
0
  if (is_qual && prec == CTF_PREC_BASE)
160
0
    ctf_list_prepend (&cd->cd_nodes[prec], cdp);
161
0
  else
162
0
    ctf_list_append (&cd->cd_nodes[prec], cdp);
163
0
}
164
165
_libctf_printflike_ (2, 3)
166
void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...)
167
0
{
168
0
  va_list ap;
169
0
  char *str;
170
0
  int n;
171
172
0
  if (cd->cd_enomem)
173
0
    return;
174
175
0
  va_start (ap, format);
176
0
  n = vasprintf (&str, format, ap);
177
0
  va_end (ap);
178
179
0
  if (n > 0)
180
0
    {
181
0
      char *newbuf;
182
0
      if ((newbuf = ctf_str_append (cd->cd_buf, str)) != NULL)
183
0
  cd->cd_buf = newbuf;
184
0
    }
185
186
  /* Sticky error condition.  */
187
0
  if (n < 0 || cd->cd_buf == NULL)
188
0
    {
189
0
      free (cd->cd_buf);
190
0
      cd->cd_buf = NULL;
191
0
      cd->cd_enomem = 1;
192
0
    }
193
194
0
  free (str);
195
0
}
196
197
char *ctf_decl_buf (ctf_decl_t *cd)
198
0
{
199
0
  char *buf = cd->cd_buf;
200
0
  cd->cd_buf = NULL;
201
0
  return buf;
202
0
}