mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-25 12:41:19 +00:00
adding 'final'
This commit is contained in:
parent
072bff44e6
commit
50f905b821
4 changed files with 31 additions and 0 deletions
2
ast.h
2
ast.h
|
@ -73,6 +73,8 @@ enum {
|
||||||
*/
|
*/
|
||||||
AST_FLAG_ARRAY_INIT = 1 << 10,
|
AST_FLAG_ARRAY_INIT = 1 << 10,
|
||||||
|
|
||||||
|
AST_FLAG_FINAL_DECL = 1 << 11,
|
||||||
|
|
||||||
AST_FLAG_LAST,
|
AST_FLAG_LAST,
|
||||||
AST_FLAG_TYPE_MASK = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
|
AST_FLAG_TYPE_MASK = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
|
||||||
};
|
};
|
||||||
|
|
21
parser.c
21
parser.c
|
@ -2862,6 +2862,14 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(parser_tokval(parser), "final")) {
|
||||||
|
flags |= AST_FLAG_FINAL_DECL;
|
||||||
|
if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
|
||||||
|
parseerror(parser, "`final` attribute has no parameters, expected `]]`");
|
||||||
|
*cvq = CV_WRONG;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
|
else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
|
||||||
flags |= AST_FLAG_ALIAS;
|
flags |= AST_FLAG_ALIAS;
|
||||||
*message = NULL;
|
*message = NULL;
|
||||||
|
@ -2966,6 +2974,8 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *
|
||||||
had_var = true;
|
had_var = true;
|
||||||
else if (!strcmp(parser_tokval(parser), "noref"))
|
else if (!strcmp(parser_tokval(parser), "noref"))
|
||||||
had_noref = true;
|
had_noref = true;
|
||||||
|
else if (!strcmp(parser_tokval(parser), "final"))
|
||||||
|
flags |= AST_FLAG_FINAL_DECL;
|
||||||
else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
|
else if (!had_const && !had_var && !had_noref && !had_attrib && !had_static && !flags) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5289,6 +5299,12 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
retval = false;
|
retval = false;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (old->flags & AST_FLAG_FINAL_DECL) {
|
||||||
|
parseerror(parser, "cannot redeclare variable `%s`, declared final here: %s:%i",
|
||||||
|
var->name, ast_ctx(old).file, ast_ctx(old).line);
|
||||||
|
retval = false;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
proto = (ast_value*)old;
|
proto = (ast_value*)old;
|
||||||
if (!ast_istype(old, ast_value)) {
|
if (!ast_istype(old, ast_value)) {
|
||||||
parseerror(parser, "internal error: not an ast_value");
|
parseerror(parser, "internal error: not an ast_value");
|
||||||
|
@ -5302,6 +5318,11 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
proto->expression.flags |= var->expression.flags;
|
proto->expression.flags |= var->expression.flags;
|
||||||
|
/* copy the context for finals,
|
||||||
|
* so the error can show where it was actually made 'final'
|
||||||
|
*/
|
||||||
|
if (proto->expression.flags & AST_FLAG_FINAL_DECL)
|
||||||
|
ast_ctx(old) = ast_ctx(var);
|
||||||
ast_delete(var);
|
ast_delete(var);
|
||||||
var = proto;
|
var = proto;
|
||||||
}
|
}
|
||||||
|
|
3
tests/final.qc
Normal file
3
tests/final.qc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
float here;
|
||||||
|
final float here;
|
||||||
|
float here;
|
5
tests/final.tmpl
Normal file
5
tests/final.tmpl
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
I: final.qc
|
||||||
|
D: final keyword
|
||||||
|
T: -fail
|
||||||
|
C: -std=gmqcc
|
||||||
|
F: -no-defs
|
Loading…
Reference in a new issue