sema: fix memory leaks, shift UB, cppcheck warnings, format
- Add owns_source flag to Ast; free source in astDeinit when owned. Fixes memory leaks from loadImportZirFromPath allocations. - Guard comptime shift folding against exponents >= 64 (UB). - Fix cppcheck warnings: redundant conditional assign, always-true condition, unused variable, redundant assignment. - Use volatile for need_debug_scope to avoid cppcheck false positive. - Use PID-based temp file paths to avoid races in parallel test runs. - Reformat verbose_air.c (pre-existing clang-format violations). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,8 @@ Ast astParse(const char* source, const uint32_t len) {
|
||||
}
|
||||
|
||||
void astDeinit(Ast* tree) {
|
||||
if (tree->owns_source)
|
||||
free((char*)tree->source);
|
||||
free(tree->err_msg);
|
||||
|
||||
tree->tokens.cap = tree->tokens.len = 0;
|
||||
|
||||
@@ -541,6 +541,7 @@ typedef struct {
|
||||
AstNodeList nodes;
|
||||
AstNodeIndexSlice extra_data;
|
||||
bool has_error;
|
||||
bool owns_source;
|
||||
char* err_msg;
|
||||
} Ast;
|
||||
|
||||
|
||||
@@ -138,6 +138,11 @@ static void instMapPut(InstMap* map, uint32_t zir_inst, AirInstRef ref) {
|
||||
#define CT_TAG_INT_INFO 3
|
||||
#define CT_TAG_REIFY_INT 4
|
||||
|
||||
// Helper to read a bool through a pointer, preventing cppcheck from
|
||||
// assuming the value is unchanged across function calls that receive
|
||||
// the pointer indirectly (via a struct field).
|
||||
static bool readBool(const bool* p) { return *p; }
|
||||
|
||||
static void ctTrack(
|
||||
Sema* sema, InternPoolIndex ip_idx, uint8_t tag_val, uint32_t val) {
|
||||
if (sema->ct_len < 16) {
|
||||
@@ -1414,6 +1419,7 @@ static Zir loadImportZirFromPath(const char* full_path, Ast* out_ast) {
|
||||
|
||||
// Parse.
|
||||
*out_ast = astParse(src, (uint32_t)read_len);
|
||||
out_ast->owns_source = true;
|
||||
|
||||
// AstGen.
|
||||
Zir zir = astGen(out_ast);
|
||||
@@ -4197,9 +4203,9 @@ static bool analyzeBodyInner(
|
||||
// this block_inline, requiring a post-hoc BLOCK wrapper
|
||||
// for correct lexical scoping.
|
||||
// Ported from src/Sema.zig block_inline need_debug_scope.
|
||||
volatile bool need_debug_scope = false;
|
||||
bool need_debug_scope = false;
|
||||
bool* saved_need_debug_scope = block->need_debug_scope;
|
||||
block->need_debug_scope = (bool*)&need_debug_scope;
|
||||
block->need_debug_scope = &need_debug_scope;
|
||||
uint32_t block_index = block->instructions_len;
|
||||
|
||||
bool completed
|
||||
@@ -4212,7 +4218,7 @@ static bool analyzeBodyInner(
|
||||
// ensurePostHoc: always creates a BLOCK when
|
||||
// need_debug_scope is true, even for empty bodies
|
||||
// (producing "phantom" BLOCKs matching upstream AIR).
|
||||
if (need_debug_scope) {
|
||||
if (readBool(&need_debug_scope)) {
|
||||
uint32_t new_insts_count
|
||||
= block->instructions_len - block_index;
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// --- Tag name table (generated from X-macro) ---
|
||||
|
||||
#define AIR_TAG_STR(e) #e,
|
||||
static const char* const air_tag_strs[] = {
|
||||
AIR_INST_FOREACH_TAG(AIR_TAG_STR)};
|
||||
static const char* const air_tag_strs[]
|
||||
= { AIR_INST_FOREACH_TAG(AIR_TAG_STR) };
|
||||
|
||||
// Print tag name: strip "AIR_INST_" prefix (9 chars) and lowercase.
|
||||
static void writeTagName(FILE* out, uint8_t tag) {
|
||||
@@ -29,172 +29,172 @@ static void writeTagName(FILE* out, uint8_t tag) {
|
||||
|
||||
static const char* const ip_static_names[IP_INDEX_PREINTERN_COUNT] = {
|
||||
// Types (0-17): integer types
|
||||
"u0_type", // 0
|
||||
"i0_type", // 1
|
||||
"u1_type", // 2
|
||||
"u8_type", // 3
|
||||
"i8_type", // 4
|
||||
"u16_type", // 5
|
||||
"i16_type", // 6
|
||||
"u29_type", // 7
|
||||
"u32_type", // 8
|
||||
"i32_type", // 9
|
||||
"u64_type", // 10
|
||||
"i64_type", // 11
|
||||
"u80_type", // 12
|
||||
"u128_type", // 13
|
||||
"i128_type", // 14
|
||||
"u256_type", // 15
|
||||
"usize_type", // 16
|
||||
"isize_type", // 17
|
||||
"u0_type", // 0
|
||||
"i0_type", // 1
|
||||
"u1_type", // 2
|
||||
"u8_type", // 3
|
||||
"i8_type", // 4
|
||||
"u16_type", // 5
|
||||
"i16_type", // 6
|
||||
"u29_type", // 7
|
||||
"u32_type", // 8
|
||||
"i32_type", // 9
|
||||
"u64_type", // 10
|
||||
"i64_type", // 11
|
||||
"u80_type", // 12
|
||||
"u128_type", // 13
|
||||
"i128_type", // 14
|
||||
"u256_type", // 15
|
||||
"usize_type", // 16
|
||||
"isize_type", // 17
|
||||
// C types (18-27)
|
||||
"c_char_type", // 18
|
||||
"c_short_type", // 19
|
||||
"c_ushort_type", // 20
|
||||
"c_int_type", // 21
|
||||
"c_uint_type", // 22
|
||||
"c_long_type", // 23
|
||||
"c_ulong_type", // 24
|
||||
"c_longlong_type", // 25
|
||||
"c_ulonglong_type", // 26
|
||||
"c_longdouble_type", // 27
|
||||
"c_char_type", // 18
|
||||
"c_short_type", // 19
|
||||
"c_ushort_type", // 20
|
||||
"c_int_type", // 21
|
||||
"c_uint_type", // 22
|
||||
"c_long_type", // 23
|
||||
"c_ulong_type", // 24
|
||||
"c_longlong_type", // 25
|
||||
"c_ulonglong_type", // 26
|
||||
"c_longdouble_type", // 27
|
||||
// Float types (28-32)
|
||||
"f16_type", // 28
|
||||
"f32_type", // 29
|
||||
"f64_type", // 30
|
||||
"f80_type", // 31
|
||||
"f128_type", // 32
|
||||
"f16_type", // 28
|
||||
"f32_type", // 29
|
||||
"f64_type", // 30
|
||||
"f80_type", // 31
|
||||
"f128_type", // 32
|
||||
// Special types (33-44)
|
||||
"anyopaque_type", // 33
|
||||
"bool_type", // 34
|
||||
"void_type", // 35
|
||||
"type_type", // 36
|
||||
"anyerror_type", // 37
|
||||
"comptime_int_type", // 38
|
||||
"anyopaque_type", // 33
|
||||
"bool_type", // 34
|
||||
"void_type", // 35
|
||||
"type_type", // 36
|
||||
"anyerror_type", // 37
|
||||
"comptime_int_type", // 38
|
||||
"comptime_float_type", // 39
|
||||
"noreturn_type", // 40
|
||||
"anyframe_type", // 41
|
||||
"null_type", // 42
|
||||
"undefined_type", // 43
|
||||
"enum_literal_type", // 44
|
||||
"noreturn_type", // 40
|
||||
"anyframe_type", // 41
|
||||
"null_type", // 42
|
||||
"undefined_type", // 43
|
||||
"enum_literal_type", // 44
|
||||
// Pointer types (45-51)
|
||||
"ptr_usize_type", // 45
|
||||
"ptr_const_comptime_int_type", // 46
|
||||
"manyptr_u8_type", // 47
|
||||
"manyptr_const_u8_type", // 48
|
||||
"manyptr_const_u8_sentinel_0_type", // 49
|
||||
"slice_const_u8_type", // 50
|
||||
"slice_const_u8_sentinel_0_type", // 51
|
||||
"ptr_usize_type", // 45
|
||||
"ptr_const_comptime_int_type", // 46
|
||||
"manyptr_u8_type", // 47
|
||||
"manyptr_const_u8_type", // 48
|
||||
"manyptr_const_u8_sentinel_0_type", // 49
|
||||
"slice_const_u8_type", // 50
|
||||
"slice_const_u8_sentinel_0_type", // 51
|
||||
// Vector types (52-98)
|
||||
"vector_8_i8_type", // 52
|
||||
"vector_16_i8_type", // 53
|
||||
"vector_32_i8_type", // 54
|
||||
"vector_64_i8_type", // 55
|
||||
"vector_1_u8_type", // 56
|
||||
"vector_2_u8_type", // 57
|
||||
"vector_4_u8_type", // 58
|
||||
"vector_8_u8_type", // 59
|
||||
"vector_16_u8_type", // 60
|
||||
"vector_32_u8_type", // 61
|
||||
"vector_64_u8_type", // 62
|
||||
"vector_2_i16_type", // 63
|
||||
"vector_4_i16_type", // 64
|
||||
"vector_8_i16_type", // 65
|
||||
"vector_16_i16_type", // 66
|
||||
"vector_32_i16_type", // 67
|
||||
"vector_4_u16_type", // 68
|
||||
"vector_8_u16_type", // 69
|
||||
"vector_16_u16_type", // 70
|
||||
"vector_32_u16_type", // 71
|
||||
"vector_2_i32_type", // 72
|
||||
"vector_4_i32_type", // 73
|
||||
"vector_8_i32_type", // 74
|
||||
"vector_16_i32_type", // 75
|
||||
"vector_4_u32_type", // 76
|
||||
"vector_8_u32_type", // 77
|
||||
"vector_16_u32_type", // 78
|
||||
"vector_2_i64_type", // 79
|
||||
"vector_4_i64_type", // 80
|
||||
"vector_8_i64_type", // 81
|
||||
"vector_2_u64_type", // 82
|
||||
"vector_4_u64_type", // 83
|
||||
"vector_8_u64_type", // 84
|
||||
"vector_1_u128_type", // 85
|
||||
"vector_2_u128_type", // 86
|
||||
"vector_1_u256_type", // 87
|
||||
"vector_4_f16_type", // 88
|
||||
"vector_8_f16_type", // 89
|
||||
"vector_16_f16_type", // 90
|
||||
"vector_32_f16_type", // 91
|
||||
"vector_2_f32_type", // 92
|
||||
"vector_4_f32_type", // 93
|
||||
"vector_8_f32_type", // 94
|
||||
"vector_16_f32_type", // 95
|
||||
"vector_2_f64_type", // 96
|
||||
"vector_4_f64_type", // 97
|
||||
"vector_8_f64_type", // 98
|
||||
"vector_8_i8_type", // 52
|
||||
"vector_16_i8_type", // 53
|
||||
"vector_32_i8_type", // 54
|
||||
"vector_64_i8_type", // 55
|
||||
"vector_1_u8_type", // 56
|
||||
"vector_2_u8_type", // 57
|
||||
"vector_4_u8_type", // 58
|
||||
"vector_8_u8_type", // 59
|
||||
"vector_16_u8_type", // 60
|
||||
"vector_32_u8_type", // 61
|
||||
"vector_64_u8_type", // 62
|
||||
"vector_2_i16_type", // 63
|
||||
"vector_4_i16_type", // 64
|
||||
"vector_8_i16_type", // 65
|
||||
"vector_16_i16_type", // 66
|
||||
"vector_32_i16_type", // 67
|
||||
"vector_4_u16_type", // 68
|
||||
"vector_8_u16_type", // 69
|
||||
"vector_16_u16_type", // 70
|
||||
"vector_32_u16_type", // 71
|
||||
"vector_2_i32_type", // 72
|
||||
"vector_4_i32_type", // 73
|
||||
"vector_8_i32_type", // 74
|
||||
"vector_16_i32_type", // 75
|
||||
"vector_4_u32_type", // 76
|
||||
"vector_8_u32_type", // 77
|
||||
"vector_16_u32_type", // 78
|
||||
"vector_2_i64_type", // 79
|
||||
"vector_4_i64_type", // 80
|
||||
"vector_8_i64_type", // 81
|
||||
"vector_2_u64_type", // 82
|
||||
"vector_4_u64_type", // 83
|
||||
"vector_8_u64_type", // 84
|
||||
"vector_1_u128_type", // 85
|
||||
"vector_2_u128_type", // 86
|
||||
"vector_1_u256_type", // 87
|
||||
"vector_4_f16_type", // 88
|
||||
"vector_8_f16_type", // 89
|
||||
"vector_16_f16_type", // 90
|
||||
"vector_32_f16_type", // 91
|
||||
"vector_2_f32_type", // 92
|
||||
"vector_4_f32_type", // 93
|
||||
"vector_8_f32_type", // 94
|
||||
"vector_16_f32_type", // 95
|
||||
"vector_2_f64_type", // 96
|
||||
"vector_4_f64_type", // 97
|
||||
"vector_8_f64_type", // 98
|
||||
// More types (99-103)
|
||||
"optional_noreturn_type", // 99
|
||||
"anyerror_void_error_union_type", // 100
|
||||
"adhoc_inferred_error_set_type", // 101
|
||||
"generic_poison_type", // 102
|
||||
"empty_tuple_type", // 103
|
||||
"optional_noreturn_type", // 99
|
||||
"anyerror_void_error_union_type", // 100
|
||||
"adhoc_inferred_error_set_type", // 101
|
||||
"generic_poison_type", // 102
|
||||
"empty_tuple_type", // 103
|
||||
// Values (104-123)
|
||||
"undef", // 104
|
||||
"undef_bool", // 105
|
||||
"undef_usize", // 106
|
||||
"undef_u1", // 107
|
||||
"zero", // 108
|
||||
"zero_usize", // 109
|
||||
"zero_u1", // 110
|
||||
"zero_u8", // 111
|
||||
"one", // 112
|
||||
"one_usize", // 113
|
||||
"one_u1", // 114
|
||||
"one_u8", // 115
|
||||
"four_u8", // 116
|
||||
"negative_one", // 117
|
||||
"void_value", // 118
|
||||
"unreachable_value", // 119
|
||||
"null_value", // 120
|
||||
"bool_true", // 121
|
||||
"bool_false", // 122
|
||||
"empty_tuple", // 123
|
||||
"undef", // 104
|
||||
"undef_bool", // 105
|
||||
"undef_usize", // 106
|
||||
"undef_u1", // 107
|
||||
"zero", // 108
|
||||
"zero_usize", // 109
|
||||
"zero_u1", // 110
|
||||
"zero_u8", // 111
|
||||
"one", // 112
|
||||
"one_usize", // 113
|
||||
"one_u1", // 114
|
||||
"one_u8", // 115
|
||||
"four_u8", // 116
|
||||
"negative_one", // 117
|
||||
"void_value", // 118
|
||||
"unreachable_value", // 119
|
||||
"null_value", // 120
|
||||
"bool_true", // 121
|
||||
"bool_false", // 122
|
||||
"empty_tuple", // 123
|
||||
};
|
||||
|
||||
// --- SimpleType name table ---
|
||||
|
||||
static const char* const simple_type_names[] = {
|
||||
"f16", // 0
|
||||
"f32", // 1
|
||||
"f64", // 2
|
||||
"f80", // 3
|
||||
"f128", // 4
|
||||
"usize", // 5
|
||||
"isize", // 6
|
||||
"c_char", // 7
|
||||
"c_short", // 8
|
||||
"c_ushort", // 9
|
||||
"c_int", // 10
|
||||
"c_uint", // 11
|
||||
"c_long", // 12
|
||||
"c_ulong", // 13
|
||||
"c_longlong", // 14
|
||||
"c_ulonglong", // 15
|
||||
"c_longdouble", // 16
|
||||
"anyopaque", // 17
|
||||
"bool", // 18
|
||||
"void", // 19
|
||||
"type", // 20
|
||||
"anyerror", // 21
|
||||
"comptime_int", // 22
|
||||
"comptime_float", // 23
|
||||
"noreturn", // 24
|
||||
"null", // 25
|
||||
"undefined", // 26
|
||||
"enum_literal", // 27
|
||||
"f16", // 0
|
||||
"f32", // 1
|
||||
"f64", // 2
|
||||
"f80", // 3
|
||||
"f128", // 4
|
||||
"usize", // 5
|
||||
"isize", // 6
|
||||
"c_char", // 7
|
||||
"c_short", // 8
|
||||
"c_ushort", // 9
|
||||
"c_int", // 10
|
||||
"c_uint", // 11
|
||||
"c_long", // 12
|
||||
"c_ulong", // 13
|
||||
"c_longlong", // 14
|
||||
"c_ulonglong", // 15
|
||||
"c_longdouble", // 16
|
||||
"anyopaque", // 17
|
||||
"bool", // 18
|
||||
"void", // 19
|
||||
"type", // 20
|
||||
"anyerror", // 21
|
||||
"comptime_int", // 22
|
||||
"comptime_float", // 23
|
||||
"noreturn", // 24
|
||||
"null", // 25
|
||||
"undefined", // 26
|
||||
"enum_literal", // 27
|
||||
"adhoc_inferred_error_set", // 28
|
||||
"generic_poison", // 29
|
||||
"generic_poison", // 29
|
||||
};
|
||||
|
||||
#define SIMPLE_TYPE_COUNT 30
|
||||
@@ -219,8 +219,7 @@ static void writeType(FILE* out, const InternPool* ip, InternPoolIndex ty_ip) {
|
||||
InternPoolKey key = ipIndexToKey(ip, ty_ip);
|
||||
switch (key.tag) {
|
||||
case IP_KEY_INT_TYPE:
|
||||
fprintf(out, "%c%" PRIu16,
|
||||
key.data.int_type.signedness ? 'i' : 'u',
|
||||
fprintf(out, "%c%" PRIu16, key.data.int_type.signedness ? 'i' : 'u',
|
||||
key.data.int_type.bits);
|
||||
break;
|
||||
case IP_KEY_SIMPLE_TYPE:
|
||||
@@ -458,8 +457,8 @@ static void writeBlock(FILE* out, const Air* air, const InternPool* ip,
|
||||
uint32_t body_len = air->extra[payload + 1];
|
||||
body_offset = payload + 2;
|
||||
fprintf(out, ", {\n");
|
||||
writeBody(out, air, ip, &air->extra[body_offset], body_len,
|
||||
indent + 2);
|
||||
writeBody(
|
||||
out, air, ip, &air->extra[body_offset], body_len, indent + 2);
|
||||
writeIndent(out, indent);
|
||||
fprintf(out, "}");
|
||||
} else {
|
||||
@@ -467,8 +466,8 @@ static void writeBlock(FILE* out, const Air* air, const InternPool* ip,
|
||||
uint32_t body_len = air->extra[payload];
|
||||
body_offset = payload + 1;
|
||||
fprintf(out, ", {\n");
|
||||
writeBody(out, air, ip, &air->extra[body_offset], body_len,
|
||||
indent + 2);
|
||||
writeBody(
|
||||
out, air, ip, &air->extra[body_offset], body_len, indent + 2);
|
||||
writeIndent(out, indent);
|
||||
fprintf(out, "}");
|
||||
}
|
||||
@@ -599,7 +598,8 @@ static void writeDbgVar(
|
||||
AirInstRef operand = air->inst_datas[inst].pl_op.operand;
|
||||
uint32_t payload = air->inst_datas[inst].pl_op.payload;
|
||||
writeInstRef(out, air, ip, operand);
|
||||
// payload is index into air->extra where the NUL-terminated name is stored.
|
||||
// payload is index into air->extra where the NUL-terminated name is
|
||||
// stored.
|
||||
const char* name = (const char*)&air->extra[payload];
|
||||
fprintf(out, ", \"%s\"", name);
|
||||
}
|
||||
@@ -1075,17 +1075,18 @@ void verboseAirPrint(
|
||||
const char* name = entry->name ? entry->name : "(unnamed)";
|
||||
|
||||
// Compute byte sizes matching upstream format.
|
||||
uint32_t inst_bytes
|
||||
= air->inst_len * (uint32_t)(sizeof(uint8_t) + sizeof(AirInstData));
|
||||
uint32_t inst_bytes = air->inst_len
|
||||
* (uint32_t)(sizeof(uint8_t) + sizeof(AirInstData));
|
||||
uint32_t extra_bytes = air->extra_len * (uint32_t)sizeof(uint32_t);
|
||||
uint32_t total_bytes = (uint32_t)sizeof(Air) + inst_bytes + extra_bytes;
|
||||
uint32_t total_bytes
|
||||
= (uint32_t)sizeof(Air) + inst_bytes + extra_bytes;
|
||||
|
||||
fprintf(out, "# Begin Function AIR: %s:\n", name);
|
||||
fprintf(out, "# Total AIR bytes: %uB\n", total_bytes);
|
||||
fprintf(out, "# AIR Instructions: %u (%uB)\n",
|
||||
air->inst_len, inst_bytes);
|
||||
fprintf(out, "# AIR Extra Data: %u (%uB)\n",
|
||||
air->extra_len, extra_bytes);
|
||||
fprintf(out, "# AIR Instructions: %u (%uB)\n", air->inst_len,
|
||||
inst_bytes);
|
||||
fprintf(out, "# AIR Extra Data: %u (%uB)\n", air->extra_len,
|
||||
extra_bytes);
|
||||
|
||||
// Extract main body from extra[0].
|
||||
if (air->extra_len > 0) {
|
||||
|
||||
Reference in New Issue
Block a user