authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 19:07:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 19:07:01-07:00
log69d4f55fbf816bf417dfab9c0e7525971922f166
tree9e6066b49ca1b3226f9579585e4acd37be70ce25
parent7ae6c2f33bf90147c5e2da558e633e40588e76bd

parseh: still produce output when not all types are known


1 files changed, 145 insertions(+), 58 deletions(-)

src/parseh.cpp+145-58
...@@ -22,9 +22,10 @@ struct Context {...@@ -22,9 +22,10 @@ struct Context {
22 bool warnings_on;22 bool warnings_on;
23 VisibMod visib_mod;23 VisibMod visib_mod;
24 AstNode *c_void_decl_node;24 AstNode *c_void_decl_node;
25 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
25};26};
2627
27static AstNode *type_node_from_qual_type(Context *c, QualType qt);28static AstNode *make_qual_type_node(Context *c, QualType qt);
2829
29static AstNode *create_node(Context *c, NodeType type) {30static AstNode *create_node(Context *c, NodeType type) {
30 AstNode *node = allocate<AstNode>(1);31 AstNode *node = allocate<AstNode>(1);
...@@ -43,12 +44,16 @@ static const char *decl_name(const Decl *decl) {...@@ -43,12 +44,16 @@ static const char *decl_name(const Decl *decl) {
43 return (const char *)named_decl->getName().bytes_begin();44 return (const char *)named_decl->getName().bytes_begin();
44}45}
4546
46static AstNode *create_typedef_node(Context *c, const char *new_name, const char *target_name) {47static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) {
48 if (!target_node) {
49 return nullptr;
50 }
47 AstNode *node = create_node(c, NodeTypeVariableDeclaration);51 AstNode *node = create_node(c, NodeTypeVariableDeclaration);
48 buf_init_from_str(&node->data.variable_declaration.symbol, new_name);52 buf_init_from_buf(&node->data.variable_declaration.symbol, new_name);
49 node->data.variable_declaration.is_const = true;53 node->data.variable_declaration.is_const = true;
50 node->data.variable_declaration.visib_mod = c->visib_mod;54 node->data.variable_declaration.visib_mod = c->visib_mod;
51 node->data.variable_declaration.expr = simple_type_node(c, target_name);55 node->data.variable_declaration.expr = target_node;
56 c->parse_h->var_list.append(node);
52 return node;57 return node;
53}58}
5459
...@@ -57,8 +62,9 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {...@@ -57,8 +62,9 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {
57 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))62 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))
58 {63 {
59 if (!c->c_void_decl_node) {64 if (!c->c_void_decl_node) {
60 c->c_void_decl_node = create_typedef_node(c, "c_void", "u8");65 c->c_void_decl_node = create_typedef_node(c, buf_create_from_str("c_void"),
61 c->parse_h->var_list.append(c->c_void_decl_node);66 simple_type_node(c, "u8"));
67 assert(c->c_void_decl_node);
62 }68 }
63 return simple_type_node(c, "c_void");69 return simple_type_node(c, "c_void");
64 } else {70 } else {
...@@ -67,13 +73,16 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {...@@ -67,13 +73,16 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {
67}73}
6874
69static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {75static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
76 if (!type_node) {
77 return nullptr;
78 }
70 AstNode *node = create_node(c, NodeTypePrefixOpExpr);79 AstNode *node = create_node(c, NodeTypePrefixOpExpr);
71 node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf;80 node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf;
72 node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node);81 node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node);
73 return node;82 return node;
74}83}
7584
76static AstNode *type_node(Context *c, const Type *ty) {85static AstNode *make_type_node(Context *c, const Type *ty) {
77 switch (ty->getTypeClass()) {86 switch (ty->getTypeClass()) {
78 case Type::Builtin:87 case Type::Builtin:
79 {88 {
...@@ -110,7 +119,6 @@ static AstNode *type_node(Context *c, const Type *ty) {...@@ -110,7 +119,6 @@ static AstNode *type_node(Context *c, const Type *ty) {
110 case BuiltinType::Double:119 case BuiltinType::Double:
111 return simple_type_node(c, "f64");120 return simple_type_node(c, "f64");
112 case BuiltinType::LongDouble:121 case BuiltinType::LongDouble:
113 return simple_type_node(c, "f128");
114 case BuiltinType::WChar_U:122 case BuiltinType::WChar_U:
115 case BuiltinType::Char16:123 case BuiltinType::Char16:
116 case BuiltinType::Char32:124 case BuiltinType::Char32:
...@@ -137,7 +145,10 @@ static AstNode *type_node(Context *c, const Type *ty) {...@@ -137,7 +145,10 @@ static AstNode *type_node(Context *c, const Type *ty) {
137 case BuiltinType::UnknownAny:145 case BuiltinType::UnknownAny:
138 case BuiltinType::BuiltinFn:146 case BuiltinType::BuiltinFn:
139 case BuiltinType::ARCUnbridgedCast:147 case BuiltinType::ARCUnbridgedCast:
140 zig_panic("TODO - make error for these types");148 if (c->warnings_on) {
149 fprintf(stderr, "missed a builtin type\n");
150 }
151 return nullptr;
141 }152 }
142 break;153 break;
143 }154 }
...@@ -145,17 +156,53 @@ static AstNode *type_node(Context *c, const Type *ty) {...@@ -145,17 +156,53 @@ static AstNode *type_node(Context *c, const Type *ty) {
145 {156 {
146 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);157 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
147 QualType child_qt = pointer_ty->getPointeeType();158 QualType child_qt = pointer_ty->getPointeeType();
148 AstNode *type_node = type_node_from_qual_type(c, child_qt);159 AstNode *type_node = make_qual_type_node(c, child_qt);
149 return pointer_to_type(c, type_node, child_qt.isConstQualified());160 return pointer_to_type(c, type_node, child_qt.isConstQualified());
150 }161 }
151 case Type::Typedef:162 case Type::Typedef:
152 {163 {
153 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);164 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
154 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();165 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
155 const char *type_name = buf_ptr(buf_create_from_str(decl_name(typedef_decl)));166 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
156 return simple_type_node(c, type_name);167 if (buf_eql_str(type_name, "uint8_t")) {
168 return simple_type_node(c, "u8");
169 } else if (buf_eql_str(type_name, "int8_t")) {
170 return simple_type_node(c, "i8");
171 } else if (buf_eql_str(type_name, "uint16_t")) {
172 return simple_type_node(c, "u16");
173 } else if (buf_eql_str(type_name, "int16_t")) {
174 return simple_type_node(c, "i16");
175 } else if (buf_eql_str(type_name, "uint32_t")) {
176 return simple_type_node(c, "u32");
177 } else if (buf_eql_str(type_name, "int32_t")) {
178 return simple_type_node(c, "i32");
179 } else if (buf_eql_str(type_name, "uint64_t")) {
180 return simple_type_node(c, "u64");
181 } else if (buf_eql_str(type_name, "int64_t")) {
182 return simple_type_node(c, "i64");
183 } else if (buf_eql_str(type_name, "intptr_t")) {
184 return simple_type_node(c, "isize");
185 } else if (buf_eql_str(type_name, "uintptr_t")) {
186 return simple_type_node(c, "usize");
187 } else {
188 auto entry = c->type_table.maybe_get(type_name);
189 if (entry) {
190 return simple_type_node(c, buf_ptr(type_name));
191 } else {
192 return nullptr;
193 }
194 }
157 }195 }
196 case Type::Elaborated:
197 if (c->warnings_on) {
198 fprintf(stderr, "ignoring elaborated type\n");
199 }
200 return nullptr;
158 case Type::FunctionProto:201 case Type::FunctionProto:
202 if (c->warnings_on) {
203 fprintf(stderr, "ignoring function type\n");
204 }
205 return nullptr;
159 case Type::Record:206 case Type::Record:
160 case Type::Enum:207 case Type::Enum:
161 case Type::BlockPointer:208 case Type::BlockPointer:
...@@ -178,7 +225,6 @@ static AstNode *type_node(Context *c, const Type *ty) {...@@ -178,7 +225,6 @@ static AstNode *type_node(Context *c, const Type *ty) {
178 case Type::TypeOf:225 case Type::TypeOf:
179 case Type::Decltype:226 case Type::Decltype:
180 case Type::UnaryTransform:227 case Type::UnaryTransform:
181 case Type::Elaborated:
182 case Type::Attributed:228 case Type::Attributed:
183 case Type::TemplateTypeParm:229 case Type::TemplateTypeParm:
184 case Type::SubstTemplateTypeParm:230 case Type::SubstTemplateTypeParm:
...@@ -194,12 +240,90 @@ static AstNode *type_node(Context *c, const Type *ty) {...@@ -194,12 +240,90 @@ static AstNode *type_node(Context *c, const Type *ty) {
194 case Type::Complex:240 case Type::Complex:
195 case Type::ObjCObjectPointer:241 case Type::ObjCObjectPointer:
196 case Type::Atomic:242 case Type::Atomic:
197 zig_panic("TODO - make error for type: %s", ty->getTypeClassName());243 if (c->warnings_on) {
244 fprintf(stderr, "missed a '%s' type\n", ty->getTypeClassName());
245 }
246 return nullptr;
198 }247 }
199}248}
200249
201static AstNode *type_node_from_qual_type(Context *c, QualType qt) {250static AstNode *make_qual_type_node(Context *c, QualType qt) {
202 return type_node(c, qt.getTypePtr());251 return make_type_node(c, qt.getTypePtr());
252}
253
254static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
255 AstNode *node = create_node(c, NodeTypeFnProto);
256 node->data.fn_proto.is_extern = true;
257 node->data.fn_proto.visib_mod = c->visib_mod;
258 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
259 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));
260
261 int arg_count = fn_decl->getNumParams();
262 bool all_ok = true;
263 for (int i = 0; i < arg_count; i += 1) {
264 const ParmVarDecl *param = fn_decl->getParamDecl(i);
265 AstNode *param_decl_node = create_node(c, NodeTypeParamDecl);
266 const char *name = decl_name(param);
267 if (strlen(name) == 0) {
268 name = buf_ptr(buf_sprintf("arg%d", i));
269 }
270 buf_init_from_str(&param_decl_node->data.param_decl.name, name);
271 QualType qt = param->getOriginalType();
272 param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified();
273 param_decl_node->data.param_decl.type = make_qual_type_node(c, qt);
274 if (!param_decl_node->data.param_decl.type) {
275 all_ok = false;
276 break;
277 }
278
279 node->data.fn_proto.params.append(param_decl_node);
280 }
281
282 if (fn_decl->isNoReturn()) {
283 node->data.fn_proto.return_type = simple_type_node(c, "unreachable");
284 } else {
285 node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType());
286 }
287
288 if (!node->data.fn_proto.return_type) {
289 all_ok = false;
290 }
291 if (!all_ok) {
292 // not all the types could be resolved, so we give up on the function decl
293 if (c->warnings_on) {
294 fprintf(stderr, "skipping function %s", buf_ptr(&node->data.fn_proto.name));
295 }
296 return;
297 }
298
299 c->parse_h->fn_list.append(node);
300
301}
302
303static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
304 QualType child_qt = typedef_decl->getUnderlyingType();
305 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
306
307 if (buf_eql_str(type_name, "uint8_t") ||
308 buf_eql_str(type_name, "int8_t") ||
309 buf_eql_str(type_name, "uint16_t") ||
310 buf_eql_str(type_name, "int16_t") ||
311 buf_eql_str(type_name, "uint32_t") ||
312 buf_eql_str(type_name, "int32_t") ||
313 buf_eql_str(type_name, "uint64_t") ||
314 buf_eql_str(type_name, "int64_t") ||
315 buf_eql_str(type_name, "intptr_t") ||
316 buf_eql_str(type_name, "uintptr_t"))
317 {
318 // special case we can just use the builtin types
319 return;
320 }
321
322 AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt));
323
324 if (node) {
325 c->type_table.put(type_name, true);
326 }
203}327}
204328
205static bool decl_visitor(void *context, const Decl *decl) {329static bool decl_visitor(void *context, const Decl *decl) {
...@@ -207,49 +331,11 @@ static bool decl_visitor(void *context, const Decl *decl) {...@@ -207,49 +331,11 @@ static bool decl_visitor(void *context, const Decl *decl) {
207331
208 switch (decl->getKind()) {332 switch (decl->getKind()) {
209 case Decl::Function:333 case Decl::Function:
210 {334 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));
211 const FunctionDecl *fn_decl = static_cast<const FunctionDecl*>(decl);335 break;
212 AstNode *node = create_node(c, NodeTypeFnProto);
213 node->data.fn_proto.is_extern = true;
214 node->data.fn_proto.visib_mod = c->visib_mod;
215 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
216 buf_init_from_str(&node->data.fn_proto.name, decl_name(decl));
217
218 int arg_count = fn_decl->getNumParams();
219 for (int i = 0; i < arg_count; i += 1) {
220 const ParmVarDecl *param = fn_decl->getParamDecl(i);
221 AstNode *param_decl_node = create_node(c, NodeTypeParamDecl);
222 const char *name = decl_name(param);
223 if (strlen(name) == 0) {
224 name = buf_ptr(buf_sprintf("arg%d", i));
225 }
226 buf_init_from_str(&param_decl_node->data.param_decl.name, name);
227 QualType qt = param->getOriginalType();
228 param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified();
229 param_decl_node->data.param_decl.type = type_node_from_qual_type(c, qt);
230 node->data.fn_proto.params.append(param_decl_node);
231 }
232
233 if (fn_decl->isNoReturn()) {
234 node->data.fn_proto.return_type = simple_type_node(c, "unreachable");
235 } else {
236 node->data.fn_proto.return_type = type_node_from_qual_type(c, fn_decl->getReturnType());
237 }
238
239 c->parse_h->fn_list.append(node);
240
241 break;
242 }
243 /*
244 case Decl::Typedef:336 case Decl::Typedef:
245 {337 visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
246 AstNode *node = create_node(c, NodeTypeVariableDeclaration);338 break;
247 node->data.variable_declaration.is_const = true;
248 buf_init_from_str(&node->data.variable_declaration.symbol, decl_name(decl));
249
250 break;
251 }
252 */
253 default:339 default:
254 if (c->warnings_on) {340 if (c->warnings_on) {
255 fprintf(stderr, "ignoring %s\n", decl->getDeclKindName());341 fprintf(stderr, "ignoring %s\n", decl->getDeclKindName());
...@@ -282,6 +368,7 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {...@@ -282,6 +368,7 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
282 Context context = {0};368 Context context = {0};
283 Context *c = &context;369 Context *c = &context;
284 c->parse_h = parse_h;370 c->parse_h = parse_h;
371 c->type_table.init(64);
285372
286 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");373 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
287 if (ZIG_PARSEH_CFLAGS) {374 if (ZIG_PARSEH_CFLAGS) {