From cf39819478e237255109d0343e642db70e88071b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 22 Jan 2018 22:24:07 -0500 Subject: add new kind of test: generating .h files. and more * docgen supports obj_err code kind for demonstrating errors without explicit test cases * add documentation for `extern enum`. See #367 * remove coldcc keyword and add @setIsCold. See #661 * add compile errors for non-extern struct, enum, unions in function signatures * add .h file generation for extern struct, enum, unions --- src/analyze.cpp | 154 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 40 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index ade9b4b1fe..1880b71fbb 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1158,6 +1158,104 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** return true; } +static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { + switch (type_entry->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + zig_unreachable(); + case TypeTableEntryIdMetaType: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdOpaque: + return false; + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdPointer: + case TypeTableEntryIdArray: + case TypeTableEntryIdFn: + return true; + case TypeTableEntryIdStruct: + return type_entry->data.structure.layout == ContainerLayoutPacked; + case TypeTableEntryIdUnion: + return type_entry->data.unionation.layout == ContainerLayoutPacked; + case TypeTableEntryIdMaybe: + { + TypeTableEntry *child_type = type_entry->data.maybe.child_type; + return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; + } + case TypeTableEntryIdEnum: + return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; + } + zig_unreachable(); +} + +static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { + switch (type_entry->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + zig_unreachable(); + case TypeTableEntryIdMetaType: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + return false; + case TypeTableEntryIdOpaque: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + return true; + case TypeTableEntryIdInt: + switch (type_entry->data.integral.bit_count) { + case 8: + case 16: + case 32: + case 64: + case 128: + return true; + default: + return false; + } + case TypeTableEntryIdFloat: + return true; + case TypeTableEntryIdArray: + return type_allowed_in_extern(g, type_entry->data.array.child_type); + case TypeTableEntryIdFn: + return type_entry->data.fn.fn_type_id.cc == CallingConventionC; + case TypeTableEntryIdPointer: + return type_allowed_in_extern(g, type_entry->data.pointer.child_type); + case TypeTableEntryIdStruct: + return type_entry->data.structure.layout == ContainerLayoutExtern; + case TypeTableEntryIdMaybe: + { + TypeTableEntry *child_type = type_entry->data.maybe.child_type; + return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; + } + case TypeTableEntryIdEnum: + return type_entry->data.enumeration.layout == ContainerLayoutExtern; + case TypeTableEntryIdUnion: + return type_entry->data.unionation.layout == ContainerLayoutExtern; + } + zig_unreachable(); +} + static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) { assert(proto_node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; @@ -1208,6 +1306,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c } } + if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, type_entry)) { + add_node_error(g, param_node->data.param_decl.type, + buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", + buf_ptr(&type_entry->name), + calling_convention_name(fn_type_id.cc))); + return g->builtin_types.entry_invalid; + } + switch (type_entry->id) { case TypeTableEntryIdInvalid: return g->builtin_types.entry_invalid; @@ -1272,6 +1378,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c fn_type_id.return_type = (fn_proto->return_type == nullptr) ? g->builtin_types.entry_void : analyze_type_expr(g, child_scope, fn_proto->return_type); + if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, fn_type_id.return_type)) { + add_node_error(g, fn_proto->return_type, + buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", + buf_ptr(&fn_type_id.return_type->name), + calling_convention_name(fn_type_id.cc))); + return g->builtin_types.entry_invalid; + } + switch (fn_type_id.return_type->id) { case TypeTableEntryIdInvalid: return g->builtin_types.entry_invalid; @@ -1424,46 +1538,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { enum_type->di_type = tag_di_type; } -static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { - switch (type_entry->id) { - case TypeTableEntryIdInvalid: - case TypeTableEntryIdVar: - zig_unreachable(); - case TypeTableEntryIdMetaType: - case TypeTableEntryIdUnreachable: - case TypeTableEntryIdNumLitFloat: - case TypeTableEntryIdNumLitInt: - case TypeTableEntryIdUndefLit: - case TypeTableEntryIdNullLit: - case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: - case TypeTableEntryIdNamespace: - case TypeTableEntryIdBlock: - case TypeTableEntryIdBoundFn: - case TypeTableEntryIdArgTuple: - case TypeTableEntryIdOpaque: - return false; - case TypeTableEntryIdVoid: - case TypeTableEntryIdBool: - case TypeTableEntryIdInt: - case TypeTableEntryIdFloat: - case TypeTableEntryIdPointer: - case TypeTableEntryIdArray: - case TypeTableEntryIdUnion: - case TypeTableEntryIdFn: - return true; - case TypeTableEntryIdStruct: - return type_entry->data.structure.layout == ContainerLayoutPacked; - case TypeTableEntryIdMaybe: - { - TypeTableEntry *child_type = type_entry->data.maybe.child_type; - return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; - } - case TypeTableEntryIdEnum: - return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; - } - zig_unreachable(); -} TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], TypeTableEntry *field_types[], size_t field_count) -- cgit v1.2.3