Fix compile crash when returning a string literal
This fixes a crash during compile-time when returning a string or array literal from a function. Now the compiler will give an error instead. See 1) here: http://forum.sa-mp.com/showthread.php?t=355877 --------- test code -------- native use(...); return_string() { new string[] = "string"; return string; } return_string_literal() { return "string"; // error 029: invalid expression, assumed zero } return_number() { return 0; } main() { new n = return_number(); // OK new s[100]; s = return_string(); // OK s = return_string_literal(); // error 033: array must be indexed (variable "s") use(n, s); } ----- end of test code -----
This commit is contained in:
parent
c20d9cb33b
commit
6133e9d183
@ -5621,7 +5621,7 @@ static void doreturn(void)
|
|||||||
if ((rettype & uRETVALUE)!=0) {
|
if ((rettype & uRETVALUE)!=0) {
|
||||||
int retarray=(ident==iARRAY || ident==iREFARRAY);
|
int retarray=(ident==iARRAY || ident==iREFARRAY);
|
||||||
/* there was an earlier "return" statement in this function */
|
/* there was an earlier "return" statement in this function */
|
||||||
if (sub==NULL && retarray || sub!=NULL && !retarray)
|
if ((sub==NULL && retarray && sym!=NULL) || sub!=NULL && !retarray)
|
||||||
error(79); /* mixing "return array;" and "return value;" */
|
error(79); /* mixing "return array;" and "return value;" */
|
||||||
if (retarray && (curfunc->usage & uPUBLIC)!=0)
|
if (retarray && (curfunc->usage & uPUBLIC)!=0)
|
||||||
error(90,curfunc->name); /* public function may not return array */
|
error(90,curfunc->name); /* public function may not return array */
|
||||||
@ -5634,76 +5634,80 @@ static void doreturn(void)
|
|||||||
if (ident==iARRAY || ident==iREFARRAY) {
|
if (ident==iARRAY || ident==iREFARRAY) {
|
||||||
int dim[sDIMEN_MAX],numdim;
|
int dim[sDIMEN_MAX],numdim;
|
||||||
cell arraysize;
|
cell arraysize;
|
||||||
assert(sym!=NULL);
|
if (sym==NULL) {
|
||||||
if (sub!=NULL) {
|
/* array literals cannot be returned directly */
|
||||||
assert(sub->ident==iREFARRAY);
|
error(29); /* invalid expression, assumed zero */
|
||||||
/* this function has an array attached already; check that the current
|
} else {
|
||||||
* "return" statement returns exactly the same array
|
if (sub!=NULL) {
|
||||||
*/
|
assert(sub->ident==iREFARRAY);
|
||||||
level=sym->dim.array.level;
|
/* this function has an array attached already; check that the current
|
||||||
if (sub->dim.array.level!=level) {
|
* "return" statement returns exactly the same array
|
||||||
error(48); /* array dimensions must match */
|
*/
|
||||||
|
level=sym->dim.array.level;
|
||||||
|
if (sub->dim.array.level!=level) {
|
||||||
|
error(48); /* array dimensions must match */
|
||||||
|
} else {
|
||||||
|
for (numdim=0; numdim<=level; numdim++) {
|
||||||
|
dim[numdim]=(int)sub->dim.array.length;
|
||||||
|
if (sym->dim.array.length!=dim[numdim])
|
||||||
|
error(47); /* array sizes must match */
|
||||||
|
if (numdim<level) {
|
||||||
|
sym=finddepend(sym);
|
||||||
|
sub=finddepend(sub);
|
||||||
|
assert(sym!=NULL && sub!=NULL);
|
||||||
|
/* ^^^ both arrays have the same dimensions (this was checked
|
||||||
|
* earlier) so the dependend should always be found
|
||||||
|
*/
|
||||||
|
} /* if */
|
||||||
|
} /* for */
|
||||||
|
} /* if */
|
||||||
} else {
|
} else {
|
||||||
|
int idxtag[sDIMEN_MAX];
|
||||||
|
int argcount;
|
||||||
|
/* this function does not yet have an array attached; clone the
|
||||||
|
* returned symbol beneath the current function
|
||||||
|
*/
|
||||||
|
sub=sym;
|
||||||
|
assert(sub!=NULL);
|
||||||
|
level=sub->dim.array.level;
|
||||||
for (numdim=0; numdim<=level; numdim++) {
|
for (numdim=0; numdim<=level; numdim++) {
|
||||||
dim[numdim]=(int)sub->dim.array.length;
|
dim[numdim]=(int)sub->dim.array.length;
|
||||||
if (sym->dim.array.length!=dim[numdim])
|
idxtag[numdim]=sub->x.tags.index;
|
||||||
error(47); /* array sizes must match */
|
|
||||||
if (numdim<level) {
|
if (numdim<level) {
|
||||||
sym=finddepend(sym);
|
|
||||||
sub=finddepend(sub);
|
sub=finddepend(sub);
|
||||||
assert(sym!=NULL && sub!=NULL);
|
assert(sub!=NULL);
|
||||||
/* ^^^ both arrays have the same dimensions (this was checked
|
|
||||||
* earlier) so the dependend should always be found
|
|
||||||
*/
|
|
||||||
} /* if */
|
} /* if */
|
||||||
|
/* check that all dimensions are known */
|
||||||
|
if (dim[numdim]<=0)
|
||||||
|
error(46,sym->name);
|
||||||
} /* for */
|
} /* for */
|
||||||
|
/* the address of the array is stored in a hidden parameter; the address
|
||||||
|
* of this parameter is 1 + the number of parameters (times the size of
|
||||||
|
* a cell) + the size of the stack frame and the return address
|
||||||
|
* base + 0*sizeof(cell) == previous "base"
|
||||||
|
* base + 1*sizeof(cell) == function return address
|
||||||
|
* base + 2*sizeof(cell) == number of arguments
|
||||||
|
* base + 3*sizeof(cell) == first argument of the function
|
||||||
|
* ...
|
||||||
|
* base + ((n-1)+3)*sizeof(cell) == last argument of the function
|
||||||
|
* base + (n+3)*sizeof(cell) == hidden parameter with array address
|
||||||
|
*/
|
||||||
|
assert(curfunc!=NULL);
|
||||||
|
assert(curfunc->dim.arglist!=NULL);
|
||||||
|
for (argcount=0; curfunc->dim.arglist[argcount].ident!=0; argcount++)
|
||||||
|
/* nothing */;
|
||||||
|
sub=addvariable(curfunc->name,(argcount+3)*sizeof(cell),iREFARRAY,sGLOBAL,curfunc->tag,dim,numdim,idxtag);
|
||||||
|
sub->parent=curfunc;
|
||||||
} /* if */
|
} /* if */
|
||||||
} else {
|
/* get the hidden parameter, copy the array (the array is on the heap;
|
||||||
int idxtag[sDIMEN_MAX];
|
* it stays on the heap for the moment, and it is removed -usually- at
|
||||||
int argcount;
|
* the end of the expression/statement, see expression() in SC3.C)
|
||||||
/* this function does not yet have an array attached; clone the
|
|
||||||
* returned symbol beneath the current function
|
|
||||||
*/
|
*/
|
||||||
sub=sym;
|
address(sub,sALT); /* ALT = destination */
|
||||||
assert(sub!=NULL);
|
arraysize=calc_arraysize(dim,numdim,0);
|
||||||
level=sub->dim.array.level;
|
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
||||||
for (numdim=0; numdim<=level; numdim++) {
|
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
||||||
dim[numdim]=(int)sub->dim.array.length;
|
|
||||||
idxtag[numdim]=sub->x.tags.index;
|
|
||||||
if (numdim<level) {
|
|
||||||
sub=finddepend(sub);
|
|
||||||
assert(sub!=NULL);
|
|
||||||
} /* if */
|
|
||||||
/* check that all dimensions are known */
|
|
||||||
if (dim[numdim]<=0)
|
|
||||||
error(46,sym->name);
|
|
||||||
} /* for */
|
|
||||||
/* the address of the array is stored in a hidden parameter; the address
|
|
||||||
* of this parameter is 1 + the number of parameters (times the size of
|
|
||||||
* a cell) + the size of the stack frame and the return address
|
|
||||||
* base + 0*sizeof(cell) == previous "base"
|
|
||||||
* base + 1*sizeof(cell) == function return address
|
|
||||||
* base + 2*sizeof(cell) == number of arguments
|
|
||||||
* base + 3*sizeof(cell) == first argument of the function
|
|
||||||
* ...
|
|
||||||
* base + ((n-1)+3)*sizeof(cell) == last argument of the function
|
|
||||||
* base + (n+3)*sizeof(cell) == hidden parameter with array address
|
|
||||||
*/
|
|
||||||
assert(curfunc!=NULL);
|
|
||||||
assert(curfunc->dim.arglist!=NULL);
|
|
||||||
for (argcount=0; curfunc->dim.arglist[argcount].ident!=0; argcount++)
|
|
||||||
/* nothing */;
|
|
||||||
sub=addvariable(curfunc->name,(argcount+3)*sizeof(cell),iREFARRAY,sGLOBAL,curfunc->tag,dim,numdim,idxtag);
|
|
||||||
sub->parent=curfunc;
|
|
||||||
} /* if */
|
} /* if */
|
||||||
/* get the hidden parameter, copy the array (the array is on the heap;
|
|
||||||
* it stays on the heap for the moment, and it is removed -usually- at
|
|
||||||
* the end of the expression/statement, see expression() in SC3.C)
|
|
||||||
*/
|
|
||||||
address(sub,sALT); /* ALT = destination */
|
|
||||||
arraysize=calc_arraysize(dim,numdim,0);
|
|
||||||
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
|
|
||||||
/* moveto1(); is not necessary, callfunction() does a popreg() */
|
|
||||||
} /* if */
|
} /* if */
|
||||||
} else {
|
} else {
|
||||||
/* this return statement contains no expression */
|
/* this return statement contains no expression */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user