aboutsummaryrefslogtreecommitdiff
path: root/src/check_decl.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2022-02-15 15:48:56 +0000
committerGitHub <noreply@github.com>2022-02-15 15:48:56 +0000
commit9e98494fff550c84a6d9c73032f3c9556f9b4c43 (patch)
tree3448b7b6dd725433a57e16348eb2d7e688e565ad /src/check_decl.cpp
parent86d334282cf039860ddd9e894fbb552c1111ca4f (diff)
parent803648be894659409beb3c2b5e76b7b491ddf7c5 (diff)
Merge pull request #1482 from odin-lang/objc-intrinsics
Improve support Objective-C code through intrinsics and Metal API
Diffstat (limited to 'src/check_decl.cpp')
-rw-r--r--src/check_decl.cpp64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index f6dade812..45d741532 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -338,6 +338,13 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def)
if (decl != nullptr) {
AttributeContext ac = {};
check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac);
+ if (e->kind == Entity_TypeName && ac.objc_class != "") {
+ e->TypeName.objc_class_name = ac.objc_class;
+
+ if (type_size_of(e->type) > 0) {
+ error(e->token, "@(objc_class) marked type must be of zero size");
+ }
+ }
}
@@ -819,6 +826,63 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
}
e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode;
+ if (ac.objc_name.len || ac.objc_is_class_method || ac.objc_type) {
+ if (ac.objc_name.len == 0 && ac.objc_is_class_method) {
+ error(e->token, "@(objc_name) is required with @(objc_is_class_method)");
+ } else if (ac.objc_type == nullptr) {
+ error(e->token, "@(objc_name) requires that @(objc_type) to be set");
+ } else if (ac.objc_name.len == 0 && ac.objc_type) {
+ error(e->token, "@(objc_name) is required with @(objc_type)");
+ } else {
+ Type *t = ac.objc_type;
+ if (t->kind == Type_Named) {
+ Entity *tn = t->Named.type_name;
+
+ GB_ASSERT(tn->kind == Entity_TypeName);
+
+ if (tn->scope != e->scope) {
+ error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope");
+ } else {
+ mutex_lock(&global_type_name_objc_metadata_mutex);
+ defer (mutex_unlock(&global_type_name_objc_metadata_mutex));
+
+ if (!tn->TypeName.objc_metadata) {
+ tn->TypeName.objc_metadata = create_type_name_obj_c_metadata();
+ }
+ auto *md = tn->TypeName.objc_metadata;
+ mutex_lock(md->mutex);
+ defer (mutex_unlock(md->mutex));
+
+ if (!ac.objc_is_class_method) {
+ bool ok = true;
+ for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
+ if (entry.name == ac.objc_name) {
+ error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
+ }
+ } else {
+ bool ok = true;
+ for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
+ if (entry.name == ac.objc_name) {
+ error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
+ }
+ }
+ }
+ }
+ }
+ }
+
switch (e->Procedure.optimization_mode) {
case ProcedureOptimizationMode_None: