Browse Source

Require parentheses for `#align(N)`

gingerBill 2 years ago
parent
commit
2cc22d118d

+ 1 - 1
core/c/libc/setjmp.odin

@@ -63,4 +63,4 @@ foreign libc {
 // strictly conformant C implementation is 16 on the platforms we care about.
 // The choice of 4096 bytes for storage of this type is more than enough on all
 // relevant platforms.
-jmp_buf :: struct #align 16 { _: [4096]char, }
+jmp_buf :: struct #align(16) { _: [4096]char, }

+ 1 - 1
core/c/libc/stdarg.odin

@@ -18,7 +18,7 @@ foreign _ {
 // strictly conformant C implementation is 16 on the platforms we care about.
 // The choice of 4096 bytes for storage of this type is more than enough on all
 // relevant platforms.
-va_list :: struct #align 16 {
+va_list :: struct #align(16) {
 	_: [4096]u8,
 }
 

+ 2 - 2
core/c/libc/time.odin

@@ -35,12 +35,12 @@ when ODIN_OS == .Windows {
 	clock_t        :: distinct long
 	time_t         :: distinct i64
 
-	timespec :: struct #align 8 {
+	timespec :: struct #align(8) {
 		tv_sec:  time_t,
 		tv_nsec: long,
 	}
 
-	tm :: struct #align 8 {
+	tm :: struct #align(8) {
 		tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst: int,
 	}
 }

+ 1 - 1
core/c/libc/wchar.odin

@@ -98,7 +98,7 @@ foreign libc {
 }
 
 // Large enough and aligned enough for any wide-spread in-use libc.
-mbstate_t :: struct #align 16 { _: [32]char, }
+mbstate_t :: struct #align(16) { _: [32]char, }
 
 // Odin does not have default argument promotion so the need for a separate type
 // here isn't necessary, though make it distinct just to be safe.

+ 1 - 1
core/os/os2/heap_linux.odin

@@ -124,7 +124,7 @@ Allocation_Header :: struct #raw_union {
 	requested: u64,
 }
 
-Region_Header :: struct #align 16 {
+Region_Header :: struct #align(16) {
 	next_region:   ^Region,  // points to next region in global_heap (linked list)
 	local_addr:    ^^Region, // tracks region ownership via address of _local_region
 	reset_addr:    ^^Region, // tracks old local addr for reset

+ 4 - 4
core/reflect/types.odin

@@ -580,9 +580,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
 		if info.is_packed    { io.write_string(w, "#packed ",    &n) or_return }
 		if info.is_raw_union { io.write_string(w, "#raw_union ", &n) or_return }
 		if info.custom_align {
-			io.write_string(w, "#align ",      &n) or_return
+			io.write_string(w, "#align(",      &n) or_return
 			io.write_i64(w, i64(ti.align), 10, &n) or_return
-			io.write_byte(w, ' ',              &n) or_return
+			io.write_string(w, ") ",           &n) or_return
 		}
 		io.write_byte(w, '{', &n) or_return
 		for name, i in info.names {
@@ -598,9 +598,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) -
 		if info.no_nil     { io.write_string(w, "#no_nil ", &n)     or_return }
 		if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return }
 		if info.custom_align {
-			io.write_string(w, "#align ",      &n) or_return
+			io.write_string(w, "#align(",      &n) or_return
 			io.write_i64(w, i64(ti.align), 10, &n) or_return
-			io.write_byte(w, ' ',              &n) or_return
+			io.write_string(w, ") ",           &n) or_return
 		}
 		io.write_byte(w, '{', &n) or_return
 		for variant, i in info.variants {

+ 1 - 1
core/runtime/core.odin

@@ -257,7 +257,7 @@ Typeid_Kind :: enum u8 {
 }
 #assert(len(Typeid_Kind) < 32)
 
-// Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
+// Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) {
 // 	index:    8*size_of(uintptr) - 8,
 // 	kind:     5, // Typeid_Kind
 // 	named:    1,

+ 1 - 1
core/runtime/dynamic_map_internal.odin

@@ -87,7 +87,7 @@ MAP_CACHE_LINE_SIZE :: 1 << MAP_CACHE_LINE_LOG2
 //
 // In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated
 // as a regular array of T, which is the case for hashes.
-Map_Cell :: struct($T: typeid) #align MAP_CACHE_LINE_SIZE {
+Map_Cell :: struct($T: typeid) #align(MAP_CACHE_LINE_SIZE) {
 	data: [MAP_CACHE_LINE_SIZE / size_of(T) when 0 < size_of(T) && size_of(T) < MAP_CACHE_LINE_SIZE else 1]T,
 }
 

+ 4 - 3
core/runtime/print.odin

@@ -398,9 +398,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
 		if info.is_packed    { print_string("#packed ") }
 		if info.is_raw_union { print_string("#raw_union ") }
 		if info.custom_align {
-			print_string("#align ")
+			print_string("#align(")
 			print_u64(u64(ti.align))
-			print_byte(' ')
+			print_string(") ")
 		}
 		print_byte('{')
 		for name, i in info.names {
@@ -414,8 +414,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
 	case Type_Info_Union:
 		print_string("union ")
 		if info.custom_align {
-			print_string("#align ")
+			print_string("#align(")
 			print_u64(u64(ti.align))
+			print_string(") ")
 		}
 		if info.no_nil {
 			print_string("#no_nil ")

+ 8 - 8
core/sys/unix/pthread_darwin.odin

@@ -17,42 +17,42 @@ PTHREAD_RWLOCKATTR_SIZE :: 16
 
 pthread_t :: distinct u64
 
-pthread_attr_t :: struct #align 16 {
+pthread_attr_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_ATTR_SIZE] c.char,
 }
 
-pthread_cond_t :: struct #align 16 {
+pthread_cond_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_COND_SIZE] c.char,
 }
 
-pthread_condattr_t :: struct #align 16 {
+pthread_condattr_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_CONDATTR_SIZE] c.char,
 }
 
-pthread_mutex_t :: struct #align 16 {
+pthread_mutex_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_MUTEX_SIZE] c.char,
 }
 
-pthread_mutexattr_t :: struct #align 16 {
+pthread_mutexattr_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_MUTEXATTR_SIZE] c.char,
 }
 
-pthread_once_t :: struct #align 16 {
+pthread_once_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_ONCE_SIZE] c.char,
 }
 
-pthread_rwlock_t :: struct #align 16 {
+pthread_rwlock_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_RWLOCK_SIZE] c.char,
 }
 
-pthread_rwlockattr_t :: struct #align 16 {
+pthread_rwlockattr_t :: struct #align(16) {
 	sig: c.long,
 	_: [PTHREAD_RWLOCKATTR_SIZE] c.char,
 }

+ 10 - 10
core/sys/unix/pthread_freebsd.odin

@@ -4,7 +4,7 @@ package unix
 import "core:c"
 
 pthread_t :: distinct u64
-// pthread_t :: struct #align 16 { x: u64 }
+// pthread_t :: struct #align(16) { x: u64 }
 
 PTHREAD_COND_T_SIZE :: 8
 
@@ -27,32 +27,32 @@ when size_of(int) == 8 {
 	PTHREAD_BARRIER_T_SIZE :: 20
 }
 
-pthread_cond_t :: struct #align 16 {
+pthread_cond_t :: struct #align(16) {
 	_: [PTHREAD_COND_T_SIZE] c.char,
 }
-pthread_mutex_t :: struct #align 16 {
+pthread_mutex_t :: struct #align(16) {
 	_: [PTHREAD_MUTEX_T_SIZE] c.char,
 }
-pthread_rwlock_t :: struct #align 16 {
+pthread_rwlock_t :: struct #align(16) {
 	_: [PTHREAD_RWLOCK_T_SIZE] c.char,
 }
-pthread_barrier_t :: struct #align 16 {
+pthread_barrier_t :: struct #align(16) {
 	_: [PTHREAD_BARRIER_T_SIZE] c.char,
 }
 
-pthread_attr_t :: struct #align 16 {
+pthread_attr_t :: struct #align(16) {
 	_: [PTHREAD_ATTR_T_SIZE] c.char,
 }
-pthread_condattr_t :: struct #align 16 {
+pthread_condattr_t :: struct #align(16) {
 	_: [PTHREAD_CONDATTR_T_SIZE] c.char,
 }
-pthread_mutexattr_t :: struct #align 16 {
+pthread_mutexattr_t :: struct #align(16) {
 	_: [PTHREAD_MUTEXATTR_T_SIZE] c.char,
 }
-pthread_rwlockattr_t :: struct #align 16 {
+pthread_rwlockattr_t :: struct #align(16) {
 	_: [PTHREAD_RWLOCKATTR_T_SIZE] c.char,
 }
-pthread_barrierattr_t :: struct #align 16 {
+pthread_barrierattr_t :: struct #align(16) {
 	_: [PTHREAD_BARRIERATTR_T_SIZE] c.char,
 }
 

+ 11 - 11
core/sys/unix/pthread_linux.odin

@@ -8,7 +8,7 @@ import "core:c"
 // And at the time of writing there is a bug with putting it
 // as the only field in a struct.
 pthread_t :: distinct u64
-// pthread_t :: struct #align 16 { x: u64 };
+// pthread_t :: struct #align(16) { x: u64 };
 
 // NOTE(tetra): Got all the size constants from pthreadtypes-arch.h on my
 // Linux machine.
@@ -34,32 +34,32 @@ when size_of(int) == 8 {
 	PTHREAD_BARRIER_T_SIZE :: 20
 }
 
-pthread_cond_t :: struct #align 16 {
+pthread_cond_t :: struct #align(16) {
 	_: [PTHREAD_COND_T_SIZE] c.char,
 }
-pthread_mutex_t :: struct #align 16 {
+pthread_mutex_t :: struct #align(16) {
 	_: [PTHREAD_MUTEX_T_SIZE] c.char,
 }
-pthread_rwlock_t :: struct #align 16 {
+pthread_rwlock_t :: struct #align(16) {
 	_: [PTHREAD_RWLOCK_T_SIZE] c.char,
 }
-pthread_barrier_t :: struct #align 16 {
+pthread_barrier_t :: struct #align(16) {
 	_: [PTHREAD_BARRIER_T_SIZE] c.char,
 }
 
-pthread_attr_t :: struct #align 16 {
+pthread_attr_t :: struct #align(16) {
 	_: [PTHREAD_ATTR_T_SIZE] c.char,
 }
-pthread_condattr_t :: struct #align 16 {
+pthread_condattr_t :: struct #align(16) {
 	_: [PTHREAD_CONDATTR_T_SIZE] c.char,
 }
-pthread_mutexattr_t :: struct #align 16 {
+pthread_mutexattr_t :: struct #align(16) {
 	_: [PTHREAD_MUTEXATTR_T_SIZE] c.char,
 }
-pthread_rwlockattr_t :: struct #align 16 {
+pthread_rwlockattr_t :: struct #align(16) {
 	_: [PTHREAD_RWLOCKATTR_T_SIZE] c.char,
 }
-pthread_barrierattr_t :: struct #align 16 {
+pthread_barrierattr_t :: struct #align(16) {
 	_: [PTHREAD_BARRIERATTR_T_SIZE] c.char,
 }
 
@@ -84,7 +84,7 @@ sched_param :: struct {
 	sched_priority: c.int,
 }
 
-sem_t :: struct #align 16 {
+sem_t :: struct #align(16) {
 	_: [SEM_T_SIZE] c.char,
 }
 

+ 1 - 1
core/sys/windows/kernel32.odin

@@ -886,7 +886,7 @@ WIN32_MEMORY_REGION_INFORMATION_u_s :: struct {
 	Bitfield: ULONG,
 }
 WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG
-/*bit_field #align align_of(ULONG) {
+/*bit_field #align(align_of(ULONG)) {
 	Private        : 1-0,
 	MappedDataFile : 2-1,
 	MappedImage    : 3-2,

+ 1 - 1
core/thread/thread_unix.odin

@@ -10,7 +10,7 @@ CAS :: intrinsics.atomic_compare_exchange_strong
 
 // NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t.
 // Also see core/sys/darwin/mach_darwin.odin/semaphore_t.
-Thread_Os_Specific :: struct #align 16 {
+Thread_Os_Specific :: struct #align(16) {
 	unix_thread: unix.pthread_t, // NOTE: very large on Darwin, small on Linux.
 	cond:        sync.Cond,
 	mutex:       sync.Mutex,

+ 14 - 0
src/parser.cpp

@@ -2485,6 +2485,13 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 					syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
 				}
 				align = parse_expr(f, true);
+				if (align && align->kind != Ast_ParenExpr) {
+					ERROR_BLOCK();
+					gbString s = expr_to_string(align);
+					syntax_warning(tag, "#align requires parentheses around the expression");
+					error_line("\tSuggestion: #align(%s)", s);
+					gb_string_free(s);
+				}
 			} else if (tag.string == "raw_union") {
 				if (is_raw_union) {
 					syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string));
@@ -2566,6 +2573,13 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
 					syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string));
 				}
 				align = parse_expr(f, true);
+				if (align && align->kind != Ast_ParenExpr) {
+					ERROR_BLOCK();
+					gbString s = expr_to_string(align);
+					syntax_warning(tag, "#align requires parentheses around the expression");
+					error_line("\tSuggestion: #align(%s)", s);
+					gb_string_free(s);
+				}
 			} else if (tag.string == "no_nil") {
 				if (no_nil) {
 					syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string));

+ 1 - 1
vendor/wasm/js/events.odin

@@ -209,7 +209,7 @@ Event :: struct {
 	is_composing: bool,
 	is_trusted:   bool,
 
-	using data: struct #raw_union #align 8 {
+	using data: struct #raw_union #align(8) {
 		scroll: struct {
 			delta: [2]f64,
 		},

+ 1 - 1
vendor/wasm/js/events_all_targets.odin

@@ -208,7 +208,7 @@ Event :: struct {
 	is_composing: bool,
 	is_trusted:   bool,
 
-	using data: struct #raw_union #align 8 {
+	using data: struct #raw_union #align(8) {
 		scroll: struct {
 			delta: [2]f64,
 		},