]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Merge branch 'cooking'
authorDale Weiler <killfieldengine@gmail.com>
Thu, 31 Oct 2013 12:22:54 +0000 (08:22 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Thu, 31 Oct 2013 12:22:54 +0000 (08:22 -0400)
16 files changed:
ansi.c
ast.c
ast.h
fold.c
ftepp.c
gmqcc.h
ir.c
ir.h
msvc.c
parser.c
parser.h
platform.h
test.c
tests/dots.qc [new file with mode: 0644]
tests/dots.tmpl [new file with mode: 0644]
util.c

diff --git a/ansi.c b/ansi.c
index 73792aa043b9695d3cd4f8ae24ba05053df6c665..3cf4508a31f604363b4609b714ccc2506dbc938d 100644 (file)
--- a/ansi.c
+++ b/ansi.c
@@ -23,7 +23,6 @@
 #define GMQCC_PLATFORM_HEADER
 #include <string.h>
 #include <stdlib.h>
-#include <unistd.h>
 
 #include "platform.h"
 #include "gmqcc.h"
@@ -48,10 +47,6 @@ char *platform_strncat(char *dest, const char *src, size_t num) {
     return strncat(dest, src, num);
 }
 
-const char *platform_tmpnam(char *str) {
-    return tmpnam(str);
-}
-
 const char *platform_getenv(const char *var) {
     return getenv(var);
 }
diff --git a/ast.c b/ast.c
index 6bc6af43b566358187ba05d0cf2a00abab16ecde..3c70a73721e49e726c1e010b3bbc0b77e94bc225 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1207,9 +1207,6 @@ ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype
     self->fixedparams      = NULL;
     self->return_value     = NULL;
 
-    self->accumulate   = NULL;
-    self->accumulation = 0;
-
     return self;
 
 cleanup:
@@ -1867,16 +1864,6 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
         }
     }
 
-    /* generate the call for any accumulation */
-    if (self->accumulate) {
-        ast_call *call = ast_call_new(ast_ctx(self), (ast_expression*)self->accumulate->vtype);
-        for (i = 0; i < vec_size(ec->params); i++)
-            vec_push(call->params, (ast_expression*)ec->params[i]);
-        vec_push(vec_last(self->blocks)->exprs, (ast_expression*)call);
-
-        self->ir_func->flags |= IR_FLAG_ACCUMULATE;
-    }
-
     for (i = 0; i < vec_size(self->blocks); ++i) {
         cgen = self->blocks[i]->expression.codegen;
         if (!(*cgen)((ast_expression*)self->blocks[i], self, false, &dummy))
diff --git a/ast.h b/ast.h
index 5d198e4f92ea4659992e2e26fa219318b7b862eb..52858ac7f132ce14372fe7e92570593e11d2071f 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -25,6 +25,8 @@
 #define GMQCC_AST_HDR
 #include "ir.h"
 
+typedef uint16_t ast_flag_t;
+
 /* Note: I will not be using a _t suffix for the
  * "main" ast node types for now.
  */
@@ -53,6 +55,28 @@ typedef struct ast_label_s       ast_label;
 typedef struct ast_goto_s        ast_goto;
 typedef struct ast_argpipe_s     ast_argpipe;
 
+enum {
+    AST_FLAG_VARIADIC      = 1 << 0,
+    AST_FLAG_NORETURN      = 1 << 1,
+    AST_FLAG_INLINE        = 1 << 2,
+    AST_FLAG_INITIALIZED   = 1 << 3,
+    AST_FLAG_DEPRECATED    = 1 << 4,
+    AST_FLAG_INCLUDE_DEF   = 1 << 5,
+    AST_FLAG_IS_VARARG     = 1 << 6,
+    AST_FLAG_ALIAS         = 1 << 7,
+    AST_FLAG_ERASEABLE     = 1 << 8,
+    AST_FLAG_ACCUMULATE    = 1 << 9,
+
+    /*
+     * An array declared as []
+     * so that the size is taken from the initializer
+     */
+    AST_FLAG_ARRAY_INIT    = 1 << 10,
+
+    AST_FLAG_LAST,
+    AST_FLAG_TYPE_MASK     = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
+};
+
 enum {
     TYPE_ast_node,        /*  0 */
     TYPE_ast_expression,  /*  1 */
@@ -134,7 +158,7 @@ struct ast_expression_common
     /* arrays get a member-count */
     size_t                  count;
     ast_value*             *params;
-    uint32_t                flags;
+    ast_flag_t              flags;
     /* void foo(string...) gets varparam set as a restriction
      * for variadic parameters
      */
@@ -147,22 +171,6 @@ struct ast_expression_common
     ir_value               *outl;
     ir_value               *outr;
 };
-#define AST_FLAG_VARIADIC     (1<<0)
-#define AST_FLAG_NORETURN     (1<<1)
-#define AST_FLAG_INLINE       (1<<2)
-#define AST_FLAG_INITIALIZED  (1<<3)
-#define AST_FLAG_DEPRECATED   (1<<4)
-#define AST_FLAG_INCLUDE_DEF  (1<<5)
-#define AST_FLAG_IS_VARARG    (1<<6)
-#define AST_FLAG_ALIAS        (1<<7)
-#define AST_FLAG_ERASEABLE    (1<<8)
-#define AST_FLAG_ACCUMULATE   (1<<9)
-/*
- * An array declared as []
- * so that the size is taken from the initializer
- */
-#define AST_FLAG_ARRAY_INIT   (1<<10)
-#define AST_FLAG_TYPE_MASK    (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
 
 /* Value
  *
@@ -617,10 +625,6 @@ struct ast_function_s
 
     int builtin;
 
-    /* function accumulation */
-    ast_function *accumulate;    /* pointer to the next function in the chain */
-    size_t        accumulation;  /* base functions # of accumulations         */
-
     ir_function *ir_func;
     ir_block    *curblock;
     ir_block    **breakblocks;
@@ -660,4 +664,11 @@ const char* ast_function_label(ast_function*, const char *prefix);
 bool ast_function_codegen(ast_function *self, ir_builder *builder);
 bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
 
+/*
+ * If the condition creates a situation where this becomes -1 size it means there are
+ * more AST_FLAGs than the type ast_flag_t is capable of holding. So either eliminate
+ * the AST flag count or change the ast_flag_t typedef to a type large enough to accomodate
+ * all the flags.
+ */
+typedef int static_assert_is_ast_flag_safe [((AST_FLAG_LAST) <= (ast_flag_t)(-1)) ? 1 : -1];
 #endif
diff --git a/fold.c b/fold.c
index 4664487a3eb776ec6251483fe3180614081337dc..c9f1a0695c07f8fe1b9c35b62f7bbfab4eaaa360 100644 (file)
--- a/fold.c
+++ b/fold.c
@@ -773,18 +773,28 @@ ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **a
 #define fold_can_1(X)           ((X)->hasvalue && (X)->cvq == CV_CONST)
 /*#define fold_can_2(X,Y)         (fold_can_1(X) && fold_can_1(Y))*/
 
-ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, int op) {
+static ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, int op) {
+    ast_expression *swapped = NULL; /* using this as bool */
     ast_value *load;
 
-    if (!ast_istype(left, ast_value) || !fold_can_1((load = (ast_value*)right)))
+    if (!ast_istype(right, ast_value) || !fold_can_1((load = (ast_value*)right))) {
+        swapped = left;
+        left    = right;
+        right   = swapped;
+    }
+
+    if (!ast_istype(right, ast_value) || !fold_can_1((load = (ast_value*)right)))
         return NULL;
 
     switch (op) {
-        case INSTR_MUL_F:
         case INSTR_DIV_F:
+            if (swapped)
+                return NULL;
+        case INSTR_MUL_F:
             if (fold_immvalue_float(load) == 1.0f) {
                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
-                return (ast_expression*)left;
+                ast_unref(right);
+                return left;
             }
             break;
 
@@ -793,14 +803,16 @@ ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, in
         case INSTR_SUB_F:
             if (fold_immvalue_float(load) == 0.0f) {
                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
-                return (ast_expression*)left;
+                ast_unref(right);
+                return left;
             }
             break;
 
         case INSTR_MUL_V:
             if (vec3_cmp(fold_immvalue_vector(load), vec3_create(1, 1, 1))) {
                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
-                return (ast_expression*)left;
+                ast_unref(right);
+                return left;
             }
             break;
 
@@ -808,7 +820,8 @@ ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, in
         case INSTR_SUB_V:
             if (vec3_cmp(fold_immvalue_vector(load), vec3_create(0, 0, 0))) {
                 ++opts_optimizationcount[OPTIM_PEEPHOLE];
-                return (ast_expression*)left;
+                ast_unref(right);
+                return left;
             }
             break;
     }
@@ -816,6 +829,13 @@ ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, in
     return NULL;
 }
 
+ast_expression *fold_binary(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right) {
+    ast_expression *ret = fold_superfluous(left, right, op);
+    if (ret)
+        return ret;
+    return (ast_expression*)ast_binary_new(ctx, op, left, right);
+}
+
 static GMQCC_INLINE int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
     if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) {
         ast_expression_codegen *cgen;
diff --git a/ftepp.c b/ftepp.c
index fe63fbf656cb9c172ee060abf7f68b3d4a8aaa01..a34b58c0e152d6077e669ac12d1215cfbf643389 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -74,17 +74,13 @@ typedef struct ftepp_s {
     char        *itemname;
     char        *includename;
     bool         in_macro;
-} ftepp_t;
 
-/*
- * Implement the predef subsystem now.  We can do this safely with the
- * help of lexer contexts.
- */
-static uint32_t ftepp_predef_countval = 0;
-static uint32_t ftepp_predef_randval  = 0;
+    uint32_t predef_countval;
+    uint32_t predef_randval;
+} ftepp_t;
 
 /* __DATE__ */
-static char *ftepp_predef_date(lex_file *context) {
+static char *ftepp_predef_date(ftepp_t *context) {
     const struct tm *itime = NULL;
     char            *value = (char*)mem_a(82);
     time_t           rtime;
@@ -99,7 +95,7 @@ static char *ftepp_predef_date(lex_file *context) {
 }
 
 /* __TIME__ */
-static char *ftepp_predef_time(lex_file *context) {
+static char *ftepp_predef_time(ftepp_t *context) {
     const struct tm *itime = NULL;
     char            *value = (char*)mem_a(82);
     time_t           rtime;
@@ -114,61 +110,58 @@ static char *ftepp_predef_time(lex_file *context) {
 }
 
 /* __LINE__ */
-static char *ftepp_predef_line(lex_file *context) {
-    char   *value;
-    util_asprintf(&value, "%d", (int)context->line);
+static char *ftepp_predef_line(ftepp_t *context) {
+    char *value;
+
+    util_asprintf(&value, "%d", (int)context->lex->line);
     return value;
 }
 /* __FILE__ */
-static char *ftepp_predef_file(lex_file *context) {
-    size_t  length = strlen(context->name) + 3; /* two quotes and a terminator */
-    char   *value  = (char*)mem_a(length);
-    util_snprintf(value, length, "\"%s\"", context->name);
+static char *ftepp_predef_file(ftepp_t *context) {
+    size_t length = strlen(context->lex->name) + 3; /* two quotes and a terminator */
+    char  *value  = (char*)mem_a(length);
 
+    util_snprintf(value, length, "\"%s\"", context->lex->name);
     return value;
 }
 /* __COUNTER_LAST__ */
-static char *ftepp_predef_counterlast(lex_file *context) {
-    char   *value;
-    util_asprintf(&value, "%u", ftepp_predef_countval);
-
-    (void)context;
+static char *ftepp_predef_counterlast(ftepp_t *context) {
+    char *value;
+    util_asprintf(&value, "%u", context->predef_countval);
     return value;
 }
 /* __COUNTER__ */
-static char *ftepp_predef_counter(lex_file *context) {
-    char   *value;
-    ftepp_predef_countval ++;
-    util_asprintf(&value, "%u", ftepp_predef_countval);
-    (void)context;
+static char *ftepp_predef_counter(ftepp_t *context) {
+    char *value;
+
+    context->predef_countval ++;
+    util_asprintf(&value, "%u", context->predef_countval);
 
     return value;
 }
 /* __RANDOM__ */
-static char *ftepp_predef_random(lex_file *context) {
-    char  *value;
-    ftepp_predef_randval = (util_rand() % 0xFF) + 1;
-    util_asprintf(&value, "%u", ftepp_predef_randval);
+static char *ftepp_predef_random(ftepp_t *context) {
+    char *value;
 
-    (void)context;
+    context->predef_randval = (util_rand() % 0xFF) + 1;
+    util_asprintf(&value, "%u", context->predef_randval);
     return value;
 }
 /* __RANDOM_LAST__ */
-static char *ftepp_predef_randomlast(lex_file *context) {
-    char   *value;
-    util_asprintf(&value, "%u", ftepp_predef_randval);
+static char *ftepp_predef_randomlast(ftepp_t *context) {
+    char *value;
 
-    (void)context;
+    util_asprintf(&value, "%u", context->predef_randval);
     return value;
 }
 /* __TIMESTAMP__ */
-static char *ftepp_predef_timestamp(lex_file *context) {
+static char *ftepp_predef_timestamp(ftepp_t *context) {
     struct stat finfo;
     const char *find;
     char       *value;
     size_t      size;
 
-    if (stat(context->name, &finfo))
+    if (stat(context->lex->name, &finfo))
         return util_strdup("\"<failed to determine timestamp>\"");
 
     find = util_ctime(&finfo.st_mtime);
@@ -183,7 +176,7 @@ static char *ftepp_predef_timestamp(lex_file *context) {
 
 typedef struct {
     const char   *name;
-    char       *(*func)(lex_file *);
+    char       *(*func)(ftepp_t *);
 } ftepp_predef_t;
 
 static const ftepp_predef_t ftepp_predefs[] = {
@@ -213,7 +206,7 @@ bool ftepp_predef_exists(const char *name) {
 }
 
 /* singleton because we're allowed */
-static GMQCC_INLINE char *(*ftepp_predef(const char *name))(lex_file *context) {
+static GMQCC_INLINE char *(*ftepp_predef(const char *name))(ftepp_t *context) {
     size_t i = ftepp_predef_index(name);
     return (i != 0) ? ftepp_predefs[i-1].func : NULL;
 }
@@ -305,8 +298,10 @@ static ftepp_t* ftepp_new(void)
     ftepp = (ftepp_t*)mem_a(sizeof(*ftepp));
     memset(ftepp, 0, sizeof(*ftepp));
 
-    ftepp->macros    = util_htnew(HT_MACROS);
-    ftepp->output_on = true;
+    ftepp->macros          = util_htnew(HT_MACROS);
+    ftepp->output_on       = true;
+    ftepp->predef_countval = 0;
+    ftepp->predef_randval  = 0;
 
     return ftepp;
 }
@@ -1686,9 +1681,9 @@ static bool ftepp_preprocess(ftepp_t *ftepp)
             case TOKEN_TYPENAME:
                 /* is it a predef? */
                 if (OPTS_FLAG(FTEPP_PREDEFS)) {
-                    char *(*predef)(lex_file*) = ftepp_predef(ftepp_tokval(ftepp));
+                    char *(*predef)(ftepp_t*) = ftepp_predef(ftepp_tokval(ftepp));
                     if (predef) {
-                        expand = predef(ftepp->lex);
+                        expand = predef(ftepp);
                         ftepp_out (ftepp, expand, false);
                         ftepp_next(ftepp);
 
diff --git a/gmqcc.h b/gmqcc.h
index 49b5a824437e2dc3ce2ee7f22849f8148cf75a36..6e0d3ac05ecfca2f7bc858212dc56b8751f539d2 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -315,7 +315,6 @@ const char      *util_ctime    (const time_t *timer);
 typedef struct fs_file_s fs_file_t;
 
 bool             util_isatty(fs_file_t *);
-const char      *util_tmpnam(char *);
 
 /*
  * A flexible vector implementation: all vector pointers contain some
diff --git a/ir.c b/ir.c
index fbb79f2e6cd0e03005cb7c5167fe229279e485bc..7d83720c4d4afb3cd56ec90a08b9cc1ad7dde9d3 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -1586,10 +1586,6 @@ bool ir_block_create_return(ir_block *self, lex_ctx_t ctx, ir_value *v)
 
     self->final = true;
 
-    /* can eliminate the return instructions for accumulation */
-    if (self->owner->flags & IR_FLAG_ACCUMULATE)
-        return true;
-
     self->is_return = true;
     in = ir_instr_new(ctx, self, INSTR_RETURN);
     if (!in)
diff --git a/ir.h b/ir.h
index 507a2317e461c6251d39656cb8101ff25d0a4b49..1d3503872efefb16a0d6328d822b82f0e76a5e19 100644 (file)
--- a/ir.h
+++ b/ir.h
 #define GMQCC_IR_HDR
 #include "gmqcc.h"
 
-typedef struct
-{
+/*
+ * Type large enough to hold all the possible IR flags. This should be
+ * changed if the static assertion at the end of this file fails.
+ */
+typedef uint8_t ir_flag_t;
+
+typedef struct ir_value_s    ir_value;
+typedef struct ir_instr_s    ir_instr;
+typedef struct ir_block_s    ir_block;
+typedef struct ir_function_s ir_function;
+typedef struct ir_builder_s  ir_builder;
+
+typedef struct {
     /* both inclusive */
     size_t start;
     size_t end;
 } ir_life_entry_t;
 
-struct ir_function_s;
-typedef struct ir_value_s {
+enum {
+    IR_FLAG_HAS_ARRAYS           = 1 << 0,
+    IR_FLAG_HAS_UNINITIALIZED    = 1 << 1,
+    IR_FLAG_HAS_GOTO             = 1 << 2,
+    IR_FLAG_INCLUDE_DEF          = 1 << 3,
+    IR_FLAG_ERASEABLE            = 1 << 4,
+
+    IR_FLAG_LAST,
+    IR_FLAG_MASK_NO_OVERLAP      = (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED),
+    IR_FLAG_MASK_NO_LOCAL_TEMPS  = (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
+};
+
+struct ir_value_s {
     char      *name;
-    int       vtype;
-    int       store;
-    lex_ctx_t   context;
-    /* even the IR knows the subtype of a field */
-    int       fieldtype;
-    /* and the output type of a function */
-    int       outtype;
-    /* 'const' vs 'var' qualifier */
-    int       cvq;
-    uint32_t  flags;
-
-    struct ir_instr_s **reads;
-    struct ir_instr_s **writes;
+    int        vtype;
+    int        store;
+    lex_ctx_t  context;
+
+
+    int       fieldtype; /* even the IR knows the subtype of a field */
+    int       outtype;   /* and the output type of a function        */
+    int       cvq;       /* 'const' vs 'var' qualifier               */
+    ir_flag_t flags;
+
+    ir_instr **reads;
+    ir_instr **writes;
 
     /* constantvalues */
     bool hasvalue;
     union {
-        qcfloat_t vfloat;
-        int       vint;
-        vec3_t    vvec;
-        int32_t   ivec[3];
-        char     *vstring;
-        struct ir_value_s *vpointer;
-        struct ir_function_s *vfunc;
+        qcfloat_t   vfloat;
+        int         vint;
+        vec3_t      vvec;
+        int32_t     ivec[3];
+        char        *vstring;
+        ir_value    *vpointer;
+        ir_function *vfunc;
     } constval;
 
     struct {
         int32_t globaladdr;
         int32_t name;
-        /* filled by the local-allocator */
-        int32_t local;
-        /* added for members */
-        int32_t addroffset;
-        /* to generate field-addresses early */
-        int32_t fieldaddr;
+        int32_t local;         /* filled by the local-allocator     */
+        int32_t addroffset;    /* added for members                 */
+        int32_t fieldaddr;     /* to generate field-addresses early */
     } code;
 
     /* for acessing vectors */
-    struct ir_value_s *members[3];
-    struct ir_value_s *memberof;
+    ir_value *members[3];
+    ir_value *memberof;
 
-    /* arrays will never overlap with temps */
-    bool unique_life;
-    /* temps living during a CALL must be locked */
-    bool      locked;
-    bool      callparam;
 
-    /* For the temp allocator */
-    ir_life_entry_t *life;
-} ir_value;
+    bool unique_life;      /* arrays will never overlap with temps      */
+    bool locked;           /* temps living during a CALL must be locked */
+    bool callparam;
 
-/* ir_value can be a variable, or created by an operation */
-/* if a result of an operation: the function should store
+    ir_life_entry_t *life; /* For the temp allocator */
+};
+
+/*
+ * ir_value can be a variable, or created by an operation
+ * if a result of an operation: the function should store
  * it to remember to delete it / garbage collect it
  */
 void            ir_value_delete(ir_value*);
@@ -100,19 +117,17 @@ bool            ir_value_lives(ir_value*, size_t);
 void            ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...));
 
 /* PHI data */
-typedef struct ir_phi_entry_s
-{
-    ir_value          *value;
-    struct ir_block_s *from;
+typedef struct ir_phi_entry_s {
+    ir_value *value;
+    ir_block *from;
 } ir_phi_entry_t;
 
 /* instruction */
-typedef struct ir_instr_s
-{
-    int       opcode;
-    lex_ctx_t   context;
+struct ir_instr_s {
+    int        opcode;
+    lex_ctx_t  context;
     ir_value* (_ops[3]);
-    struct ir_block_s* (bops[2]);
+    ir_block* (bops[2]);
 
     ir_phi_entry_t *phi;
     ir_value      **params;
@@ -123,31 +138,30 @@ typedef struct ir_instr_s
     /* For IFs */
     bool   likely;
 
-    struct ir_block_s *owner;
-} ir_instr;
+    ir_block *owner;
+};
 
 /* block */
-typedef struct ir_block_s
-{
+struct ir_block_s {
     char      *label;
-    lex_ctx_t    context;
+    lex_ctx_t  context;
     bool       final; /* once a jump is added we're done */
 
-    ir_instr          **instr;
-    struct ir_block_s **entries;
-    struct ir_block_s **exits;
-    ir_value          **living;
+    ir_instr **instr;
+    ir_block **entries;
+    ir_block **exits;
+    ir_value **living;
 
     /* For the temp-allocation */
     size_t entry_id;
     size_t eid;
     bool   is_return;
 
-    struct ir_function_s *owner;
+    ir_function *owner;
 
     bool   generated;
     size_t code_start;
-} ir_block;
+};
 
 ir_value*       ir_block_create_binop(ir_block*, lex_ctx_t, const char *label, int op, ir_value *left, ir_value *right);
 ir_value*       ir_block_create_unary(ir_block*, lex_ctx_t, const char *label, int op, ir_value *operand);
@@ -170,7 +184,8 @@ bool GMQCC_WARN ir_block_create_return(ir_block*, lex_ctx_t, ir_value *opt_value
 
 bool GMQCC_WARN ir_block_create_if(ir_block*, lex_ctx_t, ir_value *cond,
                                    ir_block *ontrue, ir_block *onfalse);
-/* A 'goto' is an actual 'goto' coded in QC, whereas
+/*
+ * A 'goto' is an actual 'goto' coded in QC, whereas
  * a 'jump' is a virtual construct which simply names the
  * next block to go to.
  * A goto usually becomes an OP_GOTO in the resulting code,
@@ -180,37 +195,33 @@ bool GMQCC_WARN ir_block_create_jump(ir_block*, lex_ctx_t, ir_block *to);
 bool GMQCC_WARN ir_block_create_goto(ir_block*, lex_ctx_t, ir_block *to);
 
 /* function */
-typedef struct ir_function_s
-{
+struct ir_function_s {
     char      *name;
     int        outtype;
     int       *params;
     ir_block **blocks;
+    ir_flag_t  flags;
+    int        builtin;
 
-    uint32_t   flags;
-
-    int builtin;
-
-    ir_value *value;
-
-    /* values generated from operations
+    /*
+     * values generated from operations
      * which might get optimized away, so anything
      * in there needs to be deleted in the dtor.
      */
     ir_value **values;
-
-    /* locally defined variables */
-    ir_value **locals;
+    ir_value **locals;     /* locally defined variables */
+    ir_value *value;
 
     size_t allocated_locals;
     size_t globaltemps;
 
-    ir_block*     first;
-    ir_block*     last;
+    ir_block*  first;
+    ir_block*  last;
 
-    lex_ctx_t       context;
+    lex_ctx_t  context;
 
-    /* for prototypes - first we generate all the
+    /*
+     * for prototypes - first we generate all the
      * globals, and we remember teh function-defs
      * so we can later fill in the entry pos
      *
@@ -221,30 +232,22 @@ typedef struct ir_function_s
     /* for temp allocation */
     size_t run_id;
 
-    struct ir_builder_s *owner;
+    ir_builder *owner;
 
     /* vararg support: */
     size_t max_varargs;
-} ir_function;
+};
 
-#define IR_FLAG_HAS_ARRAYS        (1<<1)
-#define IR_FLAG_HAS_UNINITIALIZED (1<<2)
-#define IR_FLAG_HAS_GOTO          (1<<3)
-#define IR_FLAG_INCLUDE_DEF       (1<<4)
-#define IR_FLAG_ERASEABLE         (1<<5)
-#define IR_FLAG_ACCUMULATE        (1<<6)
-#define IR_FLAG_MASK_NO_OVERLAP     (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
-#define IR_FLAG_MASK_NO_LOCAL_TEMPS (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
 
 ir_value*       ir_function_create_local(ir_function *self, const char *name, int vtype, bool param);
 bool GMQCC_WARN ir_function_finalize(ir_function*);
 ir_block*       ir_function_create_block(lex_ctx_t ctx, ir_function*, const char *label);
 
 /* builder */
-#define IR_HT_SIZE 1024
+#define IR_HT_SIZE          1024
 #define IR_MAX_VINSTR_TEMPS 1
-typedef struct ir_builder_s
-{
+
+struct ir_builder_s {
     char *name;
     ir_function **functions;
     ir_value    **globals;
@@ -277,7 +280,7 @@ typedef struct ir_builder_s
 
     /* code generator */
     code_t      *code;
-} ir_builder;
+};
 
 ir_builder*  ir_builder_new(const char *modulename);
 void         ir_builder_delete(ir_builder*);
@@ -293,7 +296,15 @@ void         ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));
  * Blub: don't use extern here, it's annoying and shows up in nm
  * for some reason :P
  */
-typedef int static_assert_is_32bit_float  [(sizeof(int32_t) == 4)?1:-1];
-typedef int static_assert_is_32bit_integer[(sizeof(qcfloat_t) == 4)?1:-1];
+typedef int static_assert_is_32bit_float  [(sizeof(int32_t) == 4)   ? 1 : -1];
+typedef int static_assert_is_32bit_integer[(sizeof(qcfloat_t) == 4) ? 1 : -1];
+
+/*
+ * If the condition creates a situation where this becomes -1 size it means there are
+ * more IR_FLAGs than the type ir_flag_t is capable of holding. So either eliminate
+ * the IR flag count or change the ir_flag_t typedef to a type large enough to accomodate
+ * all the flags.
+ */
+typedef int static_assert_is_ir_flag_safe [((IR_FLAG_LAST) <= (ir_flag_t)(-1)) ? 1 : -1];
 
 #endif
diff --git a/msvc.c b/msvc.c
index 77afc1056ee407d0cdca27d1a0e4994abb9644a7..3369cd6f8e7b00fe115abe5dc4840a20ed740a2e 100644 (file)
--- a/msvc.c
+++ b/msvc.c
@@ -76,10 +76,6 @@ char *platform_strncat(char *dest, const char *src, size_t num) {
     return strncat_s(dest, num, src, _TRUNCATE);
 }
 
-const char *platform_tmpnam(char *str) {
-    return tmpnam_s(str, L_tmpnam);
-}
-
 const char *platform_getenv(const char *var) {
     char  *buffer = (char *)platform_mem_allocate(GETENV_BUFFER);
     size_t size;
index 82ce53b0a47a84deeb0b422fc32c1558c8412681..2dc25508449e2771220d08d5907c3f01799fb183 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -44,7 +44,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
 static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
 static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
 static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname);
-static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
+static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg);
 
 static void parseerror(parser_t *parser, const char *fmt, ...)
 {
@@ -521,10 +521,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             if (!(out = fold_op(parser->fold, op, exprs))) {
                 switch (exprs[0]->vtype) {
                     case TYPE_FLOAT:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
+                        out = fold_binary(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
                         break;
                     case TYPE_VECTOR:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
+                        out = fold_binary(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
                         break;
                     default:
                         compile_error(ctx, "invalid types used in expression: cannot add type %s and %s",
@@ -546,10 +546,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             if (!(out = fold_op(parser->fold, op, exprs))) {
                 switch (exprs[0]->vtype) {
                     case TYPE_FLOAT:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
+                        out = fold_binary(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
                         break;
                     case TYPE_VECTOR:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
+                        out = fold_binary(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
                         break;
                     default:
                         compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s",
@@ -576,15 +576,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 switch (exprs[0]->vtype) {
                     case TYPE_FLOAT:
                         if (exprs[1]->vtype == TYPE_VECTOR)
-                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
+                            out = fold_binary(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
                         else
-                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
+                            out = fold_binary(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
                         break;
                     case TYPE_VECTOR:
                         if (exprs[1]->vtype == TYPE_FLOAT)
-                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
+                            out = fold_binary(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
                         else
-                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
+                            out = fold_binary(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
                         break;
                     default:
                         compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s",
@@ -604,7 +604,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
             if (!(out = fold_op(parser->fold, op, exprs))) {
                 if (exprs[0]->vtype == TYPE_FLOAT)
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
+                    out = fold_binary(ctx, INSTR_DIV_F, exprs[0], exprs[1]);
                 else {
                     ast_type_to_string(exprs[0], ty1, sizeof(ty1));
                     ast_type_to_string(exprs[1], ty2, sizeof(ty2));
@@ -657,7 +657,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                  * since scalar ^ vector is not allowed.
                  */
                 if (exprs[0]->vtype == TYPE_FLOAT) {
-                    out = (ast_expression*)ast_binary_new(ctx,
+                    out = fold_binary(ctx,
                         (op->id == opid1('^') ? VINSTR_BITXOR : op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND),
                         exprs[0], exprs[1]);
                 } else {
@@ -670,11 +670,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                          * Bitop all the values of the vector components against the
                          * vectors components in question.
                          */
-                        out = (ast_expression*)ast_binary_new(ctx,
+                        out = fold_binary(ctx,
                             (op->id == opid1('^') ? VINSTR_BITXOR_V : op->id == opid1('|') ? VINSTR_BITOR_V : VINSTR_BITAND_V),
                             exprs[0], exprs[1]);
                     } else {
-                        out = (ast_expression*)ast_binary_new(ctx,
+                        out = fold_binary(ctx,
                             (op->id == opid1('^') ? VINSTR_BITXOR_VF : op->id == opid1('|') ? VINSTR_BITOR_VF : VINSTR_BITAND_VF),
                             exprs[0], exprs[1]);
                     }
@@ -727,7 +727,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                         }
                     }
                 }
-                out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
+                out = fold_binary(ctx, generated_op, exprs[0], exprs[1]);
             }
             break;
 
@@ -774,7 +774,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
 
             if (!(out = fold_op(parser->fold, op, exprs))) {
-                out = (ast_expression*)ast_binary_new(
+                out = fold_binary(
                         parser_ctx(parser),
                         VINSTR_CROSS,
                         exprs[0],
@@ -795,6 +795,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
 
             if (!(out = fold_op(parser->fold, op, exprs))) {
+                /* This whole block is NOT fold_binary safe */
                 ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
 
                 eq->refs = AST_REF_NONE;
@@ -835,7 +836,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 return false;
             }
             if (!(out = fold_op(parser->fold, op, exprs)))
-                out = (ast_expression*)ast_binary_new(ctx, generated_op, exprs[0], exprs[1]);
+                out = fold_binary(ctx, generated_op, exprs[0], exprs[1]);
             break;
         case opid2('!', '='):
             if (exprs[0]->vtype != exprs[1]->vtype) {
@@ -845,7 +846,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 return false;
             }
             if (!(out = fold_op(parser->fold, op, exprs)))
-                out = (ast_expression*)ast_binary_new(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
+                out = fold_binary(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]);
             break;
         case opid2('=', '='):
             if (exprs[0]->vtype != exprs[1]->vtype) {
@@ -855,7 +856,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                 return false;
             }
             if (!(out = fold_op(parser->fold, op, exprs)))
-                out = (ast_expression*)ast_binary_new(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
+                out = fold_binary(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]);
             break;
 
         case opid1('='):
@@ -969,9 +970,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
             if (!out)
                 return false;
-            out = (ast_expression*)ast_binary_new(ctx, subop,
-                                                  out,
-                                                  (ast_expression*)parser->fold->imm_float[1]);
+            out = fold_binary(ctx, subop,
+                              out,
+                              (ast_expression*)parser->fold->imm_float[1]);
 
             break;
         case opid2('+','='):
@@ -1036,9 +1037,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
                         out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF,
                                                                 exprs[0], exprs[1]);
                     } else {
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_DIV_F,
-                                                                  (ast_expression*)parser->fold->imm_float[1],
-                                                                  exprs[1]);
+                        out = fold_binary(ctx, INSTR_DIV_F,
+                                         (ast_expression*)parser->fold->imm_float[1],
+                                         exprs[1]);
                         if (!out) {
                             compile_error(ctx, "internal error: failed to generate division");
                             return false;
@@ -1095,9 +1096,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             else
                 assignop = type_store_instr[exprs[0]->vtype];
             if (exprs[0]->vtype == TYPE_FLOAT)
-                out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
+                out = fold_binary(ctx, INSTR_BITAND, exprs[0], exprs[1]);
             else
-                out = (ast_expression*)ast_binary_new(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]);
+                out = fold_binary(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]);
             if (!out)
                 return false;
             (void)check_write_to(ctx, exprs[0]);
@@ -1117,9 +1118,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             }
             if (!(out = fold_op(parser->fold, op, exprs))) {
                 if (exprs[0]->vtype == TYPE_FLOAT) {
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]);
+                    out = fold_binary(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]);
                 } else {
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, (ast_expression*)parser->fold->imm_vector[1], exprs[0]);
+                    out = fold_binary(ctx, INSTR_SUB_V, (ast_expression*)parser->fold->imm_vector[1], exprs[0]);
                 }
             }
             break;
@@ -1422,7 +1423,7 @@ static ast_expression* parse_vararg_do(parser_t *parser)
         return NULL;
     }
 
-    typevar = parse_typename(parser, NULL, NULL);
+    typevar = parse_typename(parser, NULL, NULL, NULL);
     if (!typevar) {
         ast_unref(idx);
         return NULL;
@@ -3984,59 +3985,28 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         }
     }
 
-    if (var->hasvalue && !(var->expression.flags & AST_FLAG_ACCUMULATE)) {
-        parseerror(parser, "function `%s` declared with multiple bodies", var->name);
-        ast_block_delete(block);
-        goto enderr;
-    }
-
-    /* accumulation? */
-    if (var->hasvalue && var->expression.vtype == TYPE_FUNCTION) {
-        ast_value    *accum    = NULL;
-        ast_function *previous = NULL;
-        char          acname[1024];
-
-        /* only void please */
-        if (var->expression.next->vtype != TYPE_VOID) {
-            parseerror(parser, "accumulated function `%s` declared with return type `%s` (accumulated functions must return void)",
-                var->name,
-                type_name[var->expression.next->vtype]
-            );
+    if (var->hasvalue) {
+        if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) {
+            parseerror(parser, "function `%s` declared with multiple bodies", var->name);
             ast_block_delete(block);
             goto enderr;
         }
+        func = var->constval.vfunc;
 
-        /* generate a new name increasing the accumulation count*/
-        util_snprintf(acname, sizeof(acname), "##ACCUMULATE_%s_%d", var->name, var->constval.vfunc->accumulation++);
-        accum = ast_value_new(parser_ctx(parser), acname, ((ast_expression*)var)->vtype);
-        if (!accum)
-            return false;
-
-        ast_type_adopt(accum, var);
-        func = ast_function_new(ast_ctx(var), NULL, accum);
-        if (!func)
-            return false;
-
-        parser_addglobal(parser, acname, (ast_expression*)accum);
-        vec_push(parser->functions, func);
-
-        /* update the previous calls accumulate pointer for the codegen */
-        previous = var->constval.vfunc;
-        while (previous->accumulate)
-            previous = previous->accumulate;
-
-        if (ast_istype(previous, ast_function))
-            previous->accumulate = func;
-
+        if (!func) {
+            parseerror(parser, "internal error: NULL function: `%s`", var->name);
+            ast_block_delete(block);
+            goto enderr;
+        }
     } else {
         func = ast_function_new(ast_ctx(var), var->name, var);
-        vec_push(parser->functions, func);
-    }
 
-    if (!func) {
-        parseerror(parser, "failed to allocate function for `%s`", var->name);
-        ast_block_delete(block);
-        goto enderr;
+        if (!func) {
+            parseerror(parser, "failed to allocate function for `%s`", var->name);
+            ast_block_delete(block);
+            goto enderr;
+        }
+        vec_push(parser->functions, func);
     }
 
     parser_enterblock(parser);
@@ -4064,13 +4034,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         }
     }
 
-    if (var->argcounter) {
+    if (var->argcounter && !func->argc) {
         ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
         parser_addlocal(parser, argc->name, (ast_expression*)argc);
         func->argc = argc;
     }
 
-    if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
+    if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) {
         char name[1024];
         ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
         varargs->expression.flags |= AST_FLAG_IS_VARARG;
@@ -4100,7 +4070,6 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
     vec_push(func->blocks, block);
 
-
     parser->function = old;
     if (!parser_leaveblock(parser))
         retval = false;
@@ -4537,7 +4506,6 @@ static bool parser_create_array_getter(parser_t *parser, ast_value *array, const
     return parser_create_array_getter_impl(parser, array);
 }
 
-static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
 static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
 {
     lex_ctx_t     ctx;
@@ -4563,6 +4531,8 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
 
     /* parse variables until we hit a closing paren */
     while (parser->tok != ')') {
+        bool is_varargs = false;
+
         if (!first) {
             /* there must be commas between them */
             if (parser->tok != ',') {
@@ -4576,10 +4546,13 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
         }
         first = false;
 
-        if (parser->tok == TOKEN_DOTS) {
+        param = parse_typename(parser, NULL, NULL, &is_varargs);
+        if (!param && !is_varargs)
+            goto on_error;
+        if (is_varargs) {
             /* '...' indicates a varargs function */
             variadic = true;
-            if (!parser_next(parser) || (parser->tok != ')' && parser->tok != TOKEN_IDENT)) {
+            if (parser->tok != ')' && parser->tok != TOKEN_IDENT) {
                 parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
                 goto on_error;
             }
@@ -4590,13 +4563,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var)
                     goto on_error;
                 }
             }
-        }
-        else
-        {
-            /* for anything else just parse a typename */
-            param = parse_typename(parser, NULL, NULL);
-            if (!param)
-                goto on_error;
+        } else {
             vec_push(params, param);
             if (param->expression.vtype >= TYPE_VARIANT) {
                 char tname[1024]; /* typename is reserved in C++ */
@@ -4748,7 +4715,7 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var)
  *     void() foo(), bar
  * then the type-information 'void()' can be stored in 'storebase'
  */
-static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef)
+static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef, bool *is_vararg)
 {
     ast_value *var, *tmp;
     lex_ctx_t    ctx;
@@ -4758,6 +4725,8 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
     bool        wasarray = false;
     size_t      morefields = 0;
 
+    bool        vararg = (parser->tok == TOKEN_DOTS);
+
     ctx = parser_ctx(parser);
 
     /* types may start with a dot */
@@ -4781,6 +4750,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
                 morefields += 3;
             else
                 break;
+            vararg = false;
             if (!parser_next(parser)) {
                 parseerror(parser, "expected typename for field definition");
                 return NULL;
@@ -4790,6 +4760,10 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va
     if (parser->tok == TOKEN_IDENT)
         cached_typedef = parser_find_typedef(parser, parser_tokval(parser), 0);
     if (!cached_typedef && parser->tok != TOKEN_TYPENAME) {
+        if (vararg && is_vararg) {
+            *is_vararg = true;
+            return NULL;
+        }
         parseerror(parser, "expected typename");
         return NULL;
     }
@@ -4910,7 +4884,7 @@ static bool parse_typedef(parser_t *parser)
     ast_value      *typevar, *oldtype;
     ast_expression *old;
 
-    typevar = parse_typename(parser, NULL, NULL);
+    typevar = parse_typename(parser, NULL, NULL, NULL);
 
     if (!typevar)
         return false;
@@ -5080,7 +5054,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
         parseerror(parser, "`static` qualifier is not supported in global scope");
 
     /* get the first complete variable */
-    var = parse_typename(parser, &basetype, cached_typedef);
+    var = parse_typename(parser, &basetype, cached_typedef, NULL);
     if (!var) {
         if (basetype)
             ast_delete(basetype);
index 5c24650738ee23b6e6cba7df48b72e2650a6eddb..0396a7e17b3af01ac8e1fdf1f1004a18c8bbed57 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -134,7 +134,7 @@ bool            fold_generate       (fold_t *, ir_builder *);
 ast_expression *fold_op             (fold_t *, const oper_info *, ast_expression **);
 ast_expression *fold_intrin         (fold_t *, const char      *, ast_expression **);
 
-ast_expression *fold_superfluous    (ast_expression *, ast_expression *, int);
+ast_expression *fold_binary         (lex_ctx_t ctx, int, ast_expression *, ast_expression *);
 int             fold_cond_ifthen    (ir_value *, ast_function *, ast_ifthen  *);
 int             fold_cond_ternary   (ir_value *, ast_function *, ast_ternary *);
 
index 50b119a6beb12c0ecc3d739dec673397ed78c898..acb632ee2eba9a1927b4ebf094bc9ce6d5c15f99 100644 (file)
@@ -185,24 +185,6 @@ const char *platform_ctime(const time_t *timer);
  */
 char *platform_strncat(char *dest, const char *src, size_t num);
 
-/*
- * Function: platform_tmpnam
- *  Generates names you can use to create temporary files.
- *
- * Parameters:
- *  str - Pointer that will hold the generated name and will be identical
- *        to the name returned by the function. This is a convenient way
- *        to save the generated name.
- *
- * Returns:
- *  Pointer to the name generate or *NULL* if there is a failure. Failure
- *  can occur if you attempt more than TMP_MAX calls.
- *
- * Remarks:
- *  Returns a name unique in the current workign directory.
- */
-const char *platform_tmpnam(char *str);
-
 /*
  * Function: platform_getenv
  *  Get a value from the current enviroment.
diff --git a/test.c b/test.c
index c415fb87b72dba8f076cbea8a63e043fd39837f0..6ce99964b24f408b5fd482a2ddff7eb83d4d7ce9 100644 (file)
--- a/test.c
+++ b/test.c
@@ -163,8 +163,8 @@ static int task_pclose(fs_file_t **handles) {
         char    *cmd  = NULL;
         popen_t *open = (popen_t*)mem_a(sizeof(popen_t));
 
-        util_tmpnam(open->name_err);
-        util_tmpnam(open->name_out);
+        tmpnam(open->name_err);
+        tmpnam(open->name_out);
 
         (void)mode; /* excluded */
 
diff --git a/tests/dots.qc b/tests/dots.qc
new file mode 100644 (file)
index 0000000..ccca3f9
--- /dev/null
@@ -0,0 +1,27 @@
+entity self;
+.float f;
+..float fp;
+...float fpp;
+
+void try(entity e, ...float pp) {
+    print("and: ", ftos( e.(e.(e.pp)) ), "\n");
+}
+
+typedef float Float;
+
+void try2(entity e, ...Float pp) {
+    print("and: ", ftos( e.(e.(e.pp)) ), "\n");
+}
+
+// whereas the varargs are tested in vararg tests
+
+void main() {
+    self = spawn();
+    self.f = 123;
+    self.fp = f;
+    self.fpp = fp;
+    print(ftos(  self.(self.fp)  ), "\n");
+    print(ftos(  self.(self.(self.fpp))  ), "\n");
+    try(self, fpp);
+    try2(self, fpp);
+}
diff --git a/tests/dots.tmpl b/tests/dots.tmpl
new file mode 100644 (file)
index 0000000..e99ad95
--- /dev/null
@@ -0,0 +1,8 @@
+I: dots.qc
+D: TOKEN_DOTS disambiguation
+T: -execute
+C: -std=fteqcc
+M: 123
+M: 123
+M: and: 123
+M: and: 123
diff --git a/util.c b/util.c
index f6b9808657f272125381bc06cb6e9ab39ad619db..3d4b48021952ab1d8a7fa619c677c979875f2667 100644 (file)
--- a/util.c
+++ b/util.c
@@ -281,11 +281,6 @@ bool util_isatty(fs_file_t *file) {
     if (file == (fs_file_t*)stderr) return !!platform_isatty(STDERR_FILENO);
     return false;
 }
-
-const char *util_tmpnam(char *str) {
-    return platform_tmpnam(str);
-}
-
 /*
  * A small noncryptographic PRNG based on:
  * http://burtleburtle.net/bob/rand/smallprng.html