diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2025-07-20 15:32:28 +0100 |
|---|---|---|
| committer | gingerBill <gingerBill@users.noreply.github.com> | 2025-07-20 15:32:28 +0100 |
| commit | b095dd71cbe8386de901674535c9d86ccf4cb9d3 (patch) | |
| tree | 9665b0d1f2c3922c69adc8dd2858419910257159 /src | |
| parent | 0dd0a3813bcc3b8c238b5e3c7272439ed08455d0 (diff) | |
| parent | 98c2425fe0aaa749e08387986afc0aa4797ed0da (diff) | |
Merge branch 'master' of https://github.com/odin-lang/Odin
Diffstat (limited to 'src')
| -rw-r--r-- | src/build_settings.cpp | 12 | ||||
| -rw-r--r-- | src/check_decl.cpp | 196 | ||||
| -rw-r--r-- | src/checker.cpp | 2 | ||||
| -rw-r--r-- | src/linker.cpp | 2 |
4 files changed, 110 insertions, 102 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d98340844..fb88b588a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -171,7 +171,7 @@ struct TargetMetrics { enum Subtarget : u32 { Subtarget_Default, - Subtarget_iOS, + Subtarget_iPhone, Subtarget_iPhoneSimulator, Subtarget_Android, @@ -180,7 +180,7 @@ enum Subtarget : u32 { gb_global String subtarget_strings[Subtarget_COUNT] = { str_lit(""), - str_lit("ios"), + str_lit("iphone"), str_lit("iphonesimulator"), str_lit("android"), }; @@ -1828,13 +1828,13 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (metrics->os == TargetOs_darwin) { switch (subtarget) { - case Subtarget_iOS: + case Subtarget_iPhone: switch (metrics->arch) { case TargetArch_arm64: bc->metrics.target_triplet = str_lit("arm64-apple-ios"); break; default: - GB_PANIC("Unknown architecture for -subtarget:ios"); + GB_PANIC("Unknown architecture for -subtarget:iphone"); } break; case Subtarget_iPhoneSimulator: @@ -1909,7 +1909,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (!bc->minimum_os_version_string_given) { if (subtarget == Subtarget_Default) { bc->minimum_os_version_string = str_lit("11.0.0"); - } else if (subtarget == Subtarget_iOS || subtarget == Subtarget_iPhoneSimulator) { + } else if (subtarget == Subtarget_iPhone || subtarget == Subtarget_iPhoneSimulator) { // NOTE(harold): We default to 17.4 on iOS because that's when os_sync_wait_on_address was added and // we'd like to avoid any potential App Store issues by using the private ulock_* there. bc->minimum_os_version_string = str_lit("17.4"); @@ -1917,7 +1917,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } if (subtarget == Subtarget_iPhoneSimulator) { - // For the iOS simulator subtarget, the version must be between 'ios' and '-simulator'. + // For the iPhoneSimulator subtarget, the version must be between 'ios' and '-simulator'. String suffix = str_lit("-simulator"); GB_ASSERT(string_ends_with(bc->metrics.target_triplet, suffix)); diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 3d0d95556..0bacf891b 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1001,120 +1001,128 @@ gb_internal String handle_link_name(CheckerContext *ctx, Token token, String lin gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeContext &ac) { - if (!(ac.objc_name.len || ac.objc_is_class_method || ac.objc_type)) { + if (!ac.objc_type) { return; } - 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; - GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage. - Entity *tn = t->Named.type_name; + Type *t = ac.objc_type; + GB_ASSERT(t->kind == Type_Named); // NOTE(harold): This is already checked for at the attribute resolution stage. - GB_ASSERT(tn->kind == Entity_TypeName); + // Attempt to infer th objc_name automatically if the proc name contains + // the type name objc_type's name, followed by an underscore, as a prefix. + if (ac.objc_name.len == 0) { + String proc_name = e->token.string; + String type_name = t->Named.name; - if (tn->scope != e->scope) { - error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); + if (proc_name.len > type_name.len + 1 && + proc_name[type_name.len] == '_' && + str_eq(type_name, substring(proc_name, 0, type_name.len)) + ) { + ac.objc_name = substring(proc_name, type_name.len+1, proc_name.len); } else { + error(e->token, "@(objc_name) requires that @(objc_type) be set or inferred " + "by prefixing the proc name with the type and underscore: MyObjcType_myProcName :: proc()."); + } + } - // Enable implementation by default if the class is an implementer too and - // @objc_implement was not set to false explicitly in this proc. - bool implement = tn->TypeName.objc_is_implementation; - if (ac.objc_is_disabled_implement) { - implement = false; - } + Entity *tn = t->Named.type_name; + GB_ASSERT(tn->kind == Entity_TypeName); - if (implement) { - GB_ASSERT(e->kind == Entity_Procedure); - - auto &proc = e->type->Proc; - Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil; - - if (!tn->TypeName.objc_is_implementation) { - error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied"); - } else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) { - error(e->token, "Objective-C instance methods implementations require the first parameter to be a pointer to the class type set by @(objc_type)"); - } else if (proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) { - error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set"); - } else if (ac.objc_is_class_method && proc.calling_convention != ProcCC_CDecl) { - error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention"); - } else if (proc.result_count > 1) { - error(e->token, "Objective-C method implementations may return at most 1 value"); - } else { - // Always export unconditionally - // NOTE(harold): This means check_objc_methods() MUST be called before - // e->Procedure.is_export is set in check_proc_decl()! - if (ac.is_export) { - error(e->token, "Explicit export not allowed when @(objc_implement) is set. It set exported implicitly"); - } - if (ac.link_name != "") { - error(e->token, "Explicit linkage not allowed when @(objc_implement) is set. It set to \"strong\" implicitly"); - } + if (tn->scope != e->scope) { + error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); + } else { + // Enable implementation by default if the class is an implementer too and + // @objc_implement was not set to false explicitly in this proc. + bool implement = tn->TypeName.objc_is_implementation; + if (ac.objc_is_disabled_implement) { + implement = false; + } + + if (implement) { + GB_ASSERT(e->kind == Entity_Procedure); + + auto &proc = e->type->Proc; + Type *first_param = proc.param_count > 0 ? proc.params->Tuple.variables[0]->type : t_untyped_nil; + + if (!tn->TypeName.objc_is_implementation) { + error(e->token, "@(objc_is_implement) attribute may only be applied to procedures whose class also have @(objc_is_implement) applied"); + } else if (!ac.objc_is_class_method && !(first_param->kind == Type_Pointer && internal_check_is_assignable_to(t, first_param->Pointer.elem))) { + error(e->token, "Objective-C instance methods implementations require the first parameter to be a pointer to the class type set by @(objc_type)"); + } else if (proc.calling_convention == ProcCC_Odin && !tn->TypeName.objc_context_provider) { + error(e->token, "Objective-C methods with Odin calling convention can only be used with classes that have @(objc_context_provider) set"); + } else if (ac.objc_is_class_method && proc.calling_convention != ProcCC_CDecl) { + error(e->token, "Objective-C class methods (objc_is_class_method=true) that have @objc_is_implementation can only use \"c\" calling convention"); + } else if (proc.result_count > 1) { + error(e->token, "Objective-C method implementations may return at most 1 value"); + } else { + // Always export unconditionally + // NOTE(harold): This means check_objc_methods() MUST be called before + // e->Procedure.is_export is set in check_proc_decl()! + if (ac.is_export) { + error(e->token, "Explicit export not allowed when @(objc_implement) is set. It set exported implicitly"); + } + if (ac.link_name != "") { + error(e->token, "Explicit linkage not allowed when @(objc_implement) is set. It set to \"strong\" implicitly"); + } - ac.is_export = true; - ac.linkage = STR_LIT("strong"); + ac.is_export = true; + ac.linkage = STR_LIT("strong"); - auto method = ObjcMethodData{ ac, e }; - method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name; + auto method = ObjcMethodData{ ac, e }; + method.ac.objc_selector = ac.objc_selector != "" ? ac.objc_selector : ac.objc_name; - CheckerInfo *info = ctx->info; - mutex_lock(&info->objc_method_mutex); - defer (mutex_unlock(&info->objc_method_mutex)); + CheckerInfo *info = ctx->info; + mutex_lock(&info->objc_method_mutex); + defer (mutex_unlock(&info->objc_method_mutex)); - Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t); - if (method_list) { - array_add(method_list, method); - } else { - auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8); - list[0] = method; + Array<ObjcMethodData>* method_list = map_get(&info->objc_method_implementations, t); + if (method_list) { + array_add(method_list, method); + } else { + auto list = array_make<ObjcMethodData>(permanent_allocator(), 1, 8); + list[0] = method; - map_set(&info->objc_method_implementations, t, list); - } + map_set(&info->objc_method_implementations, t, list); } - } else if (ac.objc_selector != "") { - error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C implementations."); } + } else if (ac.objc_selector != "") { + error(e->token, "@(objc_selector) may only be applied to procedures that are Objective-C implementations."); + } - mutex_lock(&global_type_name_objc_metadata_mutex); - defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); + 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 (!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->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); + } + 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}); + } } } } diff --git a/src/checker.cpp b/src/checker.cpp index 625536caa..1821cbd4d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1172,7 +1172,7 @@ gb_internal void init_universal(void) { { GlobalEnumValue values[Subtarget_COUNT] = { {"Default", Subtarget_Default}, - {"iOS", Subtarget_iOS}, + {"iPhone", Subtarget_iPhone}, {"iPhoneSimulator", Subtarget_iPhoneSimulator}, {"Android", Subtarget_Android}, }; diff --git a/src/linker.cpp b/src/linker.cpp index 7647ed872..41333a3c9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -787,7 +787,7 @@ try_cross_linking:; // being set to 'MacOSX' even though we've set the sysroot to the correct SDK (-Wincompatible-sysroot). // This is because it is likely not using the SDK's toolchain Apple Clang but another one installed in the system. switch (selected_subtarget) { - case Subtarget_iOS: + case Subtarget_iPhone: darwin_platform_name = "iPhoneOS"; darwin_xcrun_sdk_name = "iphoneos"; darwin_min_version_id = "ios"; |