aboutsummaryrefslogtreecommitdiff
path: root/src/check_type.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_type.cpp')
-rw-r--r--src/check_type.cpp44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 8aa24a752..3829694a0 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -329,7 +329,7 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t
auto *found_gen_types = map_get(&ctx->checker->info.gen_types, hash_pointer(original_type));
if (found_gen_types) {
- array_add(found_gen_types, e);
+ array_add(found_gen_types, e);
} else {
auto array = array_make<Entity *>(heap_allocator());
array_add(&array, e);
@@ -2501,7 +2501,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
c->curr_proc_sig = type;
c->in_proc_sig = true;
-
+
ProcCallingConvention cc = pt->calling_convention;
if (cc == ProcCC_ForeignBlockDefault) {
cc = ProcCC_CDecl;
@@ -3284,6 +3284,46 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
return true;
case_end;
+ case_ast_node(rt, RelativeType, e);
+ GB_ASSERT(rt->tag->kind == Ast_CallExpr);
+ ast_node(ce, CallExpr, rt->tag);
+
+ Type *base_integer = nullptr;
+
+ if (ce->args.count != 1) {
+ error(rt->type, "#relative expected 1 type argument, got %td", ce->args.count);
+ } else {
+ base_integer = check_type(ctx, ce->args[0]);
+ if (!is_type_integer(base_integer)) {
+ error(rt->type, "#relative base types must be an integer");
+ base_integer = nullptr;
+ } else if (type_size_of(base_integer) > 64) {
+ error(rt->type, "#relative base integer types be less than or equal to 64-bits");
+ base_integer = nullptr;
+ }
+ }
+
+ Type *relative_type = nullptr;
+ Type *base_type = check_type(ctx, rt->type);
+ if (!is_type_pointer(base_type) && !is_type_slice(base_type)) {
+ error(rt->type, "#relative types can only be a pointer or slice");
+ relative_type = base_type;
+ } else if (base_integer == nullptr) {
+ relative_type = base_type;
+ } else {
+ if (is_type_pointer(base_type)) {
+ relative_type = alloc_type_relative_pointer(base_type, base_integer);
+ } else if (is_type_slice(base_type)) {
+ relative_type = alloc_type_relative_slice(base_type, base_integer);
+ }
+ }
+ GB_ASSERT(relative_type != nullptr);
+
+ *type = relative_type;
+ set_base_type(named_type, *type);
+ return true;
+ case_end;
+
case_ast_node(ot, OpaqueType, e);
Type *elem = strip_opaque_type(check_type_expr(ctx, ot->type, nullptr));
*type = alloc_type_opaque(elem);