From 759112e495561f9b37c4f19491fa794667803697 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Sun, 20 Mar 2022 11:17:00 +0100 Subject: [PATCH] #2639 --- TestSuite/errors/err0502.pas | 12 ++++++ .../TreeConversion/CompilationErrors.cs | 37 +++++++++++++++++++ .../TreeConversion/compilation_context.cs | 3 ++ .../TreeConversion/syntax_tree_visitor.cs | 33 ++++++++++------- bin/Lng/Eng/SemanticErrors_ds.dat | 4 ++ bin/Lng/Rus/SemanticErrors_ds.dat | 4 ++ bin/Lng/Ukr/SemanticErrors_ds.dat | 4 ++ 7 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 TestSuite/errors/err0502.pas diff --git a/TestSuite/errors/err0502.pas b/TestSuite/errors/err0502.pas new file mode 100644 index 000000000..77712402b --- /dev/null +++ b/TestSuite/errors/err0502.pas @@ -0,0 +1,12 @@ +//!Нельзя обратиться к нестатическому методу f1 из инициализатора статического поля +type + t1 = class + + public function f1 := 0; + + public static x := f1; + end; + +begin + t1.x.Println; +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/CompilationErrors.cs b/TreeConverter/TreeConversion/CompilationErrors.cs index 040055e15..5ac5ad9f1 100644 --- a/TreeConverter/TreeConversion/CompilationErrors.cs +++ b/TreeConverter/TreeConversion/CompilationErrors.cs @@ -1947,6 +1947,43 @@ namespace PascalABCCompiler.TreeConverter return string.Format(StringResources.Get(message, name)); } } + + public class CanNotReferenceToNonStaticFromStaticInitializer : CompilationErrorWithLocation + { + string message = "CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_INITIALIZER"; + string name; + public CanNotReferenceToNonStaticFromStaticInitializer(definition_node dn, location loc) + : base(loc) + { + string meth_name; + switch (dn.general_node_type) + { + case general_node_type.function_node: + meth_name = (dn as function_node).name; + if (meth_name.Contains(compiler_string_consts.event_add_method_prefix) || + meth_name.Contains(compiler_string_consts.event_remove_method_prefix)) + { + meth_name = meth_name.Replace(compiler_string_consts.event_add_method_prefix, ""); + meth_name = meth_name.Replace(compiler_string_consts.event_remove_method_prefix, ""); + message = "CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_INITIALIZER"; + } + break; + case general_node_type.variable_node: + meth_name = (dn as var_definition_node).name; + message = "CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_INITIALIZER"; + break; + default: + message = "CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_INITIALIZER"; + meth_name = ""; + break; + } + name = meth_name; + } + public override string ToString() + { + return string.Format(StringResources.Get(message, name)); + } + } /*->*/ public class CanNotReferenceToNonStaticFieldWithType : CompilationError { diff --git a/TreeConverter/TreeConversion/compilation_context.cs b/TreeConverter/TreeConversion/compilation_context.cs index af9c565ef..8f5e6dc54 100644 --- a/TreeConverter/TreeConversion/compilation_context.cs +++ b/TreeConverter/TreeConversion/compilation_context.cs @@ -332,6 +332,7 @@ namespace PascalABCCompiler.TreeConverter is_order_independed_method_description = false; _has_nested_functions = false; finally_blocks_depth = 0; + static_variable_converted = false; } public void clear_type_prededinitions() @@ -339,6 +340,8 @@ namespace PascalABCCompiler.TreeConverter _types_predefined.Clear(); } + public bool static_variable_converted; + public bool inStaticArea() { if (converted_type != null && top_function != null) diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 5621292d3..1ba2220d9 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -8949,22 +8949,27 @@ namespace PascalABCCompiler.TreeConverter if (scope != null) if (context.WithVariables.ContainsKey(scope)) return context.WithVariables[scope]; - else + else if (context.WithTypes.Contains(scope)) + { + switch (dn.semantic_node_type) + { + case semantic_node_type.class_field: if (!(dn as class_field).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field, loc, null)); break; + case semantic_node_type.compiled_variable_definition: if (!(dn as compiled_variable_definition).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field, loc, null)); break; + case semantic_node_type.compiled_property_node: + case semantic_node_type.common_property_node: if ((dn as property_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticPropertyWithType(dn as property_node, loc, null)); break; + case semantic_node_type.compiled_function_node: + case semantic_node_type.common_method_node: if ((dn as function_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticMethodWithType((dn as function_node).name, loc)); break; + } + } + if (context.static_variable_converted) { - switch (dn.semantic_node_type) - { - case semantic_node_type.class_field : if (!(dn as class_field).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field,loc,null)); break; - case semantic_node_type.compiled_variable_definition : if (!(dn as compiled_variable_definition).IsStatic) AddError(new CanNotReferenceToNonStaticFieldWithType(dn as class_field,loc,null)); break; - case semantic_node_type.compiled_property_node: - case semantic_node_type.common_property_node : if ((dn as property_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticPropertyWithType(dn as property_node,loc,null)); break; - case semantic_node_type.compiled_function_node: - case semantic_node_type.common_method_node: if ((dn as function_node).polymorphic_state != SemanticTree.polymorphic_state.ps_static) AddError(new CanNotReferenceToNonStaticMethodWithType((dn as function_node).name,loc)); break; - } + AddError(new CanNotReferenceToNonStaticFromStaticInitializer(dn, loc)); + return null; } - if (context.inStaticArea()) + else if (context.inStaticArea()) { - AddError(new CanNotReferenceToNonStaticFromStatic(dn,loc)); + AddError(new CanNotReferenceToNonStaticFromStatic(dn, loc)); return null; } else @@ -16775,6 +16780,7 @@ namespace PascalABCCompiler.TreeConverter public override void visit(SyntaxTree.var_def_statement _var_def_statement) { var_def_statement_converting = true; + if (_var_def_statement.vars_type != null && _var_def_statement.vars_type is procedure_header) { var ph = _var_def_statement.vars_type as procedure_header; @@ -16786,7 +16792,7 @@ namespace PascalABCCompiler.TreeConverter } } - + context.static_variable_converted = _var_def_statement.var_attr == SyntaxTree.definition_attribute.Static ? true : false; if (_var_def_statement.vars_type == null && _var_def_statement.inital_value is SyntaxTree.function_lambda_definition fld) { if (fld.formal_parameters != null && fld.formal_parameters.params_list.Select(x => x.vars_type).Any(x=>x is lambda_inferred_type)) @@ -16963,6 +16969,7 @@ namespace PascalABCCompiler.TreeConverter if (context.converted_type != null && context.converting_block() == block_type.type_block && context.converted_type.IsStatic && _var_def_statement.var_attr != definition_attribute.Static) AddError(get_location(_var_def_statement), "STATIC_CLASSES_CANNOT_NON_STATIC_MEMBERS"); var_def_statement_converting = false; + context.static_variable_converted = false; if (is_event) return; context.save_var_definitions(); diff --git a/bin/Lng/Eng/SemanticErrors_ds.dat b/bin/Lng/Eng/SemanticErrors_ds.dat index 15524f5d1..48b748e5a 100644 --- a/bin/Lng/Eng/SemanticErrors_ds.dat +++ b/bin/Lng/Eng/SemanticErrors_ds.dat @@ -39,6 +39,10 @@ CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_METHOD=An object reference CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_METHOD=An object reference is required for the nonstatic event '{0}' CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_METHOD=An object reference is required for the nonstatic field '{0}' CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC=An object reference is required for the nonstatic field, method, or property '{0}' +CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_INITIALIZER=An object reference is required for the nonstatic method '{0}' +CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_INITIALIZER=An object reference is required for the nonstatic event '{0}' +CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_INITIALIZER=An object reference is required for the nonstatic field '{0}' +CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC_INITIALIZER=An object reference is required for the nonstatic field, method, or property '{0}' LEFT_SIDE_CANNOT_BE_ASSIGNED_TO=Left side cannot be assigned to STATEMENT_EXPECTED=Statement expected EXPRESSION_IN_LOCK_STATEMENT_RETURNED_NOT_A_REFERENCE_TYPE=The type of expression is not a reference type as required by the lock statement diff --git a/bin/Lng/Rus/SemanticErrors_ds.dat b/bin/Lng/Rus/SemanticErrors_ds.dat index 32c2ac355..ed15488e4 100644 --- a/bin/Lng/Rus/SemanticErrors_ds.dat +++ b/bin/Lng/Rus/SemanticErrors_ds.dat @@ -39,6 +39,10 @@ CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_METHOD=Нельзя обр CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_METHOD=Нельзя обратиться к нестатическому событию {0} из статического метода CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_METHOD=Нельзя обратиться к нестатическому полю {0} из статического метода CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC=Нельзя обратиться к нестатическому определению {0} из статического метода +CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому методу {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому событию {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому определению {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому полю {0} из инициализатора статического поля LEFT_SIDE_CANNOT_BE_ASSIGNED_TO=Нельзя присвоить левой части STATEMENT_EXPECTED=Ожидался оператор EXPRESSION_IN_LOCK_STATEMENT_RETURNED_NOT_A_REFERENCE_TYPE=Выражение должно возвращать ссылочный тип, как того требует оператор lock diff --git a/bin/Lng/Ukr/SemanticErrors_ds.dat b/bin/Lng/Ukr/SemanticErrors_ds.dat index 636adc20a..37302359f 100644 --- a/bin/Lng/Ukr/SemanticErrors_ds.dat +++ b/bin/Lng/Ukr/SemanticErrors_ds.dat @@ -39,6 +39,10 @@ CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_METHOD=Не можна з CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_METHOD=Не можна звернутися до нестатичної події {0} з статичного методу CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_METHOD=Не можна звернутися до нестатичного поля {0} з статичного методу CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC=Не можна звернутися до нестатичного визначення {0} з статичного методу +CAN_NOT_REFERENCE_TO_NONSTATIC_METHOD_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому методу {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_EVENT_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому событию {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому определению {0} из инициализатора статического поля +CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_FROM_STATIC_INITIALIZER=Нельзя обратиться к нестатическому полю {0} из инициализатора статического поля LEFT_SIDE_CANNOT_BE_ASSIGNED_TO=Не можна присвоїти лівій частині STATEMENT_EXPECTED=Очікувався оператор EXPRESSION_IN_LOCK_STATEMENT_RETURNED_NOT_A_REFERENCE_TYPE=Вираз повинен повертати тип посилання, як того вимагає оператор lock