| ... | ... | @@ -22,9 +22,10 @@ struct Context { |
| 22 | 22 | bool warnings_on; |
| 23 | 23 | VisibMod visib_mod; |
| 24 | 24 | AstNode *c_void_decl_node; |
| 25 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table; |
| 25 | 26 | }; |
| 26 | 27 | |
| 27 | | static AstNode *type_node_from_qual_type(Context *c, QualType qt); |
| 28 | static AstNode *make_qual_type_node(Context *c, QualType qt); |
| 28 | 29 | |
| 29 | 30 | static AstNode *create_node(Context *c, NodeType type) { |
| 30 | 31 | AstNode *node = allocate<AstNode>(1); |
| ... | ... | @@ -43,12 +44,16 @@ static const char *decl_name(const Decl *decl) { |
| 43 | 44 | return (const char *)named_decl->getName().bytes_begin(); |
| 44 | 45 | } |
| 45 | 46 | |
| 46 | | static AstNode *create_typedef_node(Context *c, const char *new_name, const char *target_name) { |
| 47 | static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) { |
| 48 | if (!target_node) { |
| 49 | return nullptr; |
| 50 | } |
| 47 | 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 | 53 | node->data.variable_declaration.is_const = true; |
| 50 | 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 | 57 | return node; |
| 53 | 58 | } |
| 54 | 59 | |
| ... | ... | @@ -57,8 +62,9 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { |
| 57 | 62 | buf_eql_str(&type_node->data.symbol_expr.symbol, "void")) |
| 58 | 63 | { |
| 59 | 64 | if (!c->c_void_decl_node) { |
| 60 | | c->c_void_decl_node = create_typedef_node(c, "c_void", "u8"); |
| 61 | | c->parse_h->var_list.append(c->c_void_decl_node); |
| 65 | c->c_void_decl_node = create_typedef_node(c, buf_create_from_str("c_void"), |
| 66 | simple_type_node(c, "u8")); |
| 67 | assert(c->c_void_decl_node); |
| 62 | 68 | } |
| 63 | 69 | return simple_type_node(c, "c_void"); |
| 64 | 70 | } else { |
| ... | ... | @@ -67,13 +73,16 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) { |
| 67 | 73 | } |
| 68 | 74 | |
| 69 | 75 | static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { |
| 76 | if (!type_node) { |
| 77 | return nullptr; |
| 78 | } |
| 70 | 79 | AstNode *node = create_node(c, NodeTypePrefixOpExpr); |
| 71 | 80 | node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf; |
| 72 | 81 | node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node); |
| 73 | 82 | return node; |
| 74 | 83 | } |
| 75 | 84 | |
| 76 | | static AstNode *type_node(Context *c, const Type *ty) { |
| 85 | static AstNode *make_type_node(Context *c, const Type *ty) { |
| 77 | 86 | switch (ty->getTypeClass()) { |
| 78 | 87 | case Type::Builtin: |
| 79 | 88 | { |
| ... | ... | @@ -110,7 +119,6 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 110 | 119 | case BuiltinType::Double: |
| 111 | 120 | return simple_type_node(c, "f64"); |
| 112 | 121 | case BuiltinType::LongDouble: |
| 113 | | return simple_type_node(c, "f128"); |
| 114 | 122 | case BuiltinType::WChar_U: |
| 115 | 123 | case BuiltinType::Char16: |
| 116 | 124 | case BuiltinType::Char32: |
| ... | ... | @@ -137,7 +145,10 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 137 | 145 | case BuiltinType::UnknownAny: |
| 138 | 146 | case BuiltinType::BuiltinFn: |
| 139 | 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 | 153 | break; |
| 143 | 154 | } |
| ... | ... | @@ -145,17 +156,53 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 145 | 156 | { |
| 146 | 157 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 147 | 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 | 160 | return pointer_to_type(c, type_node, child_qt.isConstQualified()); |
| 150 | 161 | } |
| 151 | 162 | case Type::Typedef: |
| 152 | 163 | { |
| 153 | 164 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); |
| 154 | 165 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); |
| 155 | | const char *type_name = buf_ptr(buf_create_from_str(decl_name(typedef_decl))); |
| 156 | | return simple_type_node(c, type_name); |
| 166 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); |
| 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 | 201 | case Type::FunctionProto: |
| 202 | if (c->warnings_on) { |
| 203 | fprintf(stderr, "ignoring function type\n"); |
| 204 | } |
| 205 | return nullptr; |
| 159 | 206 | case Type::Record: |
| 160 | 207 | case Type::Enum: |
| 161 | 208 | case Type::BlockPointer: |
| ... | ... | @@ -178,7 +225,6 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 178 | 225 | case Type::TypeOf: |
| 179 | 226 | case Type::Decltype: |
| 180 | 227 | case Type::UnaryTransform: |
| 181 | | case Type::Elaborated: |
| 182 | 228 | case Type::Attributed: |
| 183 | 229 | case Type::TemplateTypeParm: |
| 184 | 230 | case Type::SubstTemplateTypeParm: |
| ... | ... | @@ -194,12 +240,90 @@ static AstNode *type_node(Context *c, const Type *ty) { |
| 194 | 240 | case Type::Complex: |
| 195 | 241 | case Type::ObjCObjectPointer: |
| 196 | 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 | } |
| 200 | 249 | |
| 201 | | static AstNode *type_node_from_qual_type(Context *c, QualType qt) { |
| 202 | | return type_node(c, qt.getTypePtr()); |
| 250 | static AstNode *make_qual_type_node(Context *c, QualType qt) { |
| 251 | return make_type_node(c, qt.getTypePtr()); |
| 252 | } |
| 253 | |
| 254 | static 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 | |
| 303 | static 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 | } |
| 204 | 328 | |
| 205 | 329 | static bool decl_visitor(void *context, const Decl *decl) { |
| ... | ... | @@ -207,49 +331,11 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 207 | 331 | |
| 208 | 332 | switch (decl->getKind()) { |
| 209 | 333 | case Decl::Function: |
| 210 | | { |
| 211 | | const FunctionDecl *fn_decl = static_cast<const FunctionDecl*>(decl); |
| 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 | | /* |
| 334 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); |
| 335 | break; |
| 244 | 336 | case Decl::Typedef: |
| 245 | | { |
| 246 | | AstNode *node = create_node(c, NodeTypeVariableDeclaration); |
| 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 | | */ |
| 337 | visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); |
| 338 | break; |
| 253 | 339 | default: |
| 254 | 340 | if (c->warnings_on) { |
| 255 | 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 | 368 | Context context = {0}; |
| 283 | 369 | Context *c = &context; |
| 284 | 370 | c->parse_h = parse_h; |
| 371 | c->type_table.init(64); |
| 285 | 372 | |
| 286 | 373 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); |
| 287 | 374 | if (ZIG_PARSEH_CFLAGS) { |