parseh: add --c-import-warnings option

master
Andrew Kelley 2016-01-28 00:25:10 -07:00
parent 3f0062d7a9
commit 137bb51e20
4 changed files with 59 additions and 34 deletions

View File

@ -1069,7 +1069,7 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, A
int err; int err;
if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, 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)); zig_panic("unable to parse h file: %s\n", err_str(err));
} }

View File

@ -33,6 +33,7 @@ static int usage(const char *arg0) {
" --libc-path [path] set the C compiler data path\n" " --libc-path [path] set the C compiler data path\n"
" -isystem [dir] add additional search path for other .h files\n" " -isystem [dir] add additional search path for other .h files\n"
" -dirafter [dir] same as -isystem but do it last\n" " -dirafter [dir] same as -isystem but do it last\n"
" --c-import-warnings enable warnings when importing .h files\n"
, arg0); , arg0);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -167,6 +168,7 @@ static int parseh(const char *arg0, int argc, char **argv) {
char *in_file = nullptr; char *in_file = nullptr;
ZigList<const char *> clang_argv = {0}; ZigList<const char *> clang_argv = {0};
ErrColor color = ErrColorAuto; ErrColor color = ErrColorAuto;
bool warnings_on = false;
for (int i = 0; i < argc; i += 1) { for (int i = 0; i < argc; i += 1) {
char *arg = argv[i]; char *arg = argv[i];
if (arg[0] == '-') { if (arg[0] == '-') {
@ -193,7 +195,9 @@ static int parseh(const char *arg0, int argc, char **argv) {
} else { } else {
return usage(arg0); return usage(arg0);
} }
} else { } else if (strcmp(arg, "--c-import-warnings") == 0) {
warnings_on = true;
} else {
fprintf(stderr, "unrecognized argument: %s", arg); fprintf(stderr, "unrecognized argument: %s", arg);
return usage(arg0); return usage(arg0);
} }
@ -217,7 +221,7 @@ static int parseh(const char *arg0, int argc, char **argv) {
ImportTableEntry import = {0}; ImportTableEntry import = {0};
ZigList<ErrorMsg *> errors = {0}; ZigList<ErrorMsg *> errors = {0};
int err = parse_h_file(&import, &errors, &clang_argv); int err = parse_h_file(&import, &errors, &clang_argv, warnings_on);
if (err) { if (err) {
fprintf(stderr, "unable to parse .h file: %s\n", err_str(err)); fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));

View File

@ -28,9 +28,36 @@ struct Context {
AstNode *root; AstNode *root;
HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table; HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table; HashMap<Buf *, bool, buf_hash, buf_eql_buf> 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) { static AstNode *create_node(Context *c, NodeType type) {
AstNode *node = allocate<AstNode>(1); AstNode *node = allocate<AstNode>(1);
@ -96,7 +123,7 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
return node; 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()) { switch (ty->getTypeClass()) {
case Type::Builtin: case Type::Builtin:
{ {
@ -159,9 +186,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
case BuiltinType::UnknownAny: case BuiltinType::UnknownAny:
case BuiltinType::BuiltinFn: case BuiltinType::BuiltinFn:
case BuiltinType::ARCUnbridgedCast: case BuiltinType::ARCUnbridgedCast:
if (c->warnings_on) { emit_warning(c, decl, "missed a builtin type");
fprintf(stderr, "missed a builtin type\n");
}
return nullptr; return nullptr;
} }
break; break;
@ -170,7 +195,7 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
{ {
const PointerType *pointer_ty = static_cast<const PointerType*>(ty); const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
QualType child_qt = pointer_ty->getPointeeType(); 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()); return pointer_to_type(c, type_node, child_qt.isConstQualified());
} }
case Type::Typedef: case Type::Typedef:
@ -208,14 +233,10 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
} }
} }
case Type::Elaborated: case Type::Elaborated:
if (c->warnings_on) { emit_warning(c, decl, "ignoring elaborated type");
fprintf(stderr, "ignoring elaborated type\n");
}
return nullptr; return nullptr;
case Type::FunctionProto: case Type::FunctionProto:
if (c->warnings_on) { emit_warning(c, decl, "ignoring function type");
fprintf(stderr, "ignoring function type\n");
}
return nullptr; return nullptr;
case Type::Record: case Type::Record:
case Type::Enum: case Type::Enum:
@ -254,15 +275,13 @@ static AstNode *make_type_node(Context *c, const Type *ty) {
case Type::Complex: case Type::Complex:
case Type::ObjCObjectPointer: case Type::ObjCObjectPointer:
case Type::Atomic: case Type::Atomic:
if (c->warnings_on) { emit_warning(c, decl, "missed a '%s' type", ty->getTypeClassName());
fprintf(stderr, "missed a '%s' type\n", ty->getTypeClassName());
}
return nullptr; return nullptr;
} }
} }
static AstNode *make_qual_type_node(Context *c, QualType qt) { static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl) {
return make_type_node(c, qt.getTypePtr()); return make_type_node(c, qt.getTypePtr(), decl);
} }
static void visit_fn_decl(Context *c, const FunctionDecl *fn_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(&param_decl_node->data.param_decl.name, name); buf_init_from_str(&param_decl_node->data.param_decl.name, name);
QualType qt = param->getOriginalType(); QualType qt = param->getOriginalType();
param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified(); 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) { if (!param_decl_node->data.param_decl.type) {
all_ok = false; all_ok = false;
break; break;
@ -305,7 +324,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
if (fn_decl->isNoReturn()) { if (fn_decl->isNoReturn()) {
node->data.fn_proto.return_type = simple_type_node(c, "unreachable"); node->data.fn_proto.return_type = simple_type_node(c, "unreachable");
} else { } 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) { 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) { if (!all_ok) {
// not all the types could be resolved, so we give up on the function decl // not all the types could be resolved, so we give up on the function decl
if (c->warnings_on) { emit_warning(c, (Decl*)fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name));
fprintf(stderr, "skipping function %s", buf_ptr(&node->data.fn_proto.name));
}
return; return;
} }
@ -344,7 +361,7 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
return; 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) { if (node) {
normalize_parent_ptrs(node); normalize_parent_ptrs(node);
@ -363,16 +380,14 @@ static bool decl_visitor(void *context, const Decl *decl) {
visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
break; break;
default: default:
if (c->warnings_on) { emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());
fprintf(stderr, "ignoring %s\n", decl->getDeclKindName());
}
} }
return true; return true;
} }
int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *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; int err;
Buf tmp_file_path = BUF_INIT; Buf tmp_file_path = BUF_INIT;
@ -389,16 +404,19 @@ int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *sour
clang_argv.append(args[i]); 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); os_delete_file(&tmp_file_path);
return err; return err;
} }
int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<const char *> *clang_argv) { int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
ZigList<const char *> *clang_argv, bool warnings_on)
{
Context context = {0}; Context context = {0};
Context *c = &context; Context *c = &context;
c->warnings_on = warnings_on;
c->import = import; c->import = import;
c->errors = errors; c->errors = errors;
c->visib_mod = VisibModPub; c->visib_mod = VisibModPub;
@ -492,6 +510,8 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<
return 0; return 0;
} }
c->source_manager = &ast_unit->getSourceManager();
c->root = create_node(c, NodeTypeRoot); c->root = create_node(c, NodeTypeRoot);
ast_unit->visitLocalTopLevelDecls(c, decl_visitor); ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
normalize_parent_ptrs(c->root); normalize_parent_ptrs(c->root);

View File

@ -12,8 +12,9 @@
#include "all_types.hpp" #include "all_types.hpp"
int parse_h_file(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs, int parse_h_file(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
ZigList<const char *> *clang_argv); ZigList<const char *> *clang_argv, bool warnings_on);
int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs, int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *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 #endif