| ... | ... | @@ -28,9 +28,36 @@ struct Context { |
| 28 | 28 | AstNode *root; |
| 29 | 29 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table; |
| 30 | 30 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; |
| 31 | SourceManager *source_manager; |
| 31 | 32 | }; |
| 32 | 33 | |
| 33 | | static AstNode *make_qual_type_node(Context *c, QualType qt); |
| 34 | __attribute__ ((format (printf, 3, 4))) |
| 35 | static void emit_warning(Context *c, const Decl *decl, const char *format, ...) { |
| 36 | if (!c->warnings_on) { |
| 37 | return; |
| 38 | } |
| 39 | |
| 40 | va_list ap; |
| 41 | va_start(ap, format); |
| 42 | Buf *msg = buf_vprintf(format, ap); |
| 43 | va_end(ap); |
| 44 | |
| 45 | SourceLocation sl = decl->getLocation(); |
| 46 | |
| 47 | StringRef filename = c->source_manager->getFilename(sl); |
| 48 | const char *filename_bytes = (const char *)filename.bytes_begin(); |
| 49 | Buf *path; |
| 50 | if (filename_bytes) { |
| 51 | path = buf_create_from_str(filename_bytes); |
| 52 | } else { |
| 53 | path = buf_sprintf("(no file)"); |
| 54 | } |
| 55 | unsigned line = c->source_manager->getSpellingLineNumber(sl); |
| 56 | unsigned column = c->source_manager->getSpellingColumnNumber(sl); |
| 57 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); |
| 58 | } |
| 59 | |
| 60 | static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl); |
| 34 | 61 | |
| 35 | 62 | static AstNode *create_node(Context *c, NodeType type) { |
| 36 | 63 | AstNode *node = allocate<AstNode>(1); |
| ... | ... | @@ -96,7 +123,7 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { |
| 96 | 123 | return node; |
| 97 | 124 | } |
| 98 | 125 | |
| 99 | | static AstNode *make_type_node(Context *c, const Type *ty) { |
| 126 | static AstNode *make_type_node(Context *c, const Type *ty, Decl *decl) { |
| 100 | 127 | switch (ty->getTypeClass()) { |
| 101 | 128 | case Type::Builtin: |
| 102 | 129 | { |
| ... | ... | @@ -159,9 +186,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) { |
| 159 | 186 | case BuiltinType::UnknownAny: |
| 160 | 187 | case BuiltinType::BuiltinFn: |
| 161 | 188 | case BuiltinType::ARCUnbridgedCast: |
| 162 | | if (c->warnings_on) { |
| 163 | | fprintf(stderr, "missed a builtin type\n"); |
| 164 | | } |
| 189 | emit_warning(c, decl, "missed a builtin type"); |
| 165 | 190 | return nullptr; |
| 166 | 191 | } |
| 167 | 192 | break; |
| ... | ... | @@ -170,7 +195,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) { |
| 170 | 195 | { |
| 171 | 196 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); |
| 172 | 197 | QualType child_qt = pointer_ty->getPointeeType(); |
| 173 | | AstNode *type_node = make_qual_type_node(c, child_qt); |
| 198 | AstNode *type_node = make_qual_type_node(c, child_qt, decl); |
| 174 | 199 | return pointer_to_type(c, type_node, child_qt.isConstQualified()); |
| 175 | 200 | } |
| 176 | 201 | case Type::Typedef: |
| ... | ... | @@ -208,14 +233,10 @@ static AstNode *make_type_node(Context *c, const Type *ty) { |
| 208 | 233 | } |
| 209 | 234 | } |
| 210 | 235 | case Type::Elaborated: |
| 211 | | if (c->warnings_on) { |
| 212 | | fprintf(stderr, "ignoring elaborated type\n"); |
| 213 | | } |
| 236 | emit_warning(c, decl, "ignoring elaborated type"); |
| 214 | 237 | return nullptr; |
| 215 | 238 | case Type::FunctionProto: |
| 216 | | if (c->warnings_on) { |
| 217 | | fprintf(stderr, "ignoring function type\n"); |
| 218 | | } |
| 239 | emit_warning(c, decl, "ignoring function type"); |
| 219 | 240 | return nullptr; |
| 220 | 241 | case Type::Record: |
| 221 | 242 | case Type::Enum: |
| ... | ... | @@ -254,15 +275,13 @@ static AstNode *make_type_node(Context *c, const Type *ty) { |
| 254 | 275 | case Type::Complex: |
| 255 | 276 | case Type::ObjCObjectPointer: |
| 256 | 277 | case Type::Atomic: |
| 257 | | if (c->warnings_on) { |
| 258 | | fprintf(stderr, "missed a '%s' type\n", ty->getTypeClassName()); |
| 259 | | } |
| 278 | emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName()); |
| 260 | 279 | return nullptr; |
| 261 | 280 | } |
| 262 | 281 | } |
| 263 | 282 | |
| 264 | | static AstNode *make_qual_type_node(Context *c, QualType qt) { |
| 265 | | return make_type_node(c, qt.getTypePtr()); |
| 283 | static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl) { |
| 284 | return make_type_node(c, qt.getTypePtr(), decl); |
| 266 | 285 | } |
| 267 | 286 | |
| 268 | 287 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| ... | ... | @@ -292,7 +311,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 292 | 311 | buf_init_from_str(&param_decl_node->data.param_decl.name, name); |
| 293 | 312 | QualType qt = param->getOriginalType(); |
| 294 | 313 | param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); |
| 295 | | param_decl_node->data.param_decl.type = make_qual_type_node(c, qt); |
| 314 | param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, (Decl*)fn_decl); |
| 296 | 315 | if (!param_decl_node->data.param_decl.type) { |
| 297 | 316 | all_ok = false; |
| 298 | 317 | break; |
| ... | ... | @@ -305,7 +324,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 305 | 324 | if (fn_decl->isNoReturn()) { |
| 306 | 325 | node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); |
| 307 | 326 | } else { |
| 308 | | node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType()); |
| 327 | node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType(), (Decl*)fn_decl); |
| 309 | 328 | } |
| 310 | 329 | |
| 311 | 330 | if (!node->data.fn_proto.return_type) { |
| ... | ... | @@ -313,9 +332,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 313 | 332 | } |
| 314 | 333 | if (!all_ok) { |
| 315 | 334 | // not all the types could be resolved, so we give up on the function decl |
| 316 | | if (c->warnings_on) { |
| 317 | | fprintf(stderr, "skipping function %s", buf_ptr(&node->data.fn_proto.name)); |
| 318 | | } |
| 335 | emit_warning(c, (Decl*)fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name)); |
| 319 | 336 | return; |
| 320 | 337 | } |
| 321 | 338 | |
| ... | ... | @@ -344,7 +361,7 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) |
| 344 | 361 | return; |
| 345 | 362 | } |
| 346 | 363 | |
| 347 | | AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt)); |
| 364 | AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt, (Decl*)typedef_decl)); |
| 348 | 365 | |
| 349 | 366 | if (node) { |
| 350 | 367 | normalize_parent_ptrs(node); |
| ... | ... | @@ -363,16 +380,14 @@ static bool decl_visitor(void *context, const Decl *decl) { |
| 363 | 380 | visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); |
| 364 | 381 | break; |
| 365 | 382 | default: |
| 366 | | if (c->warnings_on) { |
| 367 | | fprintf(stderr, "ignoring %s\n", decl->getDeclKindName()); |
| 368 | | } |
| 383 | emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName()); |
| 369 | 384 | } |
| 370 | 385 | |
| 371 | 386 | return true; |
| 372 | 387 | } |
| 373 | 388 | |
| 374 | 389 | int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, |
| 375 | | const char **args, int args_len, const char *libc_include_path) |
| 390 | const char **args, int args_len, const char *libc_include_path, bool warnings_on) |
| 376 | 391 | { |
| 377 | 392 | int err; |
| 378 | 393 | Buf tmp_file_path = BUF_INIT; |
| ... | ... | @@ -389,16 +404,19 @@ int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *sour |
| 389 | 404 | clang_argv.append(args[i]); |
| 390 | 405 | } |
| 391 | 406 | |
| 392 | | err = parse_h_file(import, errors, &clang_argv); |
| 407 | err = parse_h_file(import, errors, &clang_argv, warnings_on); |
| 393 | 408 | |
| 394 | 409 | os_delete_file(&tmp_file_path); |
| 395 | 410 | |
| 396 | 411 | return err; |
| 397 | 412 | } |
| 398 | 413 | |
| 399 | | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<const char *> *clang_argv) { |
| 414 | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, |
| 415 | ZigList<const char *> *clang_argv, bool warnings_on) |
| 416 | { |
| 400 | 417 | Context context = {0}; |
| 401 | 418 | Context *c = &context; |
| 419 | c->warnings_on = warnings_on; |
| 402 | 420 | c->import = import; |
| 403 | 421 | c->errors = errors; |
| 404 | 422 | c->visib_mod = VisibModPub; |
| ... | ... | @@ -492,6 +510,8 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList< |
| 492 | 510 | return 0; |
| 493 | 511 | } |
| 494 | 512 | |
| 513 | c->source_manager = &ast_unit->getSourceManager(); |
| 514 | |
| 495 | 515 | c->root = create_node(c, NodeTypeRoot); |
| 496 | 516 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); |
| 497 | 517 | normalize_parent_ptrs(c->root); |