aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-09-21 21:16:46 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-09-21 21:16:46 -0700
commit0c70bb4fce8b0460f86ed218f54ba31b291f2bfb (patch)
tree1e0ad8f9ea76b30e52753a2f25f5f1d18d25896d /src
parentafac5d28951cfd913851094649e8b9f2136694ca (diff)
parent58ee5f4e61cd9b7a9ba65798e2214efa3753a733 (diff)
downloadzig-0c70bb4fce8b0460f86ed218f54ba31b291f2bfb.tar.gz
zig-0c70bb4fce8b0460f86ed218f54ba31b291f2bfb.zip
Merge remote-tracking branch 'origin/master' into stage2-zig-cc
Diffstat (limited to 'src')
-rw-r--r--src/stage1/analyze.cpp29
-rw-r--r--src/stage1/ir.cpp24
-rw-r--r--src/translate_c.zig2
3 files changed, 38 insertions, 17 deletions
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp
index 6c6f198e7a..15c30350d7 100644
--- a/src/stage1/analyze.cpp
+++ b/src/stage1/analyze.cpp
@@ -3161,30 +3161,29 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
tag_type->data.enumeration.fields_by_name.init(field_count);
tag_type->data.enumeration.decls_scope = union_type->data.unionation.decls_scope;
} else if (enum_type_node != nullptr) {
- ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node);
- if (type_is_invalid(enum_type)) {
+ tag_type = analyze_type_expr(g, scope, enum_type_node);
+ } else {
+ if (decl_node->type == NodeTypeContainerDecl) {
+ tag_type = nullptr;
+ } else {
+ tag_type = union_type->data.unionation.tag_type;
+ }
+ }
+ if (tag_type != nullptr) {
+ if (type_is_invalid(tag_type)) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
return ErrorSemanticAnalyzeFail;
}
- if (enum_type->id != ZigTypeIdEnum) {
+ if (tag_type->id != ZigTypeIdEnum) {
union_type->data.unionation.resolve_status = ResolveStatusInvalid;
- add_node_error(g, enum_type_node,
- buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));
+ add_node_error(g, enum_type_node != nullptr ? enum_type_node : decl_node,
+ buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&tag_type->name)));
return ErrorSemanticAnalyzeFail;
}
- if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) {
+ if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) {
assert(g->errors.length != 0);
return err;
}
- tag_type = enum_type;
- } else {
- if (decl_node->type == NodeTypeContainerDecl) {
- tag_type = nullptr;
- } else {
- tag_type = union_type->data.unionation.tag_type;
- }
- }
- if (tag_type != nullptr) {
covered_enum_fields = heap::c_allocator.allocate<bool>(tag_type->data.enumeration.src_field_count);
}
union_type->data.unionation.tag_type = tag_type;
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
index 50076f9a86..f0546f9e01 100644
--- a/src/stage1/ir.cpp
+++ b/src/stage1/ir.cpp
@@ -63,6 +63,7 @@ enum ConstCastResultId {
ConstCastResultIdPointerChild,
ConstCastResultIdSliceChild,
ConstCastResultIdOptionalChild,
+ ConstCastResultIdOptionalShape,
ConstCastResultIdErrorUnionPayload,
ConstCastResultIdErrorUnionErrorSet,
ConstCastResultIdFnAlign,
@@ -11946,8 +11947,22 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
}
}
- // maybe
+ // optional types
if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
+ // Consider the case where the wanted type is ??[*]T and the actual one
+ // is ?[*]T, we cannot turn the former into the latter even though the
+ // child types are compatible (?[*]T and [*]T are both represented as a
+ // pointer). The extra level of indirection in ??[*]T means it's
+ // represented as a regular, fat, optional type and, as a consequence,
+ // has a different shape than the one of ?[*]T.
+ if ((wanted_ptr_type != nullptr) != (actual_ptr_type != nullptr)) {
+ // The use of type_mismatch is intentional
+ result.id = ConstCastResultIdOptionalShape;
+ result.data.type_mismatch = heap::c_allocator.allocate_nonzero<ConstCastTypeMismatch>(1);
+ result.data.type_mismatch->wanted_type = wanted_type;
+ result.data.type_mismatch->actual_type = actual_type;
+ return result;
+ }
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
if (child.id == ConstCastResultIdInvalid)
@@ -14549,6 +14564,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
report_recursive_error(ira, source_node, &cast_result->data.optional->child, msg);
break;
}
+ case ConstCastResultIdOptionalShape: {
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("optional type child '%s' cannot cast into optional type '%s'",
+ buf_ptr(&cast_result->data.type_mismatch->actual_type->name),
+ buf_ptr(&cast_result->data.type_mismatch->wanted_type->name)));
+ break;
+ }
case ConstCastResultIdErrorUnionErrorSet: {
ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
buf_sprintf("error set '%s' cannot cast into error set '%s'",
diff --git a/src/translate_c.zig b/src/translate_c.zig
index c5c5231ca2..66b5752930 100644
--- a/src/translate_c.zig
+++ b/src/translate_c.zig
@@ -2032,7 +2032,7 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
// Handle the remaining escapes Zig doesn't support by turning them
// into their respective hex representation
else => if (std.ascii.isCntrl(c))
- std.fmt.bufPrint(char_buf, "\\x{x:0<2}", .{c}) catch unreachable
+ std.fmt.bufPrint(char_buf, "\\x{x:0>2}", .{c}) catch unreachable
else
std.fmt.bufPrint(char_buf, "{c}", .{c}) catch unreachable,
};