From 94080a0e962a593bb41ebd1eb983daa6cfa5316f Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Fri, 23 Jan 2015 10:38:12 -0800 Subject: [PATCH] Be a bit more explicit about uses of the struct hack. --- src/wren_common.h | 53 +++++++++++++++++++++++++++------------------ src/wren_compiler.c | 1 + src/wren_value.h | 6 ++--- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/wren_common.h b/src/wren_common.h index 747c01bb..d1511dab 100644 --- a/src/wren_common.h +++ b/src/wren_common.h @@ -27,7 +27,7 @@ // Enabling this speeds up the main dispatch loop a bit, but requires compiler // support. // -// Defaults to on. +// Defaults to on on supported compilers. #ifndef WREN_COMPUTED_GOTO #ifdef _MSC_VER // No computed gotos in Visual Studio. @@ -94,6 +94,23 @@ // field index*. #define MAX_FIELDS 255 +// The Microsoft compiler does not support the "inline" modifier when compiling +// as plain C. +#if defined( _MSC_VER ) && !defined(__cplusplus) +#define inline _inline +#endif + +// This is used to clearly mark flexible-sized arrays that appear at the end of +// some dynamically-allocated structs, known as the "struct hack". +#if __STDC_VERSION__ >= 199901L +// In C99, a flexible array member is just "[]". +#define FLEXIBLE_ARRAY +#else +// Elsewhere, use a zero-sized array. It's technically undefined behavior, but +// works reliably in most known compilers. +#define FLEXIBLE_ARRAY 0 +#endif + // Assertions are used to validate program invariants. They indicate things the // program expects to be true about its internal state during execution. If an // assertion fails, there is a bug in Wren. @@ -104,26 +121,26 @@ #include #define ASSERT(condition, message) \ - do \ - { \ - if (!(condition)) \ + do \ { \ - fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \ - __FILE__, __LINE__, __func__, message); \ - abort(); \ + if (!(condition)) \ + { \ + fprintf(stderr, "[%s:%d] Assert failed in %s(): %s\n", \ + __FILE__, __LINE__, __func__, message); \ + abort(); \ + } \ } \ - } \ - while(0) + while(0) // Assertion to indicate that the given point in the code should never be // reached. #define UNREACHABLE() \ - do \ - { \ - fprintf(stderr, "This line should not be reached.\n"); \ - abort(); \ - } \ - while (0) + do \ + { \ + fprintf(stderr, "This line should not be reached.\n"); \ + abort(); \ + } \ + while (0) #else @@ -132,10 +149,4 @@ #endif -// The Microsoft compiler does not sport the "inline" modifier when -// compiling in plain-C -#if defined( _MSC_VER ) && !defined(__cplusplus) - #define inline _inline -#endif - #endif diff --git a/src/wren_compiler.c b/src/wren_compiler.c index e305598e..78297493 100644 --- a/src/wren_compiler.c +++ b/src/wren_compiler.c @@ -2808,6 +2808,7 @@ void definition(Compiler* compiler) classDefinition(compiler); return; } + if (match(compiler, TOKEN_VAR)) { variableDefinition(compiler); return; diff --git a/src/wren_value.h b/src/wren_value.h index 345bd647..a29a0290 100644 --- a/src/wren_value.h +++ b/src/wren_value.h @@ -112,7 +112,7 @@ typedef struct Obj obj; // Does not include the null terminator. int length; - char value[0]; + char value[FLEXIBLE_ARRAY]; } ObjString; // The dynamically allocated data structure for a variable that has been used @@ -260,7 +260,7 @@ typedef struct ObjFn* fn; // The upvalues this function has closed over. - Upvalue* upvalues[0]; + Upvalue* upvalues[FLEXIBLE_ARRAY]; } ObjClosure; typedef enum @@ -323,7 +323,7 @@ struct sObjClass typedef struct { Obj obj; - Value fields[0]; + Value fields[FLEXIBLE_ARRAY]; } ObjInstance; typedef struct