mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Improve helpers.h
Use C11 standard _Noreturn instead of attributes (except, of course, MSVC) Remove unused helpers Avoid trapping in release builds, in favor of just unreachability Improve shim when __builtin_* are not available
This commit is contained in:
@@ -55,7 +55,7 @@ void warning(enum WarningID id, const char *fmt, ...);
|
|||||||
* It is also used when the assembler goes into an invalid state (for example,
|
* It is also used when the assembler goes into an invalid state (for example,
|
||||||
* when it fails to allocate memory).
|
* when it fails to allocate memory).
|
||||||
*/
|
*/
|
||||||
noreturn_ void fatalerror(const char *fmt, ...);
|
_Noreturn void fatalerror(const char *fmt, ...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used for errors that make it impossible to assemble correctly, but don't
|
* Used for errors that make it impossible to assemble correctly, but don't
|
||||||
|
|||||||
8
include/extern/err.h
vendored
8
include/extern/err.h
vendored
@@ -34,10 +34,10 @@ void vwarn(const char *fmt, va_list ap) format_(printf, 1, 0);
|
|||||||
void warnx(const char *fmt, ...) format_(printf, 1, 2);
|
void warnx(const char *fmt, ...) format_(printf, 1, 2);
|
||||||
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
|
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
|
||||||
|
|
||||||
noreturn_ void err(int status, const char *fmt, ...) format_(printf, 2, 3);
|
_Noreturn void err(int status, const char *fmt, ...) format_(printf, 2, 3);
|
||||||
noreturn_ void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
_Noreturn void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
||||||
noreturn_ void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
|
_Noreturn void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
|
||||||
noreturn_ void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
_Noreturn void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
||||||
|
|
||||||
#endif /* ERR_IN_LIBC */
|
#endif /* ERR_IN_LIBC */
|
||||||
|
|
||||||
|
|||||||
@@ -9,21 +9,30 @@
|
|||||||
#ifndef HELPERS_H
|
#ifndef HELPERS_H
|
||||||
#define HELPERS_H
|
#define HELPERS_H
|
||||||
|
|
||||||
#ifdef __GNUC__
|
// Of course, MSVC does not support C11, so no _Noreturn there...
|
||||||
/* GCC or compatible */
|
#ifdef _MSC_VER
|
||||||
#define format_(archetype, str_index, first_arg) \
|
#define _Noreturn __declspec(noreturn)
|
||||||
__attribute__ ((format (archetype, str_index, first_arg)))
|
|
||||||
#define noreturn_ __attribute__ ((noreturn))
|
|
||||||
#define trap_ __builtin_trap()
|
|
||||||
#else
|
|
||||||
/* Unsupported, but no need to throw a fit */
|
|
||||||
#define format_(archetype, str_index, first_arg)
|
|
||||||
#define noreturn_
|
|
||||||
#define unused_
|
|
||||||
#define trap_
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Macros for stringification */
|
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
|
||||||
|
#ifdef __GNUC__ // GCC or compatible
|
||||||
|
#define format_(archetype, str_index, first_arg) \
|
||||||
|
__attribute__ ((format (archetype, str_index, first_arg)))
|
||||||
|
// In release builds, define "unreachable" as such, but trap in debug builds
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define unreachable_ __builtin_unreachable
|
||||||
|
#else
|
||||||
|
#define unreachable_ __builtin_trap
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// Unsupported, but no need to throw a fit
|
||||||
|
#define format_(archetype, str_index, first_arg)
|
||||||
|
// This seems to generate similar code to __builtin_unreachable, despite different semantics
|
||||||
|
// Note that executing this is undefined behavior (declared _Noreturn, but does return)
|
||||||
|
static inline _Noreturn unreachable_(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros for stringification
|
||||||
#define STR(x) #x
|
#define STR(x) #x
|
||||||
#define EXPAND_AND_STR(x) STR(x)
|
#define EXPAND_AND_STR(x) STR(x)
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void warning(struct FileStackNode const *where, uint32_t lineNo,
|
|||||||
void error(struct FileStackNode const *where, uint32_t lineNo,
|
void error(struct FileStackNode const *where, uint32_t lineNo,
|
||||||
char const *fmt, ...) format_(printf, 3, 4);
|
char const *fmt, ...) format_(printf, 3, 4);
|
||||||
|
|
||||||
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo,
|
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo,
|
||||||
char const *fmt, ...) format_(printf, 3, 4);
|
char const *fmt, ...) format_(printf, 3, 4);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ void error(const char *fmt, ...)
|
|||||||
nbErrors++;
|
nbErrors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void fatalerror(const char *fmt, ...)
|
_Noreturn void fatalerror(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ void warning(enum WarningID id, char const *fmt, ...)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case WARNING_DEFAULT:
|
case WARNING_DEFAULT:
|
||||||
trap_;
|
unreachable_();
|
||||||
/* Not reached */
|
/* Not reached */
|
||||||
|
|
||||||
case WARNING_ENABLED:
|
case WARNING_ENABLED:
|
||||||
|
|||||||
8
src/extern/err.c
vendored
8
src/extern/err.c
vendored
@@ -34,7 +34,7 @@ void rgbds_vwarnx(const char *fmt, va_list ap)
|
|||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
|
_Noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error: ");
|
fprintf(stderr, "error: ");
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
@@ -46,7 +46,7 @@ noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
|
|||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_verrx(int status, const char *fmt, va_list ap)
|
_Noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error");
|
fprintf(stderr, "error");
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
@@ -75,7 +75,7 @@ void rgbds_warnx(const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_err(int status, const char *fmt, ...)
|
_Noreturn void rgbds_err(int status, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ noreturn_ void rgbds_err(int status, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_errx(int status, const char *fmt, ...)
|
_Noreturn void rgbds_errx(int status, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ void assign_AssignSections(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trap_;
|
unreachable_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign_Cleanup(void)
|
void assign_Cleanup(void)
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ void error(struct FileStackNode const *where, uint32_t lineNo, char const *fmt,
|
|||||||
nbErrors++;
|
nbErrors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
|
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ static void processCommand(enum LinkerScriptCommand command, uint16_t arg,
|
|||||||
{
|
{
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case COMMAND_INVALID:
|
case COMMAND_INVALID:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case COMMAND_ORG:
|
case COMMAND_ORG:
|
||||||
break;
|
break;
|
||||||
@@ -391,12 +391,12 @@ struct SectionPlacement *script_NextSection(void)
|
|||||||
|
|
||||||
switch (parserState) {
|
switch (parserState) {
|
||||||
case PARSER_FIRSTTIME:
|
case PARSER_FIRSTTIME:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case PARSER_LINESTART:
|
case PARSER_LINESTART:
|
||||||
switch (token->type) {
|
switch (token->type) {
|
||||||
case TOKEN_INVALID:
|
case TOKEN_INVALID:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case TOKEN_EOF:
|
case TOKEN_EOF:
|
||||||
if (!popFile())
|
if (!popFile())
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SECTION_NORMAL:
|
case SECTION_NORMAL:
|
||||||
trap_;
|
unreachable_();
|
||||||
}
|
}
|
||||||
|
|
||||||
other->nextu = target->nextu;
|
other->nextu = target->nextu;
|
||||||
|
|||||||
Reference in New Issue
Block a user