1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2019, Joyent, Inc.
14 */
15
16 /*
17 * Check that we properly understand reference types and can walk through them
18 * as well as generate them.
19 */
20
21 #include "check-common.h"
22
23 static check_number_t check_base[] = {
24 { "char", CTF_K_INTEGER, CTF_INT_SIGNED | CTF_INT_CHAR, 0, 8 },
25 { "int", CTF_K_INTEGER, CTF_INT_SIGNED, 0, 32 },
26 { "float", CTF_K_FLOAT, CTF_FP_SINGLE, 0, 32 },
27 { NULL }
28 };
29
30 static check_symbol_t check_syms[] = {
31 { "a", "int" },
32 { "aa", "test_int_t" },
33 { "b", "const short" },
34 { "c", "volatile float" },
35 { "d", "int *" },
36 { "dd", "int **" },
37 { "ddd", "int ***" },
38 { "e", "test_int_t *" },
39 { "ce", "const test_int_t *" },
40 { "ve", "volatile test_int_t *" },
41 { "cve", "const volatile test_int_t *" },
42 { "f", "int *const *" },
43 { "g", "const char *const" },
44 { NULL },
45 };
46
47 static check_descent_t check_descent_aa[] = {
48 { "test_int_t", CTF_K_TYPEDEF },
49 { "int", CTF_K_INTEGER },
50 { NULL }
51 };
52
53 static check_descent_t check_descent_b[] = {
54 { "const short", CTF_K_CONST },
55 { "short", CTF_K_INTEGER },
56 { NULL }
57 };
58
59 static check_descent_t check_descent_c[] = {
60 { "volatile float", CTF_K_VOLATILE },
61 { "float", CTF_K_FLOAT },
62 { NULL }
63 };
64
65 static check_descent_t check_descent_d[] = {
66 { "int *", CTF_K_POINTER },
67 { "int", CTF_K_INTEGER },
68 { NULL }
69 };
70
71 static check_descent_t check_descent_dd[] = {
72 { "int **", CTF_K_POINTER },
73 { "int *", CTF_K_POINTER },
74 { "int", CTF_K_INTEGER },
75 { NULL }
76 };
77
78 static check_descent_t check_descent_ddd[] = {
79 { "int ***", CTF_K_POINTER },
80 { "int **", CTF_K_POINTER },
81 { "int *", CTF_K_POINTER },
82 { "int", CTF_K_INTEGER },
83 { NULL }
84 };
85
86 static check_descent_t check_descent_e[] = {
87 { "test_int_t *", CTF_K_POINTER },
88 { "test_int_t", CTF_K_TYPEDEF },
89 { "int", CTF_K_INTEGER },
90 { NULL },
91 };
92
93 static check_descent_t check_descent_ce[] = {
94 { "const test_int_t *", CTF_K_POINTER },
95 { "const test_int_t", CTF_K_CONST },
96 { "test_int_t", CTF_K_TYPEDEF },
97 { "int", CTF_K_INTEGER },
98 { NULL },
99 };
100
101 static check_descent_t check_descent_ve[] = {
102 { "volatile test_int_t *", CTF_K_POINTER},
103 { "volatile test_int_t", CTF_K_VOLATILE },
104 { "test_int_t", CTF_K_TYPEDEF },
105 { "int", CTF_K_INTEGER },
106 { NULL }
107 };
108
109 static check_descent_t check_descent_cve[] = {
110 { "const volatile test_int_t *", CTF_K_POINTER },
111 { "const volatile test_int_t", CTF_K_CONST },
112 { "volatile test_int_t", CTF_K_VOLATILE },
113 { "test_int_t", CTF_K_TYPEDEF },
114 { "int", CTF_K_INTEGER },
115 { NULL }
116 };
117
118 static check_descent_t check_descent_f[] = {
119 { "int *const *", CTF_K_POINTER },
120 { "int *const", CTF_K_CONST },
121 { "int *", CTF_K_POINTER },
122 { "int", CTF_K_INTEGER },
123 { NULL }
124 };
125
126 static check_descent_t check_descent_g[] = {
127 { "const char *const", CTF_K_CONST },
128 { "const char *", CTF_K_POINTER },
129 { "const char", CTF_K_CONST },
130 { "char", CTF_K_INTEGER },
131 { NULL }
132 };
133
134 static check_descent_test_t descents[] = {
135 { "aa", check_descent_aa },
136 { "b", check_descent_b },
137 { "c", check_descent_c },
138 { "d", check_descent_d },
139 { "dd", check_descent_dd },
140 { "ddd", check_descent_ddd },
141 { "e", check_descent_e },
142 { "ce", check_descent_ce },
143 { "ve", check_descent_ve },
144 { "cve", check_descent_cve },
145 { "f", check_descent_f },
146 { "g", check_descent_g },
147 { NULL }
148 };
149
150 static check_descent_t check_descent_cvh_gcc4[] = {
151 { "const volatile foo_t *", CTF_K_POINTER },
152 { "const volatile foo_t", CTF_K_CONST },
153 { "volatile foo_t", CTF_K_VOLATILE },
154 { "foo_t", CTF_K_TYPEDEF },
155 { "int *const *", CTF_K_POINTER },
156 { "int *const", CTF_K_CONST },
157 { "int *", CTF_K_POINTER },
158 { "int", CTF_K_INTEGER },
159 { NULL }
160 };
161
162 static check_descent_t check_descent_cvh_gcc7[] = {
163 { "volatile const foo_t *", CTF_K_POINTER },
164 { "volatile const foo_t", CTF_K_VOLATILE },
165 { "const foo_t", CTF_K_CONST },
166 { "foo_t", CTF_K_TYPEDEF },
167 { "int *const *", CTF_K_POINTER },
168 { "int *const", CTF_K_CONST },
169 { "int *", CTF_K_POINTER },
170 { "int", CTF_K_INTEGER },
171 { NULL }
172 };
173
174 /*
175 * GCC versions differ in how they order qualifiers, which is a shame for
176 * round-tripping; but as they're clearly both valid, we should cope. We'll
177 * just insist that at least one of these checks passes.
178 */
179 static check_descent_test_t alt_descents[] = {
180 { "cvh", check_descent_cvh_gcc4 },
181 { "cvh", check_descent_cvh_gcc7 },
182 };
183
184 int
main(int argc,char * argv[])185 main(int argc, char *argv[])
186 {
187 int i, ret = 0;
188
189 if (argc < 2) {
190 errx(EXIT_FAILURE, "missing test files");
191 }
192
193 for (i = 1; i < argc; i++) {
194 ctf_file_t *fp;
195 int alt_ok = 0;
196 uint_t d;
197
198 if ((fp = ctf_open(argv[i], &ret)) == NULL) {
199 warnx("failed to open %s: %s", argv[i],
200 ctf_errmsg(ret));
201 ret = EXIT_FAILURE;
202 continue;
203 }
204
205 if (!ctftest_check_numbers(fp, check_base))
206 ret = EXIT_FAILURE;
207 if (!ctftest_check_symbols(fp, check_syms))
208 ret = EXIT_FAILURE;
209 for (d = 0; descents[d].cdt_sym != NULL; d++) {
210 if (!ctftest_check_descent(descents[d].cdt_sym, fp,
211 descents[d].cdt_tests, B_FALSE)) {
212 ret = EXIT_FAILURE;
213 }
214 }
215
216 for (d = 0; alt_descents[d].cdt_sym != NULL; d++) {
217 if (ctftest_check_descent(alt_descents[d].cdt_sym, fp,
218 alt_descents[d].cdt_tests, B_TRUE)) {
219 alt_ok = 1;
220 break;
221 }
222 }
223
224 if (!alt_ok) {
225 warnx("all descents failed for %s",
226 alt_descents[0].cdt_sym);
227 ret = EXIT_FAILURE;
228 }
229
230 ctf_close(fp);
231 }
232
233 return (ret);
234 }
235