Browse Source

Merge branch 'odin-lang:master' into master

elusivePorpoise 3 năm trước cách đây
mục cha
commit
721486f875

+ 8 - 0
.github/workflows/ci.yml

@@ -38,6 +38,10 @@ jobs:
           cd tests/vendor
           make
         timeout-minutes: 10
+      - name: Odin issues tests
+        run: |
+          cd tests/issues
+          ./run.sh
       - name: Odin check examples/all for Linux i386
         run: ./odin check examples/all -vet -strict-style -target:linux_i386
         timeout-minutes: 10
@@ -151,6 +155,10 @@ jobs:
           cd tests\vendor
           call build.bat
         timeout-minutes: 10
+      - name: Odin issues tests
+        run: |
+          cd tests/issues
+          ./run.bat
       - name: core:math/big tests
         shell: cmd
         run: |

+ 8 - 1
core/strconv/strconv.odin

@@ -575,9 +575,11 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
 	i := 0
 
 	sign: f64 = 1
+	seen_sign := true
 	switch s[i] {
 	case '-': i += 1; sign = -1
 	case '+': i += 1
+	case: seen_sign = false
 	}
 
 	for ; i < len(s); i += 1 {
@@ -677,8 +679,13 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
 			for exp >   0 { scale *=   10; exp -=  1 }
 		}
 	}
-	s = s[i:]
 
+	// If we only consumed a sign, return false
+	if i == 1 && seen_sign {
+		return 0, false
+	}
+
+	s = s[i:]
 	if frac {
 		value = sign * (value/scale)
 	} else {

+ 30 - 0
core/sys/windows/advapi32.odin

@@ -128,4 +128,34 @@ foreign advapi32 {
 		lpData: LPCVOID,
 		cbData: DWORD,
 	) -> LSTATUS ---
+
+	GetFileSecurityW :: proc(
+		lpFileName: LPCWSTR,
+		RequestedInformation: SECURITY_INFORMATION,
+		pSecurityDescriptor: PSECURITY_DESCRIPTOR,
+		nLength: DWORD,
+		lpnLengthNeeded: LPDWORD,
+	) -> BOOL ---
+
+	DuplicateToken :: proc(
+		ExistingTokenHandle: HANDLE,
+		ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL,
+		DuplicateTokenHandle: PHANDLE,
+	) -> BOOL ---
+
+	MapGenericMask :: proc(
+		AccessMask: PDWORD,
+		GenericMapping: PGENERIC_MAPPING,
+	) ---
+
+	AccessCheck :: proc(
+		pSecurityDescriptor: PSECURITY_DESCRIPTOR,
+		ClientToken: HANDLE,
+		DesiredAccess: DWORD,
+		GenericMapping: PGENERIC_MAPPING,
+		PrivilegeSet: PPRIVILEGE_SET,
+		PrivilegeSetLength: LPDWORD,
+		GrantedAccess: LPDWORD,
+		AccessStatus: LPBOOL,
+	) -> BOOL ---
 }

+ 9 - 0
core/sys/windows/comctl32.odin

@@ -0,0 +1,9 @@
+// +build windows
+package sys_windows
+
+foreign import "system:Comctl32.lib"
+
+@(default_calling_convention="stdcall")
+foreign Comctl32 {
+	LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT ---
+}

+ 1 - 0
core/sys/windows/gdi32.odin

@@ -77,6 +77,7 @@ foreign gdi32 {
 	) -> HFONT ---
 	TextOutW :: proc(hdc: HDC, x, y: c_int, lpString: LPCWSTR, c: c_int) -> BOOL ---
 	GetTextExtentPoint32W :: proc(hdc: HDC, lpString: LPCWSTR, c: c_int, psizl: LPSIZE) -> BOOL ---
+	GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL ---
 }
 
 RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF {

+ 7 - 0
core/sys/windows/kernel32.odin

@@ -346,6 +346,13 @@ foreign kernel32 {
 	GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL ---
 	FreeConsole :: proc() -> BOOL ---
 	GetConsoleWindow :: proc() -> HWND ---
+
+	GetDiskFreeSpaceExW :: proc(
+		lpDirectoryName: LPCWSTR,
+		lpFreeBytesAvailableToCaller: PULARGE_INTEGER,
+		lpTotalNumberOfBytes: PULARGE_INTEGER,
+		lpTotalNumberOfFreeBytes: PULARGE_INTEGER,
+	) -> BOOL ---
 }
 
 

+ 5 - 0
core/sys/windows/shell32.odin

@@ -14,4 +14,9 @@ foreign shell32 {
 		lpDirectory: LPCWSTR,
 		nShowCmd: INT,
 	) -> HINSTANCE ---
+	SHCreateDirectoryExW :: proc(
+		hwnd: HWND,
+		pszPath: LPCWSTR,
+		psa: ^SECURITY_ATTRIBUTES,
+	) -> c_int ---
 }

+ 1 - 0
core/sys/windows/shlwapi.odin

@@ -8,4 +8,5 @@ foreign shlwapi {
 	PathFileExistsW    :: proc(pszPath: wstring) -> BOOL ---
 	PathFindExtensionW :: proc(pszPath: wstring) -> wstring ---
 	PathFindFileNameW  :: proc(pszPath: wstring) -> wstring ---
+	SHAutoComplete     :: proc(hwndEdit: HWND, dwFlags: DWORD) -> LWSTDAPI ---
 }

+ 143 - 3
core/sys/windows/types.odin

@@ -20,6 +20,7 @@ DWORD :: c_ulong
 DWORDLONG :: c.ulonglong
 QWORD :: c.ulonglong
 HANDLE :: distinct LPVOID
+PHANDLE :: ^HANDLE
 HINSTANCE :: HANDLE
 HMODULE :: distinct HINSTANCE
 HRESULT :: distinct LONG
@@ -43,6 +44,7 @@ BOOLEAN :: distinct b8
 GROUP :: distinct c_uint
 LARGE_INTEGER :: distinct c_longlong
 ULARGE_INTEGER :: distinct c_ulonglong
+PULARGE_INTEGER :: ^ULARGE_INTEGER
 LONG :: c_long
 UINT :: c_uint
 INT  :: c_int
@@ -133,6 +135,11 @@ LPWSAOVERLAPPED :: distinct rawptr
 LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr
 LPCVOID :: rawptr
 
+PACCESS_TOKEN :: PVOID
+PSECURITY_DESCRIPTOR :: PVOID
+PSID :: PVOID
+PCLAIMS_BLOB :: PVOID
+
 PCONDITION_VARIABLE :: ^CONDITION_VARIABLE
 PLARGE_INTEGER :: ^LARGE_INTEGER
 PSRWLOCK :: ^SRWLOCK
@@ -175,6 +182,7 @@ FILE_SHARE_DELETE: DWORD : 0x00000004
 FILE_GENERIC_ALL: DWORD : 0x10000000
 FILE_GENERIC_EXECUTE: DWORD : 0x20000000
 FILE_GENERIC_READ: DWORD : 0x80000000
+FILE_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
 
 FILE_ACTION_ADDED            :: 0x00000001
 FILE_ACTION_REMOVED          :: 0x00000002
@@ -230,6 +238,20 @@ SECURITY_SQOS_PRESENT: DWORD : 0x00100000
 
 FIONBIO: c_ulong : 0x8004667e
 
+OWNER_SECURITY_INFORMATION               :: 0x00000001
+GROUP_SECURITY_INFORMATION               :: 0x00000002
+DACL_SECURITY_INFORMATION                :: 0x00000004
+SACL_SECURITY_INFORMATION                :: 0x00000008
+LABEL_SECURITY_INFORMATION               :: 0x00000010
+ATTRIBUTE_SECURITY_INFORMATION           :: 0x00000020
+SCOPE_SECURITY_INFORMATION               :: 0x00000040
+PROCESS_TRUST_LABEL_SECURITY_INFORMATION :: 0x00000080
+ACCESS_FILTER_SECURITY_INFORMATION       :: 0x00000100
+BACKUP_SECURITY_INFORMATION              :: 0x00010000
+PROTECTED_DACL_SECURITY_INFORMATION      :: 0x80000000
+PROTECTED_SACL_SECURITY_INFORMATION      :: 0x40000000
+UNPROTECTED_DACL_SECURITY_INFORMATION    :: 0x20000000
+UNPROTECTED_SACL_SECURITY_INFORMATION    :: 0x10000000
 
 GET_FILEEX_INFO_LEVELS :: distinct i32
 GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0
@@ -773,6 +795,30 @@ MSG :: struct {
 
 LPMSG :: ^MSG
 
+TEXTMETRICW :: struct {
+	tmHeight: LONG,
+	tmAscent: LONG,
+	tmDescent: LONG,
+	tmInternalLeading: LONG,
+	tmExternalLeading: LONG,
+	tmAveCharWidth: LONG,
+	tmMaxCharWidth: LONG,
+	tmWeight: LONG,
+	tmOverhang: LONG,
+	tmDigitizedAspectX: LONG,
+	tmDigitizedAspectY: LONG,
+	tmFirstChar: WCHAR,
+	tmLastChar: WCHAR,
+	tmDefaultChar: WCHAR,
+	tmBreakChar: WCHAR,
+	tmItalic: BYTE,
+	tmUnderlined: BYTE,
+	tmStruckOut: BYTE,
+	tmPitchAndFamily: BYTE,
+	tmCharSet: BYTE,
+}
+LPTEXTMETRICW :: ^TEXTMETRICW
+
 PAINTSTRUCT :: struct {
 	hdc: HDC,
 	fErase: BOOL,
@@ -1066,8 +1112,14 @@ WS_EX_TOPMOST               : UINT : 0x0000_0008
 WS_EX_TRANSPARENT           : UINT : 0x0000_0020
 WS_EX_WINDOWEDGE            : UINT : 0x0000_0100
 
-PBS_SMOOTH   :: 0x01
-PBS_VERTICAL :: 0x04
+PBS_SMOOTH        :: 0x01
+PBS_VERTICAL      :: 0x04
+PBS_MARQUEE       :: 0x08
+PBS_SMOOTHREVERSE :: 0x10
+
+PBST_NORMAL :: 0x0001
+PBST_ERROR  :: 0x0002
+PBST_PAUSED :: 0x0003
 
 QS_ALLEVENTS      : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY
 QS_ALLINPUT       : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE
@@ -1462,6 +1514,24 @@ IDI_WARNING      := IDI_EXCLAMATION
 IDI_ERROR        := IDI_HAND
 IDI_INFORMATION  := IDI_ASTERISK
 
+IMAGE_BITMAP      :: 0
+IMAGE_ICON        :: 1
+IMAGE_CURSOR      :: 2
+IMAGE_ENHMETAFILE :: 3
+
+LR_DEFAULTCOLOR     :: 0x00000000
+LR_MONOCHROME       :: 0x00000001
+LR_COLOR            :: 0x00000002
+LR_COPYRETURNORG    :: 0x00000004
+LR_COPYDELETEORG    :: 0x00000008
+LR_LOADFROMFILE     :: 0x00000010
+LR_LOADTRANSPARENT  :: 0x00000020
+LR_DEFAULTSIZE      :: 0x00000040
+LR_VGACOLOR         :: 0x00000080
+LR_LOADMAP3DCOLORS  :: 0x00001000
+LR_CREATEDIBSECTION :: 0x00002000
+LR_COPYFROMRESOURCE :: 0x00004000
+LR_SHARED           :: 0x00008000
 
 // DIB color table identifiers
 DIB_RGB_COLORS :: 0
@@ -1774,12 +1844,15 @@ WAIT_FAILED: DWORD : 0xFFFFFFFF
 
 PIPE_ACCESS_INBOUND: DWORD : 0x00000001
 PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002
+PIPE_ACCESS_DUPLEX: DWORD : 0x00000003
 FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000
 FILE_FLAG_OVERLAPPED: DWORD : 0x40000000
 PIPE_WAIT: DWORD : 0x00000000
 PIPE_TYPE_BYTE: DWORD : 0x00000000
+PIPE_TYPE_MESSAGE: DWORD : 0x00000004
 PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008
 PIPE_READMODE_BYTE: DWORD : 0x00000000
+PIPE_READMODE_MESSAGE: DWORD : 0x00000002
 PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000
 
 FD_SETSIZE :: 64
@@ -1793,7 +1866,58 @@ HEAP_ZERO_MEMORY: DWORD : 0x00000008
 HANDLE_FLAG_INHERIT: DWORD : 0x00000001
 HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002
 
-TOKEN_READ: DWORD : 0x20008
+GENERIC_MAPPING :: struct {
+	GenericRead: ACCESS_MASK,
+	GenericWrite: ACCESS_MASK,
+	GenericExecute: ACCESS_MASK,
+	GenericAll: ACCESS_MASK,
+}
+PGENERIC_MAPPING :: ^GENERIC_MAPPING
+
+SECURITY_IMPERSONATION_LEVEL :: enum {
+	SecurityAnonymous,
+	SecurityIdentification,
+	SecurityImpersonation,
+	SecurityDelegation,
+}
+
+SECURITY_INFORMATION :: DWORD
+ANYSIZE_ARRAY :: 1
+
+LUID_AND_ATTRIBUTES :: struct {
+	Luid: LUID,
+	Attributes: DWORD,
+}
+
+PRIVILEGE_SET :: struct {
+	PrivilegeCount: DWORD,
+	Control: DWORD,
+	Privilege: [ANYSIZE_ARRAY]LUID_AND_ATTRIBUTES,
+}
+PPRIVILEGE_SET :: ^PRIVILEGE_SET
+
+// Token Specific Access Rights.
+TOKEN_ASSIGN_PRIMARY    :: 0x0001
+TOKEN_DUPLICATE         :: 0x0002
+TOKEN_IMPERSONATE       :: 0x0004
+TOKEN_QUERY             :: 0x0008
+TOKEN_QUERY_SOURCE      :: 0x0010
+TOKEN_ADJUST_PRIVILEGES :: 0x0020
+TOKEN_ADJUST_GROUPS     :: 0x0040
+TOKEN_ADJUST_DEFAULT    :: 0x0080
+TOKEN_ADJUST_SESSIONID  :: 0x0100
+
+TOKEN_ALL_ACCESS_P :: STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY |\
+	TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT
+
+TOKEN_ALL_ACCESS                :: TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_SESSIONID
+TOKEN_READ                      :: STANDARD_RIGHTS_READ | TOKEN_QUERY
+TOKEN_WRITE                     :: STANDARD_RIGHTS_WRITE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT
+TOKEN_EXECUTE                   :: STANDARD_RIGHTS_EXECUTE
+TOKEN_TRUST_CONSTRAINT_MASK     :: STANDARD_RIGHTS_READ | TOKEN_QUERY | TOKEN_QUERY_SOURCE
+TOKEN_ACCESS_PSEUDO_HANDLE_WIN8 :: TOKEN_QUERY | TOKEN_QUERY_SOURCE
+TOKEN_ACCESS_PSEUDO_HANDLE      :: TOKEN_ACCESS_PSEUDO_HANDLE_WIN8
+
 
 CP_ACP        :: 0     // default to ANSI code page
 CP_OEMCP      :: 1     // default to OEM  code page
@@ -3048,6 +3172,22 @@ SHCONTF_FLATLIST              :: 0x4000
 SHCONTF_ENABLE_ASYNC          :: 0x8000
 SHCONTF_INCLUDESUPERHIDDEN    :: 0x10000
 
+SHACF_DEFAULT               :: 0x00000000  // Currently (SHACF_FILESYSTEM | SHACF_URLALL)
+SHACF_FILESYSTEM            :: 0x00000001  // This includes the File System as well as the rest of the shell (Desktop\My Computer\Control Panel\)
+SHACF_URLALL                :: (SHACF_URLHISTORY | SHACF_URLMRU)
+SHACF_URLHISTORY            :: 0x00000002  // URLs in the User's History
+SHACF_URLMRU                :: 0x00000004  // URLs in the User's Recently Used list.
+SHACF_USETAB                :: 0x00000008  // Use the tab to move thru the autocomplete possibilities instead of to the next dialog/window control.
+SHACF_FILESYS_ONLY          :: 0x00000010  // This includes the File System
+SHACF_FILESYS_DIRS          :: 0x00000020  // Same as SHACF_FILESYS_ONLY except it only includes directories, UNC servers, and UNC server shares.
+SHACF_VIRTUAL_NAMESPACE     :: 0x00000040  // Also include the virtual namespace
+SHACF_AUTOSUGGEST_FORCE_ON  :: 0x10000000  // Ignore the registry default and force the feature on.
+SHACF_AUTOSUGGEST_FORCE_OFF :: 0x20000000  // Ignore the registry default and force the feature off.
+SHACF_AUTOAPPEND_FORCE_ON   :: 0x40000000  // Ignore the registry default and force the feature on. (Also know as AutoComplete)
+SHACF_AUTOAPPEND_FORCE_OFF  :: 0x80000000  // Ignore the registry default and force the feature off. (Also know as AutoComplete)
+
+LWSTDAPI :: HRESULT
+
 CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}}
 CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}}
 

+ 1 - 0
core/sys/windows/user32.odin

@@ -78,6 +78,7 @@ foreign user32 {
 	LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON ---
 	LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR ---
 	LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR ---
+	LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx: c_int, cy: c_int, fuLoad: UINT) -> HANDLE ---
 
 	GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
 	GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---

+ 3 - 0
core/sys/windows/window_messages.odin

@@ -454,6 +454,7 @@ TB_ISBUTTONENABLED                :: 0x0409
 TBM_CLEARTICS                     :: 0x0409
 TTM_SETTOOLINFOA                  :: 0x0409
 CBEM_HASEDITCHANGED               :: 0x040a
+PBM_SETMARQUEE                    :: 0x040a
 RB_INSERTBANDW                    :: 0x040a
 SB_GETRECT                        :: 0x040a
 TB_ISBUTTONCHECKED                :: 0x040a
@@ -488,10 +489,12 @@ TTM_ENUMTOOLSA                    :: 0x040e
 SB_SETICON                        :: 0x040f
 TBM_GETTICPOS                     :: 0x040f
 TTM_GETCURRENTTOOLA               :: 0x040f
+PBM_SETSTATE                      :: 0x0410
 RB_IDTOINDEX                      :: 0x0410
 SB_SETTIPTEXTA                    :: 0x0410
 TBM_GETNUMTICS                    :: 0x0410
 TTM_WINDOWFROMPOINT               :: 0x0410
+PBM_GETSTATE                      :: 0x0411
 RB_GETTOOLTIPS                    :: 0x0411
 SB_SETTIPTEXTW                    :: 0x0411
 TBM_GETSELSTART                   :: 0x0411

+ 18 - 18
src/llvm_abi.cpp

@@ -550,10 +550,10 @@ namespace lbAbiAmd64SysV {
 		if (is_mem_cls(cls, attribute_kind)) {
 			LLVMAttributeRef attribute = nullptr;
 			if (attribute_kind == Amd64TypeAttribute_ByVal) {
-				if (!is_calling_convention_odin(calling_convention)) {
+				// if (!is_calling_convention_odin(calling_convention)) {
 					return lb_arg_type_indirect_byval(c, type);
-				}
-				attribute = nullptr;
+				// }
+				// attribute = nullptr;
 			} else if (attribute_kind == Amd64TypeAttribute_StructRect) {
 				attribute = lb_create_enum_attribute_with_type(c, "sret", type);
 			}
@@ -982,13 +982,13 @@ namespace lbAbiArm64 {
 		}
 		return false;
 	}
-    
-    unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef *base_type_, unsigned member_count_) {
-        return (member_count_ <= 4);
-    }
+
+	unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef base_type, unsigned member_count) {
+		return (member_count <= 4);
+	}
 
 	lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef type, bool return_is_defined) {
-		LLVMTypeRef homo_base_type = {};
+		LLVMTypeRef homo_base_type = nullptr;
 		unsigned homo_member_count = 0;
 
 		if (!return_is_defined) {
@@ -996,16 +996,16 @@ namespace lbAbiArm64 {
 		} else if (is_register(type)) {
 			return non_struct(c, type);
 		} else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) {
-            if(is_homogenous_aggregate_small_enough(&homo_base_type, homo_member_count)) {
-                return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
-            } else {
-                //TODO(Platin): do i need to create stuff that can handle the diffrent return type?
-                //              else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type
-                
-                //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count);
-                LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type);
-                return lb_arg_type_indirect(type, attr);
-            }
+			if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) {
+				return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
+			} else {
+				//TODO(Platin): do i need to create stuff that can handle the diffrent return type?
+				//              else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type
+
+				//LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count);
+				LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type);
+				return lb_arg_type_indirect(type, attr);
+			}
 		} else {
 			i64 size = lb_sizeof(type);
 			if (size <= 16) {

+ 1 - 0
src/llvm_backend_debug.cpp

@@ -293,6 +293,7 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
 	case Type_Named:
 		GB_PANIC("Type_Named should be handled in lb_debug_type separately");
 
+	case Type_SoaPointer:
 	case Type_Pointer:
 		return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0);
 	case Type_MultiPointer:

+ 14 - 0
src/llvm_backend_proc.cpp

@@ -753,12 +753,16 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
 		}
 		GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp));
 
+		lbFunctionType *ft = map_must_get(&p->module->function_type_map, base_type(value.type));
+
 		{
 			unsigned param_count = LLVMCountParamTypes(fnp);
 			GB_ASSERT(arg_count >= param_count);
 
 			LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count);
 			LLVMGetParamTypes(fnp, param_types);
+
+
 			for (unsigned i = 0; i < param_count; i++) {
 				LLVMTypeRef param_type = param_types[i];
 				LLVMTypeRef arg_type = LLVMTypeOf(args[i]);
@@ -776,10 +780,20 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
 
 		LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
 
+		LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
 		if (return_ptr.value != nullptr) {
+			param_offset += 1;
+
 			LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0])));
 		}
 
+		for_array(i, ft->args) {
+			LLVMAttributeRef attribute = ft->args[i].attribute;
+			if (attribute != nullptr) {
+				LLVMAddCallSiteAttribute(ret, param_offset + cast(LLVMAttributeIndex)i, attribute);
+			}
+		}
+
 		switch (inlining) {
 		case ProcInlining_none:
 			break;

+ 12 - 4
tests/issues/run.bat

@@ -1,15 +1,23 @@
 @echo off
 
 if not exist "build\" mkdir build
+pushd build
 
-set COMMON=-collection:tests=..
+set COMMON=-collection:tests=..\..
+
+set ERROR_DID_OCCUR=0
 
 @echo on
 
-..\..\odin test test_issue_829.odin %COMMON% -file
-..\..\odin test test_issue_1592.odin %COMMON% -file
-..\..\odin test test_issue_2087.odin %COMMON% -file
+..\..\..\odin test ..\test_issue_829.odin %COMMON% -file
+..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file
+..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file
+..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug
 
 @echo off
 
+if %ERRORLEVEL% NEQ 0 set ERROR_DID_OCCUR=1
+
+popd
 rmdir /S /Q build
+if %ERROR_DID_OCCUR% NEQ 0 EXIT /B 1

+ 8 - 5
tests/issues/run.sh

@@ -2,15 +2,18 @@
 set -eu
 
 mkdir -p build
-ODIN=../../odin
-COMMON="-collection:tests=.."
+pushd build
+ODIN=../../../odin
+COMMON="-collection:tests=../.."
 
 set -x
 
-$ODIN test test_issue_829.odin  $COMMON -file
-$ODIN test test_issue_1592.odin $COMMON -file
-$ODIN test test_issue_2087.odin $COMMON -file
+$ODIN test ../test_issue_829.odin  $COMMON -file
+$ODIN test ../test_issue_1592.odin $COMMON -file
+$ODIN test ../test_issue_2087.odin $COMMON -file
+$ODIN build ../test_issue_2113.odin $COMMON -file -debug
 
 set +x
 
+popd
 rm -rf build

+ 5 - 1
tests/issues/test_issue_2087.odin

@@ -10,9 +10,13 @@ test_parse_float :: proc(t: ^testing.T) {
 	{
 		f, ok := strconv.parse_f64("1.2")
 		testing.expect(t, ok && f == 1.2, "expected f64(1.2), fully consumed")
-
 		f, ok = strconv.parse_f64("1.2a")
 		testing.expect(t, !ok && f == 1.2, "expected f64(1.2), partially consumed")
+		f, ok = strconv.parse_f64("+")
+		testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
+		f, ok = strconv.parse_f64("-")
+		testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
+
 
 		f, ok = strconv.parse_f64("inf")
 		testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed")

+ 13 - 0
tests/issues/test_issue_2113.odin

@@ -0,0 +1,13 @@
+// Tests issue #2113 https://github.com/odin-lang/Odin/issues/2113
+// Causes a panic on compilation
+package test_issues
+
+T :: struct {
+    a: int,
+}
+
+main :: proc() {
+    array: #soa[1]T
+    a := &array[0]
+    _ = a
+}

+ 3 - 3
vendor/darwin/Foundation/NSApplication.odin

@@ -11,7 +11,7 @@ ActivationPolicy :: enum UInteger {
 ApplicationDelegate :: struct {
 	willFinishLaunching:                  proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
 	didFinishLaunching:                   proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
-	shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application),
+	shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> BOOL,
 
 	user_data: rawptr,
 }
@@ -34,9 +34,9 @@ Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelega
 		del := (^ApplicationDelegate)(self->pointerValue())
 		del->didFinishLaunching(notification)
 	}
-	shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) {
+	shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> BOOL {
 		del := (^ApplicationDelegate)(self->pointerValue())
-		del->shouldTerminateAfterLastWindowClosed(application)
+		return del->shouldTerminateAfterLastWindowClosed(application)
 	}
 
 	wrapper := Value.valueWithPointer(delegate)

+ 16 - 0
vendor/darwin/Foundation/NSWindow.odin

@@ -156,6 +156,22 @@ Window_makeKeyAndOrderFront :: proc(self: ^Window, key: ^NS.Object) {
 Window_setTitle :: proc(self: ^Window, title: ^NS.String) {
 	msgSend(nil, self, "setTitle:", title)
 }
+@(objc_type=Window, objc_name="setTitlebarAppearsTransparent")
+Window_setTitlebarAppearsTransparent :: proc(self: ^Window, ok: NS.BOOL) {
+	msgSend(nil, self, "setTitlebarAppearsTransparent:", ok)
+}
+@(objc_type=Window, objc_name="setMovable")
+Window_setMovable :: proc(self: ^Window, ok: NS.BOOL) {
+	msgSend(nil, self, "setMovable:", ok)
+}
+@(objc_type=Window, objc_name="setMovableByWindowBackground")
+Window_setMovableByWindowBackground :: proc(self: ^Window, ok: NS.BOOL) {
+	msgSend(nil, self, "setMovableByWindowBackground:", ok)
+}
+@(objc_type=Window, objc_name="setStyleMask")
+Window_setStyleMask :: proc(self: ^Window, style_mask: WindowStyleMask) {
+	msgSend(nil, self, "setStyleMask:", style_mask)
+}
 @(objc_type=Window, objc_name="close")
 Window_close :: proc(self: ^Window) {
 	msgSend(nil, self, "close")

+ 3 - 0
vendor/darwin/Foundation/objc.odin

@@ -13,6 +13,9 @@ foreign Foundation {
 	objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) ---
 
 	class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL ---
+	class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method ---
+
+	method_setImplementation :: proc "c" (method: Method, imp: IMP) ---
 }
 
 

+ 0 - 33
vendor/glfw/native.odin

@@ -1,33 +0,0 @@
-package glfw
-
-when ODIN_OS == .Windows {
-	import win32 "core:sys/windows"
-	
-	foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" }
-	
-	@(default_calling_convention="c", link_prefix="glfw")
-	foreign glfw {
-		GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring ---
-		GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring ---
-		GetWin32Window  :: proc(window: WindowHandle) -> win32.HWND ---
-		GetWGLContext   :: proc(window: WindowHandle) -> rawptr ---
-	}
-} else when ODIN_OS == .Linux {
-	// TODO: Native Linux
-	// Display* glfwGetX11Display(void);
-	// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
-	// RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
-	// Window glfwGetX11Window(GLFWwindow* window);
-	// void glfwSetX11SelectionString(const char* string);
-	// const char* glfwGetX11SelectionString(void);
-	
-	// struct wl_display* glfwGetWaylandDisplay(void);
-	// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
-	// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
-} else when ODIN_OS == .Darwin {
-	// TODO: Native Darwin
-	// CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
-	// id glfwGetCocoaWindow(GLFWwindow* window);
-	// id glfwGetNSGLContext(GLFWwindow* window);
-}
-

+ 16 - 0
vendor/glfw/native_darwin.odin

@@ -0,0 +1,16 @@
+//+build darwin
+
+package glfw
+
+import NS "vendor:darwin/foundation"
+
+foreign import glfw { "lib/darwin/libglfw3.a" }
+
+@(default_calling_convention="c", link_prefix="glfw")
+foreign glfw {
+    GetCocoaWindow :: proc(window: WindowHandle) -> ^NS.Window ---
+}
+
+// TODO:
+// CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
+// id glfwGetNSGLContext(GLFWwindow* window);

+ 15 - 0
vendor/glfw/native_linux.odin

@@ -0,0 +1,15 @@
+//+build linux
+
+package glfw
+
+// TODO: Native Linux
+// Display* glfwGetX11Display(void);
+// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
+// RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
+// Window glfwGetX11Window(GLFWwindow* window);
+// void glfwSetX11SelectionString(const char* string);
+// const char* glfwGetX11SelectionString(void);
+
+// struct wl_display* glfwGetWaylandDisplay(void);
+// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
+// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);

+ 15 - 0
vendor/glfw/native_windows.odin

@@ -0,0 +1,15 @@
+//+build windows
+
+package glfw
+
+import win32 "core:sys/windows"
+
+foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" }
+
+@(default_calling_convention="c", link_prefix="glfw")
+foreign glfw {
+    GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring ---
+    GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring ---
+    GetWin32Window  :: proc(window: WindowHandle) -> win32.HWND ---
+    GetWGLContext   :: proc(window: WindowHandle) -> rawptr ---
+}