diff --git a/Compiler/PCU/PCUFileFormatVersion.cs b/Compiler/PCU/PCUFileFormatVersion.cs index 6a03d9faf..dc4bb8279 100644 --- a/Compiler/PCU/PCUFileFormatVersion.cs +++ b/Compiler/PCU/PCUFileFormatVersion.cs @@ -6,6 +6,6 @@ namespace PascalABCCompiler.PCU { public static class PCUFileFormatVersion { - public static System.Int16 Version = 118; + public static System.Int16 Version = 119; } } diff --git a/Compiler/PCU/PCUReader.cs b/Compiler/PCU/PCUReader.cs index 80b8690dd..4f3e09498 100644 --- a/Compiler/PCU/PCUReader.cs +++ b/Compiler/PCU/PCUReader.cs @@ -313,7 +313,13 @@ namespace PascalABCCompiler.PCU AddTypeSynonyms(pcu_file.interface_synonyms_offset, cun.scope); AddTypeSynonyms(pcu_file.implementation_synonyms_offset, cun.implementation_scope); //\ssyy - + for (int i = 0; i < pcu_file.names.Length; i++) + { + if (pcu_file.names[i].always_restore) + { + cun.scope.Find(pcu_file.names[i].name); + } + } ChangeState(this, PCUReaderWriterState.EndReadTree, unit); return unit; @@ -578,6 +584,7 @@ namespace PascalABCCompiler.PCU pcu_file.names[i].offset = br.ReadInt32(); pcu_file.names[i].symbol_kind = (symbol_kind)br.ReadByte(); pcu_file.names[i].special_scope = br.ReadByte(); + pcu_file.names[i].always_restore = br.ReadBoolean(); } //ssyy num_names = br.ReadInt32(); @@ -588,6 +595,7 @@ namespace PascalABCCompiler.PCU pcu_file.implementation_names[i].offset = br.ReadInt32(); pcu_file.implementation_names[i].symbol_kind = (symbol_kind)br.ReadByte(); pcu_file.implementation_names[i].special_scope = br.ReadByte(); + pcu_file.implementation_names[i].always_restore = br.ReadBoolean(); } //\ssyy int num_incl = br.ReadInt32(); @@ -2567,7 +2575,7 @@ namespace PascalABCCompiler.PCU si.symbol_kind = (symbol_kind)br.ReadByte(); si.semantic_node_type = (semantic_node_type)br.ReadByte(); - si.virtual_slot = br.ReadBoolean(); + si.always_restore = br.ReadBoolean(); si.is_static = br.ReadBoolean(); //Вроде это ненужно //SymbolInfo si2 = scope.FindWithoutCreation(name); diff --git a/Compiler/PCU/PCUWrappers.cs b/Compiler/PCU/PCUWrappers.cs index 62a6997e3..8a7b49427 100644 --- a/Compiler/PCU/PCUWrappers.cs +++ b/Compiler/PCU/PCUWrappers.cs @@ -189,7 +189,9 @@ namespace PascalABCCompiler.PCU { if (pcu_tsi == null) return true; - if (pcu_tsi.semantic_node_type == semantic_node_type.common_method_node && pcu_tsi.virtual_slot) + //if (pcu_tsi.semantic_node_type == semantic_node_type.common_method_node && pcu_tsi.virtual_slot) + // return true; + if (pcu_tsi.always_restore) return true; if (hasNotRestoreAttribute()) return false; diff --git a/Compiler/PCU/PCUWriter.cs b/Compiler/PCU/PCUWriter.cs index 441ef742e..04cca00f2 100644 --- a/Compiler/PCU/PCUWriter.cs +++ b/Compiler/PCU/PCUWriter.cs @@ -40,7 +40,7 @@ namespace PascalABCCompiler.PCU public byte special_scope=0;//говорит о том что этот символ добавляется не в пространсво имен модуля public int index;//не сериализуется public semantic_node_type semantic_node_type; - public bool virtual_slot; + public bool always_restore; public bool is_static; public NameRef(string name, int index, TreeConverter.access_level access_level, semantic_node_type semantic_node_type) @@ -441,6 +441,7 @@ namespace PascalABCCompiler.PCU fbw.Write(pcu_file.names[i].offset); fbw.Write((byte)pcu_file.names[i].symbol_kind); fbw.Write(pcu_file.names[i].special_scope); + fbw.Write(pcu_file.names[i].always_restore); } //ssyy @@ -451,6 +452,7 @@ namespace PascalABCCompiler.PCU fbw.Write(pcu_file.implementation_names[i].offset); fbw.Write((byte)pcu_file.implementation_names[i].symbol_kind); fbw.Write(pcu_file.implementation_names[i].special_scope); + fbw.Write(pcu_file.implementation_names[i].always_restore); } //\ssyy @@ -812,6 +814,17 @@ namespace PascalABCCompiler.PCU return ctn.name; } //ssyy + + private bool HasPCUAlwaysRestoreAttribute(definition_node dn) + { + foreach (var attr in dn.attributes) + { + if (attr.attribute_type.full_name == "PABCSystem.PCUAlwaysRestoreAttribute") + return true; + } + return false; + } + private void FillNames(NameRef[] name_array, Dictionary pools) { int j = 0, i = 0; @@ -838,12 +851,16 @@ namespace PascalABCCompiler.PCU else name_array[i].symbol_kind = symbol_kind.sk_overload_procedure; } + if (HasPCUAlwaysRestoreAttribute(cur_cnn.functions[i - j])) + name_array[i].always_restore = true; pools[cur_cnn.functions[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.non_template_types.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.non_template_types[i - j].name, i); + if (HasPCUAlwaysRestoreAttribute(cur_cnn.non_template_types[i - j])) + name_array[i].always_restore = true; pools[cur_cnn.non_template_types[i - j]] = name_array[i]; } j = i; @@ -864,6 +881,8 @@ namespace PascalABCCompiler.PCU for (i = j; i < cur_cnn.variables.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.variables[i - j].name, i); + if (HasPCUAlwaysRestoreAttribute(cur_cnn.variables[i - j])) + name_array[i].always_restore = true; pools[cur_cnn.variables[i - j]] = name_array[i]; } j = i; @@ -2707,6 +2726,8 @@ namespace PascalABCCompiler.PCU names[i] = new NameRef(type.fields[i - j].name, i, convert_field_access_level(type.fields[i - j].field_access_level), type.fields[i - j].semantic_node_type); name_pool[type.fields[i - j]] = names[i]; names[i].is_static = type.fields[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_static; + if (HasPCUAlwaysRestoreAttribute(type.fields[i - j])) + names[i].always_restore = true; size += names[i].Size; } j = i; @@ -2715,6 +2736,8 @@ namespace PascalABCCompiler.PCU names[i] = new NameRef(type.properties[i - j].name, i, convert_field_access_level(type.properties[i - j].field_access_level), type.properties[i - j].semantic_node_type); name_pool[type.properties[i - j]] = names[i]; names[i].is_static = type.properties[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_static; + if (HasPCUAlwaysRestoreAttribute(type.properties[i - j])) + names[i].always_restore = true; size += names[i].Size; } j = i; @@ -2724,8 +2747,10 @@ namespace PascalABCCompiler.PCU name_pool[type.methods[i - j]] = names[i]; if (type.methods[i - j].is_overload) names[i].symbol_kind = symbol_kind.sk_overload_function; - names[i].virtual_slot = type.methods[i - j].newslot_awaited || type.methods[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_virtual || type.methods[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract || type.methods[i - j].is_constructor; + names[i].always_restore = type.methods[i - j].newslot_awaited || type.methods[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_virtual || type.methods[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_virtual_abstract || type.methods[i - j].is_constructor; names[i].is_static = type.methods[i - j].polymorphic_state == SemanticTree.polymorphic_state.ps_static && !type.methods[i - j].is_constructor; + if (!names[i].always_restore && HasPCUAlwaysRestoreAttribute(type.methods[i - j])) + names[i].always_restore = true; size += names[i].Size; } j = i; @@ -2907,7 +2932,7 @@ namespace PascalABCCompiler.PCU bw.Write((byte)names[i].access_level); bw.Write((byte)names[i].symbol_kind); bw.Write((byte)names[i].semantic_node_type); - bw.Write(names[i].virtual_slot); + bw.Write(names[i].always_restore); bw.Write(names[i].is_static); } bw.BaseStream.Seek(tmp, SeekOrigin.Begin); diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index 293d29100..ef7d0be43 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -2833,6 +2833,12 @@ type PCUNotRestoreAttribute = class(System.Attribute) public constructor := exit; end; + +type + [AttributeUsage(AttributeTargets.Class or AttributeTargets.Method or AttributeTargets.Property or AttributeTargets.Interface or AttributeTargets.Field or AttributeTargets.Struct)] + PCUAlwaysRestoreAttribute = class(System.Attribute) + public constructor := exit; + end; ///-- function InternalRange(l,r: integer): IntRange; diff --git a/TestSuite/units/u_alwaysrestore.pas b/TestSuite/units/u_alwaysrestore.pas new file mode 100644 index 000000000..2e55e3307 --- /dev/null +++ b/TestSuite/units/u_alwaysrestore.pas @@ -0,0 +1,19 @@ +unit u_alwaysrestore; +interface + +[PCUAlwaysRestore] +function myfunc: integer; + +type +[PCUAlwaysRestore] +MyClass = class + +end; + +implementation + +function myfunc: integer; +begin + +end; +end. \ No newline at end of file diff --git a/TestSuite/usesunits/use_alwaysrestore.pas b/TestSuite/usesunits/use_alwaysrestore.pas new file mode 100644 index 000000000..0b219619c --- /dev/null +++ b/TestSuite/usesunits/use_alwaysrestore.pas @@ -0,0 +1,5 @@ +uses u_alwaysrestore; +begin + assert(System.Type.GetType('u_alwaysrestore.MyClass') <> nil); + assert(System.Type.GetType('u_alwaysrestore.u_alwaysrestore').GetMethod('myfunc') <> nil); +end. \ No newline at end of file diff --git a/TreeConverter/SymbolTable/symbol_information.cs b/TreeConverter/SymbolTable/symbol_information.cs index a6f3d03b7..433954e50 100644 --- a/TreeConverter/SymbolTable/symbol_information.cs +++ b/TreeConverter/SymbolTable/symbol_information.cs @@ -77,7 +77,7 @@ namespace PascalABCCompiler.TreeConverter { private semantic_node_type _semantic_node_type; - private bool _virtual_slot; + private bool _always_restore; private bool _is_static; @@ -93,15 +93,15 @@ namespace PascalABCCompiler.TreeConverter } } - public bool virtual_slot + public bool always_restore { get { - return _virtual_slot; + return _always_restore; } set { - _virtual_slot = value; + _always_restore = value; } } diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index 293d29100..ef7d0be43 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -2833,6 +2833,12 @@ type PCUNotRestoreAttribute = class(System.Attribute) public constructor := exit; end; + +type + [AttributeUsage(AttributeTargets.Class or AttributeTargets.Method or AttributeTargets.Property or AttributeTargets.Interface or AttributeTargets.Field or AttributeTargets.Struct)] + PCUAlwaysRestoreAttribute = class(System.Attribute) + public constructor := exit; + end; ///-- function InternalRange(l,r: integer): IntRange;