Fixes bug 530623.
}
public void generate_constant_declaration (Constant c, CCodeFile decl_space, bool definition = false) {
+ if (c.parent_symbol is Block) {
+ // local constant
+ return;
+ }
+
if (add_symbol_declaration (decl_space, c, c.get_cname ())) {
return;
}
}
public override void visit_constant (Constant c) {
+ if (c.parent_symbol is Block) {
+ // local constant
+
+ generate_type_declaration (c.type_reference, cfile);
+
+ c.value.emit (this);
+
+ string type_name = c.type_reference.get_const_cname ();
+ string arr = "";
+ if (c.type_reference is ArrayType) {
+ arr = "[]";
+ }
+
+ if (c.type_reference.compatible (string_type)) {
+ type_name = "const char";
+ arr = "[]";
+ }
+
+ var cinitializer = get_cvalue (c.value);
+
+ ccode.add_declaration (type_name, new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), cinitializer), CCodeModifiers.STATIC);
+
+ return;
+ }
+
generate_constant_declaration (c, cfile, true);
if (!c.is_internal_symbol ()) {
private List<Statement> statement_list = new ArrayList<Statement> ();
private List<LocalVariable> local_variables = new ArrayList<LocalVariable> ();
+ private List<Constant> local_constants = new ArrayList<Constant> ();
/**
* Creates a new block.
var parent_block = parent_symbol;
while (parent_block is Block || parent_block is Method || parent_block is PropertyAccessor) {
if (parent_block.scope.lookup (local.name) != null) {
- Report.error (local.source_reference, "Local variable `%s' conflicts with another local variable declared in a parent scope".printf (local.name));
+ Report.error (local.source_reference, "Local variable `%s' conflicts with a local variable or constant declared in a parent scope".printf (local.name));
break;
}
parent_block = parent_block.parent_symbol;
return local_variables;
}
+ public void add_local_constant (Constant constant) {
+ var parent_block = parent_symbol;
+ while (parent_block is Block || parent_block is Method || parent_block is PropertyAccessor) {
+ if (parent_block.scope.lookup (constant.name) != null) {
+ Report.error (constant.source_reference, "Local constant `%s' conflicts with a local variable or constant declared in a parent scope".printf (constant.name));
+ break;
+ }
+ parent_block = parent_block.parent_symbol;
+ }
+ local_constants.add (constant);
+ scope.add (constant.name, constant);
+ }
+
public override void accept (CodeVisitor visitor) {
visitor.visit_block (this);
}
local.active = false;
}
+ foreach (Constant constant in local_constants) {
+ constant.active = false;
+ }
+
// use get_statements () instead of statement_list to not miss errors within StatementList objects
foreach (Statement stmt in get_statements ()) {
add_error_types (stmt.get_error_types ());
analyzer.current_source_file = old_source_file;
analyzer.current_symbol = old_symbol;
+ active = true;
+
return !error;
}
is_decl = true;
parse_local_variable_declarations (block);
break;
+ case TokenType.CONST:
+ is_decl = true;
+ parse_local_constant_declarations (block);
+ break;
case TokenType.OP_INC:
case TokenType.OP_DEC:
case TokenType.BASE:
return new LocalVariable (type, id, initializer, get_src (begin));
}
+ void parse_local_constant_declarations (Block block) throws ParseError {
+ expect (TokenType.CONST);
+ var constant_type = parse_type (false, false);
+ do {
+ DataType type_copy = constant_type.copy ();
+ var local = parse_local_constant (type_copy);
+ block.add_statement (new DeclarationStatement (local, local.source_reference));
+ block.add_local_constant (local);
+ local.active = false;
+ } while (accept (TokenType.COMMA));
+ expect (TokenType.SEMICOLON);
+ }
+
+ Constant parse_local_constant (DataType constant_type) throws ParseError {
+ var begin = get_location ();
+ string id = parse_identifier ();
+
+ var type = parse_inline_array_type (constant_type);
+
+ expect (TokenType.ASSIGN);
+ var initializer = parse_expression ();
+
+ return new Constant (id, type, initializer, get_src (begin));
+ }
+
Statement parse_expression_statement () throws ParseError {
var begin = get_location ();
var expr = parse_statement_expression ();
}
public override void visit_constant (Constant c) {
+ var old_scope = current_scope;
current_scope = c.scope;
c.accept_children (this);
+
+ current_scope = old_scope;
}
public override void visit_field (Field f) {