diff --git a/SyntaxTree/tree/TreeSubsidiary.cs b/SyntaxTree/tree/TreeSubsidiary.cs index 59f7d57f0..672683feb 100644 --- a/SyntaxTree/tree/TreeSubsidiary.cs +++ b/SyntaxTree/tree/TreeSubsidiary.cs @@ -380,7 +380,12 @@ namespace PascalABCCompiler.SyntaxTree (begin_position.line_num > sc1.begin_position.line_num || (begin_position.line_num == sc1.begin_position.line_num && begin_position.column_num > sc1.begin_position.column_num)) && (end_position.line_num < sc2.begin_position.line_num || (end_position.line_num == sc2.begin_position.line_num && end_position.column_num < sc2.begin_position.column_num)); } - } + public bool Less(SourceContext sc) + { + return begin_position.line_num < sc.begin_position.line_num || (begin_position.line_num == sc.begin_position.line_num && begin_position.column_num < sc.begin_position.column_num); + } + + } public class Utils { diff --git a/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs b/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs index a13d22287..2f29255bf 100644 --- a/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs +++ b/SyntaxVisitors/CheckingVisitors/UnnamedRecordsCheckErrorsVisitor.cs @@ -114,7 +114,11 @@ namespace SyntaxVisitors.CheckingVisitors // Имена, захваченные записью. Их мы будем искать затем во внешних контекстах // Сюда не включаются имена во вложенных безымянных записях // Сюда не включаются имена, являющиеся определениями (в данном случае это только определения полей) + + // Есть еще одна проблема - в имена, захваченные записью, не должны включаться имена, определенные в самой записи (!!!) - #2214 + public List idents = new List(); + public List defIdents = new List(); public class_definition StartUnnamedRecord; public static OneUnnamedRecordCaptureNamesVisitor New(class_definition cd) { @@ -135,7 +139,7 @@ namespace SyntaxVisitors.CheckingVisitors var id = q.vars.idents[0]; // это просто имя var type = q.vars_type; var initValue = q.inital_value; - // idents.Add(id); - вот как раз не надо добавлять определения - только использования!!! + defIdents.Add(id); // Определения надо добавлять в другой список. Потом вычитать его из определений в неглобальных контекстах ProcessNode(type); if (initValue != null) ProcessNode(initValue); @@ -247,6 +251,7 @@ namespace SyntaxVisitors.CheckingVisitors var lvi = localsvis.idents.Select(id => id.name).ToArray(); var cvi = cdvis.idents; + var cvdi = cdvis.defIdents; // Теперь проверим пересечение foreach (var id in cvi) @@ -254,8 +259,13 @@ namespace SyntaxVisitors.CheckingVisitors var s = id.name; foreach (var lname in lvi) { - if (string.Compare(s,lname,true)==0) + var ind = cvdi.FindIndex(idd => string.Compare(idd.name, lname, true) == 0); + bool b = ind != -1; + if (b) + b = cvdi[ind].source_context.Less(id.source_context); + if (string.Compare(s,lname,true)==0 && !b) { + // то надо еще проверить cvdi чтобы там как раз не было этих имен throw new SyntaxVisitorError("UNNAMED_RECORD_CANNOT_CATCH_NAMES_FROM_NONGLOBAL_CONTEXT", id); } } diff --git a/TestSuite/unn_rec_ex.pas b/TestSuite/unn_rec_ex.pas new file mode 100644 index 000000000..3be35a0fa --- /dev/null +++ b/TestSuite/unn_rec_ex.pas @@ -0,0 +1,12 @@ +var + A: record + j: integer; + jlocal0: record + j: integer; + i: real := j; + end; + end; + +begin + +end. \ No newline at end of file