Merge pull request #97 from alliedmodders/bug-6179
Fix const with newdecls and a varargs bug. (bug 6179)
This commit is contained in:
commit
8125faeb70
@ -154,6 +154,7 @@ static int *readwhile(void);
|
|||||||
static void inst_datetime_defines(void);
|
static void inst_datetime_defines(void);
|
||||||
static void inst_binary_name(char *binfname);
|
static void inst_binary_name(char *binfname);
|
||||||
static int operatorname(char *name);
|
static int operatorname(char *name);
|
||||||
|
static int parse_new_typename(const token_t *tok);
|
||||||
static int reparse_old_decl(declinfo_t *decl, int flags);
|
static int reparse_old_decl(declinfo_t *decl, int flags);
|
||||||
static int reparse_new_decl(declinfo_t *decl, int flags);
|
static int reparse_new_decl(declinfo_t *decl, int flags);
|
||||||
static void check_void_decl(const declinfo_t *decl, int variable);
|
static void check_void_decl(const declinfo_t *decl, int variable);
|
||||||
@ -2875,7 +2876,7 @@ static void decl_const(int vclass)
|
|||||||
{
|
{
|
||||||
char constname[sNAMEMAX+1];
|
char constname[sNAMEMAX+1];
|
||||||
cell val;
|
cell val;
|
||||||
char *str;
|
token_t tok;
|
||||||
int tag,exprtag;
|
int tag,exprtag;
|
||||||
int symbolline;
|
int symbolline;
|
||||||
symbol *sym;
|
symbol *sym;
|
||||||
@ -2884,11 +2885,41 @@ static void decl_const(int vclass)
|
|||||||
do {
|
do {
|
||||||
int orgfline;
|
int orgfline;
|
||||||
|
|
||||||
tag=pc_addtag(NULL);
|
// Since spcomp is terrible, it's hard to use parse_decl() here - there
|
||||||
if (lex(&val,&str)!=tSYMBOL) /* read in (new) token */
|
// are all sorts of restrictions on const. We just implement some quick
|
||||||
error(20,str); /* invalid symbol name */
|
// detection instead.
|
||||||
|
int tag = 0;
|
||||||
|
switch (lextok(&tok)) {
|
||||||
|
case tINT:
|
||||||
|
case tOBJECT:
|
||||||
|
case tCHAR:
|
||||||
|
tag = parse_new_typename(&tok);
|
||||||
|
break;
|
||||||
|
case tLABEL:
|
||||||
|
tag = pc_addtag(tok.str);
|
||||||
|
break;
|
||||||
|
case tSYMBOL:
|
||||||
|
// See if we can peek ahead another symbol.
|
||||||
|
if (lexpeek(tSYMBOL)) {
|
||||||
|
// This is a new-style declaration.
|
||||||
|
tag = parse_new_typename(&tok);
|
||||||
|
} else {
|
||||||
|
// Otherwise, we got "const X ..." so the tag is int. Give the
|
||||||
|
// symbol back to the lexer so we get it as the name.
|
||||||
|
lexpush();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error(122);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expecttoken(tSYMBOL, &tok))
|
||||||
|
strcpy(constname, tok.str);
|
||||||
|
else
|
||||||
|
strcpy(constname, "<unknown>");
|
||||||
|
|
||||||
symbolline=fline; /* save line where symbol was found */
|
symbolline=fline; /* save line where symbol was found */
|
||||||
strcpy(constname,str); /* save symbol name */
|
|
||||||
needtoken('=');
|
needtoken('=');
|
||||||
constexpr(&val,&exprtag,NULL); /* get value */
|
constexpr(&val,&exprtag,NULL); /* get value */
|
||||||
|
|
||||||
@ -3034,6 +3065,50 @@ static int consume_line()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_new_typename(const token_t *tok)
|
||||||
|
{
|
||||||
|
switch (tok->id) {
|
||||||
|
case tINT:
|
||||||
|
return 0;
|
||||||
|
case tCHAR:
|
||||||
|
return pc_tag_string;
|
||||||
|
case tVOID:
|
||||||
|
return pc_tag_void;
|
||||||
|
case tOBJECT:
|
||||||
|
return pc_tag_object;
|
||||||
|
case tLABEL:
|
||||||
|
error(120);
|
||||||
|
return pc_addtag(tok->str);
|
||||||
|
case tSYMBOL:
|
||||||
|
{
|
||||||
|
if (strcmp(tok->str, "float") == 0)
|
||||||
|
return sc_rationaltag;
|
||||||
|
if (strcmp(tok->str, "bool") == 0)
|
||||||
|
return pc_tag_bool;
|
||||||
|
int tag = pc_findtag(tok->str);
|
||||||
|
if (tag == sc_rationaltag) {
|
||||||
|
error(98, "Float", "float");
|
||||||
|
} else if (tag == pc_tag_string) {
|
||||||
|
error(98, "String", "char");
|
||||||
|
} else if (tag == 0) {
|
||||||
|
error(98, "_", "int");
|
||||||
|
} else if (tag == -1) {
|
||||||
|
error(139, tok->str);
|
||||||
|
tag = 0;
|
||||||
|
} else {
|
||||||
|
// Perform some basic filters so we can start narrowing down what can
|
||||||
|
// be used as a type.
|
||||||
|
if (!(tag & TAGTYPEMASK))
|
||||||
|
error(139, tok->str);
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error(122);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
|
static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
|
||||||
{
|
{
|
||||||
token_t tok;
|
token_t tok;
|
||||||
@ -3050,51 +3125,9 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
|
|||||||
lextok(&tok);
|
lextok(&tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tok.id) {
|
type->tag = parse_new_typename(&tok);
|
||||||
case tINT:
|
if (type->tag == -1)
|
||||||
type->tag = 0;
|
goto err_out;
|
||||||
break;
|
|
||||||
case tCHAR:
|
|
||||||
type->tag = pc_tag_string;
|
|
||||||
break;
|
|
||||||
case tVOID:
|
|
||||||
type->tag = pc_tag_void;
|
|
||||||
break;
|
|
||||||
case tOBJECT:
|
|
||||||
type->tag = pc_tag_object;
|
|
||||||
break;
|
|
||||||
case tLABEL:
|
|
||||||
type->tag = pc_addtag(tok.str);
|
|
||||||
error(120);
|
|
||||||
break;
|
|
||||||
case tSYMBOL:
|
|
||||||
if (strcmp(tok.str, "float") == 0) {
|
|
||||||
type->tag = sc_rationaltag;
|
|
||||||
} else if (strcmp(tok.str, "bool") == 0) {
|
|
||||||
type->tag = pc_tag_bool;
|
|
||||||
} else {
|
|
||||||
type->tag = pc_findtag(tok.str);
|
|
||||||
if (type->tag == sc_rationaltag) {
|
|
||||||
error(98, "Float", "float");
|
|
||||||
} else if (type->tag == pc_tag_string) {
|
|
||||||
error(98, "String", "char");
|
|
||||||
} else if (type->tag == 0) {
|
|
||||||
error(98, "_", "int");
|
|
||||||
} else if (type->tag == -1) {
|
|
||||||
error(139, tok.str);
|
|
||||||
type->tag = 0;
|
|
||||||
} else {
|
|
||||||
// Perform some basic filters so we can start narrowing down what can
|
|
||||||
// be used as a type.
|
|
||||||
if (!(type->tag & TAGTYPEMASK))
|
|
||||||
error(139, tok.str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error(122);
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: we could have already filled in the prefix array bits, so we check
|
// Note: we could have already filled in the prefix array bits, so we check
|
||||||
// that ident != iARRAY before looking for an open bracket.
|
// that ident != iARRAY before looking for an open bracket.
|
||||||
@ -3432,6 +3465,10 @@ int parse_decl(declinfo_t *decl, int flags)
|
|||||||
decl->type.ident = iVARIABLE;
|
decl->type.ident = iVARIABLE;
|
||||||
decl->type.size = 1;
|
decl->type.size = 1;
|
||||||
|
|
||||||
|
// Match early varargs as old decl.
|
||||||
|
if (matchtoken(tELLIPS))
|
||||||
|
return parse_old_decl(decl, flags);
|
||||||
|
|
||||||
// Must attempt to match const first, since it's a common prefix.
|
// Must attempt to match const first, since it's a common prefix.
|
||||||
if (matchtoken(tCONST))
|
if (matchtoken(tCONST))
|
||||||
decl->type.usage |= uCONST;
|
decl->type.usage |= uCONST;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma semicolon 1
|
#pragma semicolon 1
|
||||||
|
|
||||||
|
native IsValidEntity(entity);
|
||||||
|
|
||||||
methodmap Entity
|
methodmap Entity
|
||||||
{
|
{
|
||||||
public Entity(const char[] className) {
|
public Entity(const char[] className) {
|
||||||
|
12
sourcepawn/compiler/tests/ok-newdecl-const.sp
Normal file
12
sourcepawn/compiler/tests/ok-newdecl-const.sp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// both fine
|
||||||
|
const MY_CONST = 1;
|
||||||
|
const Float:FLOAT_CONST = 1.0;
|
||||||
|
|
||||||
|
// error 020: invalid symbol name ""
|
||||||
|
const int MY_INT_COST = 1;
|
||||||
|
// error 001: expected token: "=", but found "-identifier-"
|
||||||
|
const float MY_FLOAT_CONST = 1.0;
|
||||||
|
|
||||||
|
public main()
|
||||||
|
{
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user