From 614c6989d84779f107f50bc4ebc3f6cc2b43b024 Mon Sep 17 00:00:00 2001 From: Giuliano Macedo Date: Mon, 20 Oct 2025 06:24:07 -0300 Subject: [PATCH] Fixed incorrect format strings when using `error_exit`. (#2530) * Fixed incorrect format strings when using `error_exit`. --- src/compiler/asm_target.c | 2 +- src/compiler/compiler.c | 4 ++-- src/compiler/llvm_codegen.c | 2 +- src/compiler/llvm_codegen_expr.c | 2 +- src/compiler/types.c | 2 +- src/utils/common.h | 28 +++++++++++++++++++++++----- src/utils/malloc.c | 4 ++-- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/compiler/asm_target.c b/src/compiler/asm_target.c index 4089884ca..32ff2f6c9 100644 --- a/src/compiler/asm_target.c +++ b/src/compiler/asm_target.c @@ -164,7 +164,7 @@ NEXT: case 0: return arg_type; default: - error_exit("Expected '/' or end: '%s'.", desc); + error_exit("Expected '/' or end: '%s'.", *desc); } } return arg_type; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index c4188e181..3393664b0 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -116,7 +116,7 @@ static void compiler_lex(void) bool loaded = false; const char *error; File *file = source_file_load(source, &loaded, &error); - if (!file) error_exit(error); + if (!file) error_exit("%s", error); if (loaded) continue; Lexer lexer = { .file = file }; lexer_init(&lexer); @@ -401,7 +401,7 @@ void compiler_parse(void) bool loaded = false; const char *error; File *file = source_file_load(source, &loaded, &error); - if (!file) error_exit(error); + if (!file) error_exit("%s", error); if (loaded) continue; if (!parse_file(file)) has_error = true; if (compiler.build.print_input) puts(file->full_path); diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index bcf182b2d..7d8c5b238 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -26,7 +26,7 @@ static void diagnostics_handler(LLVMDiagnosticInfoRef ref, void *context) switch (severity) { case LLVMDSError: - error_exit("LLVM error generating code for %s: %s", ((GenContext *)context)->code_module->name, message); + error_exit("LLVM error generating code for %s: %s", ((GenContext *)context)->code_module->name->module, message); case LLVMDSWarning: severity_name = "warning"; break; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 78abf4143..af96b19f2 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2493,7 +2493,7 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) switch (expr->unary_expr.operator) { case UNARYOP_ERROR: - FATAL_ERROR("Illegal unary op %s", expr->unary_expr.operator); + FATAL_ERROR("Illegal unary op %d", expr->unary_expr.operator); case UNARYOP_PLUS: // Folded UNREACHABLE_VOID diff --git a/src/compiler/types.c b/src/compiler/types.c index 7c22e581f..43563421c 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -84,7 +84,7 @@ Type *type_int_signed_by_bitsize(BitSize bitsize) case 32: return type_int; case 64: return type_long; case 128: return type_i128; - default: FATAL_ERROR("Illegal bitsize %d", bitsize); + default: FATAL_ERROR("Illegal bitsize %llu", (unsigned long long)bitsize); } UNREACHABLE } diff --git a/src/utils/common.h b/src/utils/common.h index 4a5d59e69..899fe152e 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -81,18 +81,35 @@ #define UNUSED __attribute__((unused)) #define NORETURN __attribute__((noreturn)) #define INLINE __attribute__((always_inline)) static inline +#define FORMAT_STR +#define FORMAT(__X__, __Y__) __attribute__((format (printf, __X__, __Y__))) #elif defined(_MSC_VER) #define FALLTHROUGH ((void)0) #define INLINE static __forceinline #define NORETURN __declspec(noreturn) #define UNUSED #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +// On msvc when using /analyze flag it is possible to have printf-style format strings compiler warnings +// by using the SAL annotations, but __attribute__((format (printf, x, y))) syntax is not supported. +#define FORMAT(__X__, __Y__) +#if _MSC_VER >= 1400 + #include + #if _MSC_VER > 1400 + #define FORMAT_STR _Printf_format_string_ + #else + #define FORMAT_STR __format_string + #endif +#else + #define FORMAT_STR +#endif #else #define PACK(__Declaration__) __Declaration__ #define INLINE static inline #define FALLTHROUGH ((void)0) #define UNUSED #define NORETURN +#define FORMAT_STR +#define FORMAT(__X__, __Y__) #endif #define INFO_LOG(_string, ...) \ @@ -112,11 +129,11 @@ } while (0) #endif -#define FATAL_ERROR(_string, ...) do { error_exit("\xe2\x9a\xa0\xef\xb8\x8f The compiler encountered an unexpected error: \"%s\".\n\n" \ +#define FATAL_ERROR(_format, ...) do { error_exit("\xe2\x9a\xa0\xef\xb8\x8f The compiler encountered an unexpected error: \"" _format "\".\n\n" \ "- Function: %s(...)\n" \ "- Source file: %s:%d\n\n" \ - "\xf0\x9f\x99\x8f Please consider taking the time to file an issue on GitHub, so that we can get it fixed:\n\n" \ - "https://github.com/c3lang/c3c/issues/new so that we can get it fixed.", _string, __func__, __FILE__, __LINE__, ##__VA_ARGS__); } while(0) + "\xf0\x9f\x99\x8f Please consider taking the time to file an issue on GitHub (https://github.com/c3lang/c3c/issues/new), so that we can get it fixed.\n", \ + ##__VA_ARGS__, __func__, __FILE__, __LINE__); } while(0) #define ASSERT(_condition) do { if (!(_condition)) { FATAL_ERROR("Violated assert: " #_condition); } } while (0) @@ -128,7 +145,7 @@ #define UNSUPPORTED do { error_exit("Unsupported functionality"); } while (0) #define TEST_ASSERT(condition_, string_) while (!(condition_)) { FATAL_ERROR(string_); } -#define TEST_ASSERTF(condition_, string_, ...) while (!(condition_)) { char* str_ = str_printf(string_, __VA_ARGS__); FATAL_ERROR(str_); } +#define TEST_ASSERTF(condition_, format_, ...) while (!(condition_)) { FATAL_ERROR(format_, __VA_ARGS__); } #define EXPECT(_string, _value, _expected) \ do { long long __tempval1 = _value; long long __tempval2 = _expected; \ @@ -136,4 +153,5 @@ void evprintf(const char *format, va_list list); void eprintf(const char *format, ...); -NORETURN void error_exit(const char *format, ...); +NORETURN FORMAT(1, 2) void error_exit(FORMAT_STR const char *format, ...); + diff --git a/src/utils/malloc.c b/src/utils/malloc.c index ae147c4ec..59a494a02 100644 --- a/src/utils/malloc.c +++ b/src/utils/malloc.c @@ -89,13 +89,13 @@ void run_arena_allocator_tests(void) void *cmalloc(size_t size) { void *ptr = malloc(size); - if (!ptr) error_exit("Failed to malloc %d bytes.", size); + if (!ptr) error_exit("Failed to malloc %zu bytes.", size); return ptr; } void *ccalloc(size_t size, size_t elements) { void *ptr = calloc(size, elements); - if (!ptr) error_exit("Failed to calloc %d bytes.", size * elements); + if (!ptr) error_exit("Failed to calloc %zu bytes.", size * elements); return ptr; }