|
@@ -3392,6 +3392,21 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|
|
check_expr_with_type_hint(c, &x, ce->args[1], elem);
|
|
|
check_assignment(c, &x, elem, builtin_name);
|
|
|
|
|
|
+ Type *t = type_deref(operand->type);
|
|
|
+ switch (id) {
|
|
|
+ case BuiltinProc_atomic_add:
|
|
|
+ case BuiltinProc_atomic_sub:
|
|
|
+ if (!is_type_numeric(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ } else if (is_type_different_to_arch_endianness(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
operand->type = elem;
|
|
|
operand->mode = Addressing_Value;
|
|
|
break;
|
|
@@ -3419,6 +3434,22 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ Type *t = type_deref(operand->type);
|
|
|
+ switch (id) {
|
|
|
+ case BuiltinProc_atomic_add_explicit:
|
|
|
+ case BuiltinProc_atomic_sub_explicit:
|
|
|
+ if (!is_type_numeric(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a numeric type for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ } else if (is_type_different_to_arch_endianness(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a numeric type of the same platform endianness for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
operand->type = elem;
|
|
|
operand->mode = Addressing_Value;
|
|
|
break;
|
|
@@ -3439,6 +3470,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|
|
check_assignment(c, &x, elem, builtin_name);
|
|
|
check_assignment(c, &y, elem, builtin_name);
|
|
|
|
|
|
+ Type *t = type_deref(operand->type);
|
|
|
+ if (!is_type_comparable(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ }
|
|
|
+
|
|
|
operand->mode = Addressing_OptionalOk;
|
|
|
operand->type = elem;
|
|
|
break;
|
|
@@ -3468,6 +3506,13 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ Type *t = type_deref(operand->type);
|
|
|
+ if (!is_type_comparable(t)) {
|
|
|
+ gbString str = type_to_string(t);
|
|
|
+ error(operand->expr, "Expected a comparable type for '%.*s', got %s", LIT(builtin_name), str);
|
|
|
+ gb_string_free(str);
|
|
|
+ }
|
|
|
+
|
|
|
bool invalid_combination = false;
|
|
|
|
|
|
switch (success_memory_order) {
|