Skip to content

Commit

Permalink
Fix #2594 transitive REDEFINES problem (wrong physical length) (#2595)
Browse files Browse the repository at this point in the history
* Fix #2594 transitive REDEFINES problem (wrong physical length)

* Fix #2594 Code review
  • Loading branch information
efr15 committed Nov 20, 2023
1 parent 27dcb86 commit 58a376d
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Diagnostics
------------
None

--------- FIELD LEVEL|NAME ---------- START END LENGTH
1 group0 1 21 21
5 group1 1 10 10
10 var1 1 10 10
5 group2 1 20 20
10 var2 1 20 20
5 group3 1 3 3
10 var3 1 3 3
5 next-group 21 21 1
10 next-var 21 21 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. PGMREDFT.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 group0.
05 group1.
10 var1 PIC X(10).
05 group2 REDEFINES group1.
10 var2 PIC X(20).
05 group3 REDEFINES group2.
10 var3 PIC X(3).
05 next-group.
10 next-var PIC X.
PROCEDURE DIVISION.
GOBACK
.
END PROGRAM PGMREDFT.
39 changes: 25 additions & 14 deletions TypeCobol/Compiler/CodeModel/SymbolTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,28 +344,39 @@ void SearchChildren(IReadOnlyList<Node> children)
}
}

public DataDefinition GetRedefinedVariable(DataRedefines redefinesNode, SymbolReference symbolReference)
public DataDefinition GetRedefinedVariable(DataRedefines redefinesNode)
{
var redefinesDataName = redefinesNode.CodeElement.RedefinesDataName.Name;
var childrens = redefinesNode.Parent.Children;
int index = redefinesNode.Parent.IndexOf(redefinesNode);

while (index >= 0)
{
CommonDataDescriptionAndDataRedefines child = childrens[index].CodeElement as CommonDataDescriptionAndDataRedefines;

if (child != null && (child is DataDescriptionEntry || child is DataRedefinesEntry))
var child = childrens[index];
if (child.Name != null)
{
if (child.DataName != null &&
string.Equals(child.DataName.Name, symbolReference.Name,
StringComparison.OrdinalIgnoreCase))
return childrens[index] as DataDefinition;
else if (child.DataName != null && child is DataDescriptionEntry &&
!string.Equals(child.DataName.Name, symbolReference.Name,
StringComparison.OrdinalIgnoreCase))
return null;
var type = child.CodeElement?.Type;
if (type == CodeElementType.DataDescriptionEntry || type == CodeElementType.DataRedefinesEntry)
{
if (string.Equals(child.Name, redefinesDataName, StringComparison.OrdinalIgnoreCase))
{
if (type == CodeElementType.DataRedefinesEntry)
{
// Transitive REDEFINES => continue until root one is reached
return ((DataRedefines)child).RedefinedVariable;
}

return (DataDefinition)child;
}

// Name differs
if (type == CodeElementType.DataDescriptionEntry)
{
// No more REDEFINES => not found
return null;
}
}
}
else
return null;

index--;
}
Expand Down
2 changes: 1 addition & 1 deletion TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static void OnNode(DataRedefines redefinesNode)
}

var redefinesSymbolReference = redefinesNode.CodeElement.RedefinesDataName;
var redefinedVariable = redefinesNode.SymbolTable.GetRedefinedVariable(redefinesNode, redefinesSymbolReference);
var redefinedVariable = redefinesNode.RedefinedVariable;

if (redefinedVariable == null)
{
Expand Down
22 changes: 14 additions & 8 deletions TypeCobol/Compiler/Nodes/Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ public TypeDefinition TypeDefinition

private IList<DataRedefines> _dataRedefines;

public IEnumerable<DataRedefines> DataRedefinitions => _dataRedefines;

public void AddDataRedefinition(DataRedefines dataRedefines)
{
if (_dataRedefines == null)
Expand Down Expand Up @@ -459,12 +461,9 @@ public long SlackBytes
{
DataRedefines redefines = parent.Children[index] as DataRedefines;
//Get the original redefined node
while (redefines != null)
if (redefines != null)
{
SymbolReference redefined = redefines.CodeElement.RedefinesDataName;
redefinedDataDefinition = redefines.SymbolTable.GetRedefinedVariable(redefines, redefined);

redefines = redefinedDataDefinition as DataRedefines;
redefinedDataDefinition = redefines.RedefinedVariable;
}

//Sum up all physical lengths except these from DataRedefines and the node that is redefined by the current node (if he is a DataRedefines)
Expand Down Expand Up @@ -537,8 +536,7 @@ public virtual long StartPosition
if (this is DataRedefines node)
{
//Get the start position from the node it redefines.
SymbolReference redefined = node.CodeElement.RedefinesDataName;
var result = SymbolTable.GetRedefinedVariable(node, redefined);
var result = node.RedefinedVariable;

_startPosition = result.StartPosition + SlackBytes;
return _startPosition.Value;
Expand Down Expand Up @@ -764,11 +762,19 @@ public override bool VisitNode(IASTVisitor astVisitor)
}
}
public class DataRedefines: DataDefinition {
public DataRedefines([NotNull] DataRedefinesEntry entry) : base(entry) { }
public DataRedefines([NotNull] DataRedefinesEntry entry)
: base(entry)
{
_redefinedVariable = new Lazy<DataDefinition>(() => SymbolTable.GetRedefinedVariable(this));
}

[NotNull]
public new DataRedefinesEntry CodeElement => (DataRedefinesEntry) base.CodeElement;

private readonly Lazy<DataDefinition> _redefinedVariable;

public DataDefinition RedefinedVariable => _redefinedVariable.Value;

public override bool VisitNode(IASTVisitor astVisitor)
{
return base.VisitNode(astVisitor) && astVisitor.Visit(this);
Expand Down

0 comments on commit 58a376d

Please sign in to comment.