| author | |
| committer | |
| log | baf889c87913b08f444291242e0c170b1aad14f4 |
| tree | a71b79db04b201cd0ab459e9a52cf32cc6c7cd98 |
| parent | 87922bfae0cbb90bd8e05a00c51a0c737ef3245f |
3 files changed, 31 insertions(+), 10 deletions(-)
src/analyze.cpp+6-4| ... | ... | @@ -3886,17 +3886,19 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 3886 | 3886 | } |
| 3887 | 3887 | |
| 3888 | 3888 | // explicit cast from pointer to another pointer |
| 3889 | if (actual_type->id == TypeTableEntryIdPointer && | |
| 3890 | wanted_type->id == TypeTableEntryIdPointer) | |
| 3889 | if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) && | |
| 3890 | (wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn)) | |
| 3891 | 3891 | { |
| 3892 | 3892 | return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false); |
| 3893 | 3893 | } |
| 3894 | 3894 | |
| 3895 | 3895 | // explicit cast from maybe pointer to another maybe pointer |
| 3896 | 3896 | if (actual_type->id == TypeTableEntryIdMaybe && |
| 3897 | actual_type->data.maybe.child_type->id == TypeTableEntryIdPointer && | |
| 3897 | (actual_type->data.maybe.child_type->id == TypeTableEntryIdPointer || | |
| 3898 | actual_type->data.maybe.child_type->id == TypeTableEntryIdFn) && | |
| 3898 | 3899 | wanted_type->id == TypeTableEntryIdMaybe && |
| 3899 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer) | |
| 3900 | (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer || | |
| 3901 | wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn)) | |
| 3900 | 3902 | { |
| 3901 | 3903 | return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false); |
| 3902 | 3904 | } |
src/parseh.cpp+21-6| ... | ... | @@ -314,6 +314,19 @@ static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) { |
| 314 | 314 | return false; |
| 315 | 315 | } |
| 316 | 316 | |
| 317 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | |
| 318 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | |
| 319 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | |
| 320 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | |
| 321 | return true; | |
| 322 | } | |
| 323 | } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) { | |
| 324 | const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr()); | |
| 325 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); | |
| 326 | } | |
| 327 | return false; | |
| 328 | } | |
| 329 | ||
| 317 | 330 | static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl, |
| 318 | 331 | HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table) |
| 319 | 332 | { |
| ... | ... | @@ -395,11 +408,8 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const |
| 395 | 408 | return c->codegen->builtin_types.entry_invalid; |
| 396 | 409 | } |
| 397 | 410 | |
| 398 | if (child_qt.getTypePtr()->getTypeClass() == Type::Paren) { | |
| 399 | const ParenType *paren_type = static_cast<const ParenType *>(child_qt.getTypePtr()); | |
| 400 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | |
| 401 | return get_maybe_type(c->codegen, child_type); | |
| 402 | } | |
| 411 | if (qual_type_child_is_fn_proto(child_qt)) { | |
| 412 | return get_maybe_type(c->codegen, child_type); | |
| 403 | 413 | } |
| 404 | 414 | bool is_const = child_qt.isConstQualified(); |
| 405 | 415 | |
| ... | ... | @@ -1639,7 +1649,12 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 1639 | 1649 | unsigned offset = fsl.getManager().getFileOffset(fsl); |
| 1640 | 1650 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); |
| 1641 | 1651 | Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin()); |
| 1642 | Buf *path = buf_create_from_str((const char *)filename.bytes_begin()); | |
| 1652 | Buf *path; | |
| 1653 | if (filename.empty()) { | |
| 1654 | path = buf_alloc(); | |
| 1655 | } else { | |
| 1656 | path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size()); | |
| 1657 | } | |
| 1643 | 1658 | |
| 1644 | 1659 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); |
| 1645 | 1660 |
test/run_tests.cpp+4| ... | ... | @@ -1928,6 +1928,10 @@ extern void (*fn_ptr)(void); |
| 1928 | 1928 | add_parseh_case("#define string", R"SOURCE( |
| 1929 | 1929 | #define foo "a string" |
| 1930 | 1930 | )SOURCE", 1, "pub const foo = c\"a string\";"); |
| 1931 | ||
| 1932 | add_parseh_case("__cdecl doesn't mess up function pointers", R"SOURCE( | |
| 1933 | void foo(void (__cdecl *fn_ptr)(void)); | |
| 1934 | )SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());"); | |
| 1931 | 1935 | } |
| 1932 | 1936 | |
| 1933 | 1937 | static void run_self_hosted_test(void) { |