diff --git a/plugins/include/datapack.inc b/plugins/include/datapack.inc index 7807d074..ee9daa4b 100644 --- a/plugins/include/datapack.inc +++ b/plugins/include/datapack.inc @@ -70,7 +70,7 @@ native void WritePackFloat(Handle pack, float val); * @noreturn * @error Invalid handle. */ -native void WritePackString(Handle pack, const char str[]); +native void WritePackString(Handle pack, const char[] str); /** * Packs a function pointer into a data pack. @@ -109,7 +109,7 @@ native float ReadPackFloat(Handle pack); * @noreturn * @error Invalid handle, or bounds error. */ -native void ReadPackString(Handle pack, char buffer[], maxlen); +native void ReadPackString(Handle pack, char[] buffer, maxlen); /** * Reads a function pointer from a data pack. diff --git a/sourcepawn/compiler/sc1.cpp b/sourcepawn/compiler/sc1.cpp index 61cc13e8..2f2ca83e 100644 --- a/sourcepawn/compiler/sc1.cpp +++ b/sourcepawn/compiler/sc1.cpp @@ -614,6 +614,17 @@ static void inst_datetime_defines(void) insert_subst("__TIME__", ltime, 8); } +const char *pc_typename(int tag) +{ + if (tag == 0) + return "int"; + if (tag == sc_rationaltag) + return "float"; + if (tag == pc_tag_string) + return "char"; + return pc_tagname(tag); +} + const char *pc_tagname(int tag) { constvalue *ptr=tagname_tab.next; @@ -1985,6 +1996,11 @@ static void declglb(declinfo_t *decl,int fpublic,int fstatic,int fstock) litidx=0; /* global initial data is dumped, so restart at zero */ } /* if */ assert(litidx==0); /* literal queue should be empty (again) */ + if (type->ident == iREFARRAY) { + // Dynamc array in global scope. + assert(type->is_new); + error(162); + } initials3(decl); if (type->tag == pc_tag_string && type->numdim == 1 && !type->dim[type->numdim - 1]) { slength = glbstringread; @@ -2038,6 +2054,25 @@ static void declglb(declinfo_t *decl,int fpublic,int fstatic,int fstock) needtoken(tTERM); /* if not comma, must be semicolumn */ } +static bool parse_local_array_initializer(typeinfo_t *type, int *curlit, int *slength) +{ + if (sc_alignnext) { + aligndata(sc_dataalign); + sc_alignnext=FALSE; + } /* if */ + *curlit = litidx; /* save current index in the literal table */ + if (type->numdim && !type->dim[type->numdim-1]) + type->size = 0; + initials(type->ident,type->tag,&type->size,type->dim,type->numdim,type->enumroot); + if (type->tag == pc_tag_string && type->numdim == 1 && !type->dim[type->numdim - 1]) + *slength = glbstringread; + if (type->size == 0) + return false; + if (type->numdim == 1) + type->dim[0] = type->size; + return true; +} + /* declloc - declare local symbols * * Declare local (automatic) variables. Since these variables are relative @@ -2092,20 +2127,8 @@ static void declloc(int tokid) slength = fix_char_size(&decl); if (type->ident == iARRAY || fstatic) { - if (sc_alignnext) { - aligndata(sc_dataalign); - sc_alignnext=FALSE; - } /* if */ - cur_lit=litidx; /* save current index in the literal table */ - if (type->numdim && !type->dim[type->numdim-1]) - type->size = 0; - initials(type->ident,type->tag,&type->size,type->dim,type->numdim,type->enumroot); - if (type->tag == pc_tag_string && type->numdim == 1 && !type->dim[type->numdim - 1]) - slength = glbstringread; - if (type->size == 0) + if (!parse_local_array_initializer(type, &cur_lit, &slength)) return; - if (type->numdim == 1) - type->dim[0] = type->size; } /* reserve memory (on the stack) for the variable */ if (fstatic) { @@ -2132,6 +2155,17 @@ static void declloc(int tokid) if (curfunc->x.stacksizex.stacksize=declared+1; /* +1 for PROC opcode */ } else if (type->ident == iREFARRAY) { + if (matchtoken('=')) { + if (lexpeek('{')) { + // Dynamic array with fixed initializer. + error(160); + + // Parse just to clear the tokens. First give '=' back. + lexpush(); + if (!parse_local_array_initializer(type, &cur_lit, &slength)) + return; + } + } declared+=1; /* one cell for address */ sym=addvariable(decl.name,-declared*sizeof(cell),type->ident,sLOCAL,type->tag,type->dim,type->numdim,type->idxtag); //markexpr(sLDECL,name,-declared*sizeof(cell)); /* mark for better optimization */ @@ -3035,7 +3069,7 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags) goto err_out; } } while (matchtoken('[')); - type->ident = iARRAY; + type->ident = iREFARRAY; type->size = 0; } @@ -3146,6 +3180,10 @@ static void parse_old_array_dims(declinfo_t *decl, int flags) genarray(type->numdim, autozero); type->ident = iREFARRAY; type->size = 0; + if (type->is_new) { + // Fixed array with dynamic size. + error(161, pc_typename(type->tag)); + } } stgout(staging_index); @@ -3301,6 +3339,8 @@ static int parse_new_decl(declinfo_t *decl, const token_t *first, int flags) } } + decl->type.is_new = TRUE; + if (flags & DECLMASK_NAMED_DECL) { if (matchtoken('[')) { if (decl->type.numdim == 0) @@ -3310,7 +3350,6 @@ static int parse_new_decl(declinfo_t *decl, const token_t *first, int flags) } } - decl->type.is_new = TRUE; return TRUE; } @@ -5606,6 +5645,9 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi int slength=0; typeinfo_t *type = &decl->type; + // Otherwise we get very weird line number ranges, anything to the current fline. + errorset(sEXPRMARK,0); + strcpy(arg->name, decl->name); arg->hasdefault=FALSE; /* preset (most common case) */ arg->defvalue.val=0; /* clear */ @@ -5641,6 +5683,10 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi } } } else { + if (type->is_new && !type->has_postdims && lexpeek('{')) { + // Dynamic array with fixed initializer. + error(160); + } initials2(type->ident, type->tags[0], &type->size, arg->dim, arg->numdim, type->enumroot, 1, 0); assert(type->size >= litidx); /* allocate memory to hold the initial values */ @@ -5660,7 +5706,17 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi } /* if */ litidx=0; /* reset */ } - } /* if */ + } else { + if (type->is_new && type->has_postdims) { + for (int i = 0; i < type->numdim; i++) { + if (type->dim[i] <= 0) { + // Fixed-array with unknown size. + error(159); + break; + } + } + } + } } else { if (matchtoken('=')) { unsigned char size_tag_token; @@ -5729,6 +5785,8 @@ static void doarg(declinfo_t *decl, int offset, int fpublic, int chkshadow, argi if (type->usage & uCONST) argsym->usage|=uCONST; } /* if */ + + errorset(sEXPRRELEASE,0); } static int count_referrers(symbol *entry) diff --git a/sourcepawn/compiler/sc5-in.scp b/sourcepawn/compiler/sc5-in.scp index 4ad17ca0..a34d7b30 100644 --- a/sourcepawn/compiler/sc5-in.scp +++ b/sourcepawn/compiler/sc5-in.scp @@ -202,6 +202,10 @@ static const char *errmsg[] = { /*156*/ "unused156\n", /*157*/ "'%s' is a reserved keyword\n", /*158*/ "multi-tags are no longer supported\n", +/*159*/ "brackets after variable name indicate a fixed-size array, but size could not be determined - either specify sizes, an array initializer, or use dynamic syntax (such as 'char[] x')\n", +/*160*/ "brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given\n", +/*161*/ "brackets after variable name indicate a fixed-size array, but a dynamic size was given - did you mean to use 'new %s[size]' syntax?\n", +/*162*/ "cannot create dynamic arrays in global scope - did you mean to create a fixed-length array with brackets after the variable name?\n", #else "\315e\306\227\266k\217:\235\277bu\201fo\220\204\223\012", "\202l\224\250s\205g\346\356e\233\201(\243\315\214\267\202) \253 f\255low ea\305 \042c\353e\042\012", diff --git a/sourcepawn/compiler/tests/fail-bad-array-decls.sp b/sourcepawn/compiler/tests/fail-bad-array-decls.sp new file mode 100644 index 00000000..07d0fb0c --- /dev/null +++ b/sourcepawn/compiler/tests/fail-bad-array-decls.sp @@ -0,0 +1,16 @@ +int[] gInvalid = {1}; + +public OnPluginStart() +{ + int v = 10; + int invalid1[v]; + int[] invalid2 = {1}; +} + +void invalid_arg1(int invalid[]) +{ +} + +void invalid_arg2(int[] invalid = {1, 2, 3}) +{ +} diff --git a/sourcepawn/compiler/tests/fail-bad-array-decls.txt b/sourcepawn/compiler/tests/fail-bad-array-decls.txt new file mode 100644 index 00000000..1f7022da --- /dev/null +++ b/sourcepawn/compiler/tests/fail-bad-array-decls.txt @@ -0,0 +1,6 @@ +(1) : error 162: cannot create dynamic arrays in global scope - did you mean to create a fixed-length array with brackets after the variable name? +(6) : error 161: brackets after variable name indicate a fixed-size array, but a dynamic size was given - did you mean to use 'new int[size]' syntax? +(7) : error 160: brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given +(10) : error 159: brackets after variable name indicate a fixed-size array, but size could not be determined - either specify sizes, an array initializer, or use dynamic syntax (such as 'char[] x') +(14) : error 160: brackets in between type and variable name indicate a dynamic-size array, but a fixed-size initializer was given + diff --git a/sourcepawn/compiler/tests/fail-newdecls.sp b/sourcepawn/compiler/tests/fail-newdecls.sp index 197c4b10..510eef99 100644 --- a/sourcepawn/compiler/tests/fail-newdecls.sp +++ b/sourcepawn/compiler/tests/fail-newdecls.sp @@ -1,13 +1,15 @@ native int[] egg6(); forward float[] egg7(); new void crab4; -int[] yam1 = {1,2,3}, yam2[] = {3,4,5}; + +void bad(int[] yam[] = {1}) +{ +} forward void OnPluginStart(); public int OnPluginStart() { - } diff --git a/sourcepawn/compiler/tests/fail-newdecls.txt b/sourcepawn/compiler/tests/fail-newdecls.txt index 4258d3f8..8259b01d 100644 --- a/sourcepawn/compiler/tests/fail-newdecls.txt +++ b/sourcepawn/compiler/tests/fail-newdecls.txt @@ -1,5 +1,5 @@ (1) : error 141: natives, forwards, and public functions cannot return arrays (2) : error 141: natives, forwards, and public functions cannot return arrays (3) : error 143: new-style declarations should not have "new" -(4) : error 121: cannot specify array dimensions on both type and name -(6) : error 025: function heading differs from prototype +(5) : error 121: cannot specify array dimensions on both type and name +(9) : error 025: function heading differs from prototype diff --git a/sourcepawn/compiler/tests/ok-new-decl-args.sp b/sourcepawn/compiler/tests/ok-new-decl-args.sp index 75fe92f7..c2e25745 100644 --- a/sourcepawn/compiler/tests/ok-new-decl-args.sp +++ b/sourcepawn/compiler/tests/ok-new-decl-args.sp @@ -2,7 +2,7 @@ stock A(int n) { } -stock B(int n[]) +stock B(int n[10]) { } diff --git a/sourcepawn/compiler/tests/ok-newdecls.sp b/sourcepawn/compiler/tests/ok-newdecls.sp index 33000f14..581e0131 100644 --- a/sourcepawn/compiler/tests/ok-newdecls.sp +++ b/sourcepawn/compiler/tests/ok-newdecls.sp @@ -9,10 +9,8 @@ new crab2 = 5; bool crab3 = true; int crab4 = 6; new crab5[] = {1, 2, 3}; -bool[] crab6 = {true, false, false, true} bool crab7[] = {false, true, true} char crab8[] = "hello" -char[] crab9 = "bye" native float operator*(float oper1, float oper2) = FloatMul; @@ -41,7 +39,6 @@ new Float:ham, bool:ham2; int cram, cram2, cram3; new cram4[] = {1, 2}, cram5[] = {3, 4, 7} int cram6[] = {1, 2}, cram7[] = {3, 4, 7} -int[] cram8 = {3, 4}, cram9 = {4, 8, 10} public OnPluginStart() { @@ -50,6 +47,4 @@ public OnPluginStart() cram4[0] = 2 cram5[2] = 2 cram7[2] = 2 - cram8[1] = 5 - cram9[2] = 5 }