From 137bb51e200517c40e4863d9d45dd31c5bf90967 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Jan 2016 00:25:10 -0700 Subject: [PATCH] parseh: add --c-import-warnings option --- src/analyze.cpp | 2 +- src/main.cpp | 8 +++-- src/parseh.cpp | 78 +++++++++++++++++++++++++++++++------------------ src/parseh.hpp | 5 ++-- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 6df6c8baed..e0519cdc10 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1069,7 +1069,7 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A int err; if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, - buf_ptr(g->libc_include_path)))) + buf_ptr(g->libc_include_path), false))) { zig_panic("unable to parse h file: %s\n", err_str(err)); } diff --git a/src/main.cpp b/src/main.cpp index 188346fb21..8105634d6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ static int usage(const char *arg0) { " --libc-path [path] set the C compiler data path\n" " -isystem [dir] add additional search path for other .h files\n" " -dirafter [dir] same as -isystem but do it last\n" + " --c-import-warnings enable warnings when importing .h files\n" , arg0); return EXIT_FAILURE; } @@ -167,6 +168,7 @@ static int parseh(const char *arg0, int argc, char **argv) { char *in_file = nullptr; ZigList clang_argv = {0}; ErrColor color = ErrColorAuto; + bool warnings_on = false; for (int i = 0; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-') { @@ -193,7 +195,9 @@ static int parseh(const char *arg0, int argc, char **argv) { } else { return usage(arg0); } - } else { + } else if (strcmp(arg, "--c-import-warnings") == 0) { + warnings_on = true; + } else { fprintf(stderr, "unrecognized argument: %s", arg); return usage(arg0); } @@ -217,7 +221,7 @@ static int parseh(const char *arg0, int argc, char **argv) { ImportTableEntry import = {0}; ZigList errors = {0}; - int err = parse_h_file(&import, &errors, &clang_argv); + int err = parse_h_file(&import, &errors, &clang_argv, warnings_on); if (err) { fprintf(stderr, "unable to parse .h file: %s\n", err_str(err)); diff --git a/src/parseh.cpp b/src/parseh.cpp index cca9eab869..1d1e76e65e 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -28,9 +28,36 @@ struct Context { AstNode *root; HashMap type_table; HashMap fn_table; + SourceManager *source_manager; }; -static AstNode *make_qual_type_node(Context *c, QualType qt); +__attribute__ ((format (printf, 3, 4))) +static void emit_warning(Context *c, const Decl *decl, const char *format, ...) { + if (!c->warnings_on) { + return; + } + + va_list ap; + va_start(ap, format); + Buf *msg = buf_vprintf(format, ap); + va_end(ap); + + SourceLocation sl = decl->getLocation(); + + StringRef filename = c->source_manager->getFilename(sl); + const char *filename_bytes = (const char *)filename.bytes_begin(); + Buf *path; + if (filename_bytes) { + path = buf_create_from_str(filename_bytes); + } else { + path = buf_sprintf("(no file)"); + } + unsigned line = c->source_manager->getSpellingLineNumber(sl); + unsigned column = c->source_manager->getSpellingColumnNumber(sl); + fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); +} + +static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl); static AstNode *create_node(Context *c, NodeType type) { AstNode *node = allocate(1); @@ -96,7 +123,7 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { return node; } -static AstNode *make_type_node(Context *c, const Type *ty) { +static AstNode *make_type_node(Context *c, const Type *ty, Decl *decl) { switch (ty->getTypeClass()) { case Type::Builtin: { @@ -159,9 +186,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) { case BuiltinType::UnknownAny: case BuiltinType::BuiltinFn: case BuiltinType::ARCUnbridgedCast: - if (c->warnings_on) { - fprintf(stderr, "missed a builtin type\n"); - } + emit_warning(c, decl, "missed a builtin type"); return nullptr; } break; @@ -170,7 +195,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) { { const PointerType *pointer_ty = static_cast(ty); QualType child_qt = pointer_ty->getPointeeType(); - AstNode *type_node = make_qual_type_node(c, child_qt); + AstNode *type_node = make_qual_type_node(c, child_qt, decl); return pointer_to_type(c, type_node, child_qt.isConstQualified()); } case Type::Typedef: @@ -208,14 +233,10 @@ static AstNode *make_type_node(Context *c, const Type *ty) { } } case Type::Elaborated: - if (c->warnings_on) { - fprintf(stderr, "ignoring elaborated type\n"); - } + emit_warning(c, decl, "ignoring elaborated type"); return nullptr; case Type::FunctionProto: - if (c->warnings_on) { - fprintf(stderr, "ignoring function type\n"); - } + emit_warning(c, decl, "ignoring function type"); return nullptr; case Type::Record: case Type::Enum: @@ -254,15 +275,13 @@ static AstNode *make_type_node(Context *c, const Type *ty) { case Type::Complex: case Type::ObjCObjectPointer: case Type::Atomic: - if (c->warnings_on) { - fprintf(stderr, "missed a '%s' type\n", ty->getTypeClassName()); - } + emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName()); return nullptr; } } -static AstNode *make_qual_type_node(Context *c, QualType qt) { - return make_type_node(c, qt.getTypePtr()); +static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl) { + return make_type_node(c, qt.getTypePtr(), decl); } 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) { buf_init_from_str(¶m_decl_node->data.param_decl.name, name); QualType qt = param->getOriginalType(); param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); - param_decl_node->data.param_decl.type = make_qual_type_node(c, qt); + param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, (Decl*)fn_decl); if (!param_decl_node->data.param_decl.type) { all_ok = false; break; @@ -305,7 +324,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { if (fn_decl->isNoReturn()) { node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); } else { - node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType()); + node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType(), (Decl*)fn_decl); } if (!node->data.fn_proto.return_type) { @@ -313,9 +332,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { } if (!all_ok) { // not all the types could be resolved, so we give up on the function decl - if (c->warnings_on) { - fprintf(stderr, "skipping function %s", buf_ptr(&node->data.fn_proto.name)); - } + emit_warning(c, (Decl*)fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name)); return; } @@ -344,7 +361,7 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) return; } - AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt)); + AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt, (Decl*)typedef_decl)); if (node) { normalize_parent_ptrs(node); @@ -363,16 +380,14 @@ static bool decl_visitor(void *context, const Decl *decl) { visit_typedef_decl(c, static_cast(decl)); break; default: - if (c->warnings_on) { - fprintf(stderr, "ignoring %s\n", decl->getDeclKindName()); - } + emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName()); } return true; } int parse_h_buf(ImportTableEntry *import, ZigList *errors, Buf *source, - const char **args, int args_len, const char *libc_include_path) + const char **args, int args_len, const char *libc_include_path, bool warnings_on) { int err; Buf tmp_file_path = BUF_INIT; @@ -389,16 +404,19 @@ int parse_h_buf(ImportTableEntry *import, ZigList *errors, Buf *sour clang_argv.append(args[i]); } - err = parse_h_file(import, errors, &clang_argv); + err = parse_h_file(import, errors, &clang_argv, warnings_on); os_delete_file(&tmp_file_path); return err; } -int parse_h_file(ImportTableEntry *import, ZigList *errors, ZigList *clang_argv) { +int parse_h_file(ImportTableEntry *import, ZigList *errors, + ZigList *clang_argv, bool warnings_on) +{ Context context = {0}; Context *c = &context; + c->warnings_on = warnings_on; c->import = import; c->errors = errors; c->visib_mod = VisibModPub; @@ -492,6 +510,8 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, ZigList< return 0; } + c->source_manager = &ast_unit->getSourceManager(); + c->root = create_node(c, NodeTypeRoot); ast_unit->visitLocalTopLevelDecls(c, decl_visitor); normalize_parent_ptrs(c->root); diff --git a/src/parseh.hpp b/src/parseh.hpp index e2bb272401..47564b2b16 100644 --- a/src/parseh.hpp +++ b/src/parseh.hpp @@ -12,8 +12,9 @@ #include "all_types.hpp" int parse_h_file(ImportTableEntry *out_import, ZigList *out_errs, - ZigList *clang_argv); + ZigList *clang_argv, bool warnings_on); int parse_h_buf(ImportTableEntry *out_import, ZigList *out_errs, - Buf *source, const char **args, int args_len, const char *libc_include_path); + Buf *source, const char **args, int args_len, const char *libc_include_path, + bool warnings_on); #endif