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_binary_name(char *binfname);
 | 
			
		||||
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_new_decl(declinfo_t *decl, int flags);
 | 
			
		||||
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];
 | 
			
		||||
  cell val;
 | 
			
		||||
  char *str;
 | 
			
		||||
  token_t tok;
 | 
			
		||||
  int tag,exprtag;
 | 
			
		||||
  int symbolline;
 | 
			
		||||
  symbol *sym;
 | 
			
		||||
@ -2884,11 +2885,41 @@ static void decl_const(int vclass)
 | 
			
		||||
  do {
 | 
			
		||||
    int orgfline;
 | 
			
		||||
 | 
			
		||||
    tag=pc_addtag(NULL);
 | 
			
		||||
    if (lex(&val,&str)!=tSYMBOL)        /* read in (new) token */
 | 
			
		||||
      error(20,str);                    /* invalid symbol name */
 | 
			
		||||
    // Since spcomp is terrible, it's hard to use parse_decl() here - there
 | 
			
		||||
    // are all sorts of restrictions on const. We just implement some quick
 | 
			
		||||
    // 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 */
 | 
			
		||||
    strcpy(constname,str);              /* save symbol name */
 | 
			
		||||
    needtoken('=');
 | 
			
		||||
    constexpr(&val,&exprtag,NULL);      /* get value */
 | 
			
		||||
 | 
			
		||||
@ -3034,6 +3065,50 @@ static int consume_line()
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
  token_t tok;
 | 
			
		||||
@ -3050,51 +3125,9 @@ static int parse_new_typeexpr(typeinfo_t *type, const token_t *first, int flags)
 | 
			
		||||
    lextok(&tok);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (tok.id) {
 | 
			
		||||
    case tINT:
 | 
			
		||||
      type->tag = 0;
 | 
			
		||||
      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;
 | 
			
		||||
  }
 | 
			
		||||
  type->tag = parse_new_typename(&tok);
 | 
			
		||||
  if (type->tag == -1)
 | 
			
		||||
    goto err_out;
 | 
			
		||||
 | 
			
		||||
  // Note: we could have already filled in the prefix array bits, so we check
 | 
			
		||||
  // 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.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.
 | 
			
		||||
  if (matchtoken(tCONST))
 | 
			
		||||
    decl->type.usage |= uCONST;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
#pragma semicolon 1
 | 
			
		||||
 | 
			
		||||
native IsValidEntity(entity);
 | 
			
		||||
 | 
			
		||||
methodmap Entity
 | 
			
		||||
{
 | 
			
		||||
	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