From 5a634b4e2a3ff950a326a7f56e737ebfdd208ea7 Mon Sep 17 00:00:00 2001 From: fm-117 Date: Mon, 18 Aug 2025 17:32:42 +0200 Subject: [PATCH 1/3] WI #2306 Protect against NullReferenceException when reading NameLiteral property --- .../CodeElements/Expressions/StorageArea.cs | 12 ++--- TypeCobol/Compiler/CodeModel/SymbolTable.cs | 4 +- .../Diagnostics/CodeElementCheckers.cs | 10 +++- .../Compiler/Diagnostics/TypeCobolChecker.cs | 3 +- .../CobolExpressionsBuilder.cs | 54 +++++++++++++------ .../CodeElementBuilder/CobolWordsBuilder.cs | 47 +++++++++++++--- TypeCobol/Compiler/Parser/DiagnosticUtils.cs | 26 ++++----- 7 files changed, 107 insertions(+), 49 deletions(-) diff --git a/TypeCobol/Compiler/CodeElements/Expressions/StorageArea.cs b/TypeCobol/Compiler/CodeElements/Expressions/StorageArea.cs index bee1e01cf..18bff64e2 100644 --- a/TypeCobol/Compiler/CodeElements/Expressions/StorageArea.cs +++ b/TypeCobol/Compiler/CodeElements/Expressions/StorageArea.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using JetBrains.Annotations; +using JetBrains.Annotations; using TypeCobol.Compiler.Nodes; using TypeCobol.Compiler.Scanner; @@ -536,7 +532,7 @@ public IntrinsicFunctionCall([CanBeNull] ExternalName intrinsicFunctionName, Cal [CanBeNull] public ExternalName IntrinsicFunctionName { get; private set; } public override string FunctionName { get { return IntrinsicFunctionName?.Name; } } - public override Token FunctionNameToken { get { return IntrinsicFunctionName?.NameLiteral.Token; } } + public override Token FunctionNameToken { get { return IntrinsicFunctionName?.NameLiteral?.Token; } } public override bool NeedDeclaration { @@ -567,7 +563,7 @@ public UserDefinedFunctionCall([CanBeNull] SymbolReference functionName, CallSit [CanBeNull] public SymbolReference UserDefinedFunctionName { get; private set; } public override string FunctionName { get { return UserDefinedFunctionName?.Name; } } - public override Token FunctionNameToken { get { return UserDefinedFunctionName?.NameLiteral.Token; } } + public override Token FunctionNameToken { get { return UserDefinedFunctionName?.NameLiteral?.Token; } } public override string Namespace { get { return (UserDefinedFunctionName as QualifiedSymbolReference) == null ? null : ((QualifiedSymbolReference)UserDefinedFunctionName).Tail.Name; } } @@ -592,7 +588,7 @@ public ProcedureCall(SymbolReference name, List inputs, List< public SymbolReference ProcedureName { get; private set; } public override string FunctionName { get { return ProcedureName.Name; } } - public override Token FunctionNameToken { get { return ProcedureName.NameLiteral.Token; } } + public override Token FunctionNameToken { get { return ProcedureName.NameLiteral?.Token; } } public List InputParameters { get; private set; } public List InoutParameters { get; private set; } diff --git a/TypeCobol/Compiler/CodeModel/SymbolTable.cs b/TypeCobol/Compiler/CodeModel/SymbolTable.cs index 9b1fced00..3a1d41911 100644 --- a/TypeCobol/Compiler/CodeModel/SymbolTable.cs +++ b/TypeCobol/Compiler/CodeModel/SymbolTable.cs @@ -819,7 +819,7 @@ public IList GetParagraph(SymbolReference symbolRef, Section sectionN { //If paragraph is qualified we get a paragraph and a section name var qualifiedSymbolReference = (QualifiedSymbolReference) symbolRef; - paragraphName = qualifiedSymbolReference.NameLiteral.Value; + paragraphName = qualifiedSymbolReference.Head.Name; parentSectionName = qualifiedSymbolReference.Tail.Name; } else @@ -830,7 +830,7 @@ public IList GetParagraph(SymbolReference symbolRef, Section sectionN } //Retrieve all paragraphs with matching name, then apply additional filters - if (Paragraphs.TryGetValue(paragraphName, out var candidates)) + if (paragraphName != null && Paragraphs.TryGetValue(paragraphName, out var candidates)) { if (parentSectionName != null) { diff --git a/TypeCobol/Compiler/Diagnostics/CodeElementCheckers.cs b/TypeCobol/Compiler/Diagnostics/CodeElementCheckers.cs index ea03181df..b3861a478 100644 --- a/TypeCobol/Compiler/Diagnostics/CodeElementCheckers.cs +++ b/TypeCobol/Compiler/Diagnostics/CodeElementCheckers.cs @@ -256,7 +256,7 @@ private static void CheckCallUsings(CallStatement statement) { foreach (var inputParameter in statement.InputParameters) { - var errorPosition = inputParameter.StorageAreaOrValue?.MainSymbolReference?.NameLiteral.Token; + var errorPosition = inputParameter.StorageAreaOrValue?.MainSymbolReference?.NameLiteral?.Token; // TODO#249 these checks should be done during semantic phase, after symbol type resolution // TODO#249 if input is a file name AND input.SendingMode.Value == SendingMode.ByContent OR ByValue @@ -736,10 +736,16 @@ public static void OnCodeElement(RepositoryParagraph paragraph, CodeElementsPars { foreach (var intrinsicFunction in intrinsicFunctions) { - Token token = intrinsicFunction.NameLiteral.Token; var intrinsicFunctionName = intrinsicFunction.Name; if (!CobolIntrinsicFunctions.IsAllowedInRepositoryParagraph(intrinsicFunctionName)) { + /* + * NameLiteral cannot be null here, otherwise intrinsicFuntionName would also be null + * and IsAllowedInRepositoryParagraph would then have returned true. + */ + System.Diagnostics.Debug.Assert(intrinsicFunction.NameLiteral != null); + + Token token = intrinsicFunction.NameLiteral.Token; DiagnosticUtils.AddError(paragraph, $"\"{intrinsicFunctionName}\" was specified in the \"FUNCTION\" phrase of the \"REPOSITORY\" paragraph, but the keyword \"FUNCTION\" is always required for this function.", token); } } diff --git a/TypeCobol/Compiler/Diagnostics/TypeCobolChecker.cs b/TypeCobol/Compiler/Diagnostics/TypeCobolChecker.cs index 4d4199d7f..3408b831a 100644 --- a/TypeCobol/Compiler/Diagnostics/TypeCobolChecker.cs +++ b/TypeCobol/Compiler/Diagnostics/TypeCobolChecker.cs @@ -618,10 +618,9 @@ public static void OnNode(FunctionDeclaration functionDeclaration) var functions = functionDeclaration.SymbolTable.GetFunction(headerNameURI, functionDeclaration.Profile); if (functions.Count > 1) { - Token nameToken = header.FunctionName.NameLiteral.Token; DiagnosticUtils.AddError(functionDeclaration, "A function \"" + headerNameURI.Head + "\" with the same profile already exists in namespace \"" + - headerNameURI.Tail + "\".", nameToken, null, MessageCode.SemanticTCErrorInParser); + headerNameURI.Tail + "\".", header.FunctionName, MessageCode.SemanticTCErrorInParser); } } diff --git a/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolExpressionsBuilder.cs b/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolExpressionsBuilder.cs index 9bf4cca90..7f2b17261 100644 --- a/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolExpressionsBuilder.cs +++ b/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolExpressionsBuilder.cs @@ -2,7 +2,6 @@ using TypeCobol.Compiler.AntlrUtils; using TypeCobol.Compiler.CodeElements; using TypeCobol.Compiler.Parser.Generated; -using System.Collections.Generic; using TypeCobol.Compiler.Diagnostics; using TypeCobol.Compiler.Scanner; @@ -240,13 +239,21 @@ internal StorageArea CreateLinageCounterSpecialRegister(CodeElementsParser.Linag var specialRegister = new FilePropertySpecialRegister( ParseTreeUtils.GetFirstToken(context.LINAGE_COUNTER()), CobolWordsBuilder.CreateFileNameReference(context.fileNameReference())); - if(specialRegister.DataDescriptionEntry != null) { - var dataDescription = specialRegister.DataDescriptionEntry; - CobolWordsBuilder.symbolInformationForTokens[specialRegister.DataDescriptionEntry.DataName.NameLiteral.Token] = specialRegister.DataDescriptionEntry.DataName; + + var dataName = specialRegister.DataDescriptionEntry?.DataName; + var dataNameToken = dataName?.NameLiteral?.Token; + if (dataNameToken != null) + { + CobolWordsBuilder.symbolInformationForTokens[dataNameToken] = dataName; } - if (specialRegister.SymbolReference != null) { - CobolWordsBuilder.symbolInformationForTokens[specialRegister.SymbolReference.NameLiteral.Token] = specialRegister.SymbolReference; + + var specialRegisterReference = specialRegister.SymbolReference; + var specialRegisterReferenceToken = specialRegisterReference?.NameLiteral?.Token; + if (specialRegisterReferenceToken != null) + { + CobolWordsBuilder.symbolInformationForTokens[specialRegisterReferenceToken] = specialRegisterReference; } + return specialRegister; } @@ -255,14 +262,19 @@ internal StorageArea CreateAddressOfSpecialRegister(CodeElementsParser.AddressOf var specialRegister = new StorageAreaPropertySpecialRegister( ParseTreeUtils.GetFirstToken(context.ADDRESS()), CreateStorageAreaReference(context.storageAreaReference())); - if (specialRegister.DataDescriptionEntry != null) + + var specialRegisterName = specialRegister.DataDescriptionEntry?.DataName; + var specialRegisterNameToken = specialRegisterName?.NameLiteral?.Token; + if (specialRegisterNameToken != null) { - var dataDescription = specialRegister.DataDescriptionEntry; - CobolWordsBuilder.symbolInformationForTokens[specialRegister.DataDescriptionEntry.DataName.NameLiteral.Token] = specialRegister.DataDescriptionEntry.DataName; + CobolWordsBuilder.symbolInformationForTokens[specialRegisterNameToken] = specialRegisterName; } - if (specialRegister.SymbolReference != null) + + var specialRegisterReference = specialRegister.SymbolReference; + var specialRegisterReferenceToken = specialRegisterReference?.NameLiteral?.Token; + if (specialRegisterReferenceToken != null) { - CobolWordsBuilder.symbolInformationForTokens[specialRegister.SymbolReference.NameLiteral.Token] = specialRegister.SymbolReference; + CobolWordsBuilder.symbolInformationForTokens[specialRegisterReferenceToken] = specialRegisterReference; } return specialRegister; } @@ -272,15 +284,21 @@ internal StorageArea CreateLengthOfSpecialRegister(CodeElementsParser.LengthOfSp var specialRegister = new StorageAreaPropertySpecialRegister( ParseTreeUtils.GetFirstToken(context.LENGTH()), CreateStorageAreaReference(context.storageAreaReference())); - if (specialRegister.DataDescriptionEntry != null) + + var specialRegisterDataName = specialRegister.DataDescriptionEntry?.DataName; + var specialRegisterDataNameToken = specialRegisterDataName?.NameLiteral?.Token; + if (specialRegisterDataNameToken != null) { - var dataDescription = specialRegister.DataDescriptionEntry; - CobolWordsBuilder.symbolInformationForTokens[specialRegister.DataDescriptionEntry.DataName.NameLiteral.Token] = specialRegister.DataDescriptionEntry.DataName; + CobolWordsBuilder.symbolInformationForTokens[specialRegisterDataNameToken] = specialRegisterDataName; } - if (specialRegister.SymbolReference != null) + + var specialRegisterReference = specialRegister.SymbolReference; + var specialRegisterReferenceToken = specialRegisterReference?.NameLiteral?.Token; + if (specialRegisterReferenceToken != null) { - CobolWordsBuilder.symbolInformationForTokens[specialRegister.SymbolReference.NameLiteral.Token] = specialRegister.SymbolReference; + CobolWordsBuilder.symbolInformationForTokens[specialRegisterReferenceToken] = specialRegisterReference; } + return specialRegister; } @@ -317,8 +335,12 @@ internal StorageArea CreateFunctionIdentifier(CodeElementsParser.FunctionIdentif if (functionCall.FunctionName != null && functionCall.FunctionNameToken != null) { var functionCallResult = new FunctionCallResult(functionCall); + System.Diagnostics.Debug.Assert(functionCallResult.DataDescriptionEntry.DataName != null); + System.Diagnostics.Debug.Assert(functionCallResult.DataDescriptionEntry.DataName.NameLiteral.Token != null); CobolWordsBuilder.symbolInformationForTokens[functionCallResult.DataDescriptionEntry.DataName.NameLiteral.Token] = functionCallResult.DataDescriptionEntry.DataName; + System.Diagnostics.Debug.Assert(functionCallResult.SymbolReference != null); + System.Diagnostics.Debug.Assert(functionCallResult.SymbolReference.NameLiteral.Token != null); CobolWordsBuilder.symbolInformationForTokens[functionCallResult.SymbolReference.NameLiteral.Token] = functionCallResult.SymbolReference; return functionCallResult; diff --git a/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolWordsBuilder.cs b/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolWordsBuilder.cs index dd986ad6e..91911277f 100644 --- a/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolWordsBuilder.cs +++ b/TypeCobol/Compiler/Parser/CodeElementBuilder/CobolWordsBuilder.cs @@ -67,6 +67,8 @@ internal CharacterValue CreateFigurativeConstant(CodeElementsParser.FigurativeCo if (context.symbolicCharacterReference() != null) { var symbolicCharacterReference = CreateSymbolicCharacterReference(context.symbolicCharacterReference()); + System.Diagnostics.Debug.Assert(symbolicCharacterReference.NameLiteral != null); + System.Diagnostics.Debug.Assert(symbolicCharacterReference.NameLiteral.Token != null); return new CharacterValue(symbolicCharacterReference); } @@ -172,6 +174,8 @@ private RepeatedCharacterValue CreateRepeatedCharacterValue([CanBeNull] Token al if (context.symbolicCharacterReference() != null) { var symbolicCharacterReference = CreateSymbolicCharacterReference(context.symbolicCharacterReference()); + System.Diagnostics.Debug.Assert(symbolicCharacterReference.NameLiteral != null); + System.Diagnostics.Debug.Assert(symbolicCharacterReference.NameLiteral.Token != null); return new RepeatedCharacterValue(allToken, symbolicCharacterReference); } @@ -803,7 +807,13 @@ internal SymbolReference CreateIndexNameReference(CodeElementsParser.QualifiedIn var reference = CreateQualifiedSymbolReference(new SymbolReference(headLiteral, SymbolType.IndexName), new SymbolReference(CreateAlphanumericValue(tail[0]), SymbolType.IndexName), false); for (int c = 1; c < tail.Length; c++) reference = CreateQualifiedSymbolReference(reference, new SymbolReference(CreateAlphanumericValue(tail[c]), SymbolType.IndexName), false); - symbolInformationForTokens[reference.NameLiteral.Token] = reference; + + var token = reference.NameLiteral?.Token; + if (token != null) + { + symbolInformationForTokens[token] = reference; + } + return reference; } @@ -871,7 +881,12 @@ internal SymbolReference CreateQualifiedParagraphNameReference(CodeElementsParse private SymbolReference CreateQualifiedParagraphNameReference(CodeElementsParser.ParagraphNameReferenceContext head, CodeElementsParser.SectionNameReferenceContext tail, bool isCOBOL = true) { var reference = CreateQualifiedSymbolReference(CreateParagraphNameReference(head), CreateSectionNameReference(tail), isCOBOL); - symbolInformationForTokens[reference.NameLiteral.Token] = reference; + var token = reference.NameLiteral?.Token; + if (token != null) + { + symbolInformationForTokens[token] = reference; + } + return reference; } @@ -912,9 +927,11 @@ private SymbolReference CreateQualifiedDataName(CodeElementsParser.DataNameRefer } qname = CreateQualifiedSymbolReference(qname, current, isCOBOL); } - if (qname != null) + + var token = qname?.NameLiteral?.Token; + if (token != null) { - symbolInformationForTokens[qname.NameLiteral.Token] = qname; + symbolInformationForTokens[token] = qname; return qname; } @@ -954,7 +971,13 @@ private SymbolReference CreateQualifiedConditionName(CodeElementsParser.Conditio qname = CreateQualifiedSymbolReference(qname, part, isCOBOL); } } - symbolInformationForTokens[qname.NameLiteral.Token] = qname; + + var token = qname.NameLiteral?.Token; + if (token != null) + { + symbolInformationForTokens[token] = qname; + } + return qname; } @@ -1015,7 +1038,12 @@ private SymbolReference CreateQualifiedDataNameOrQualifiedConditionNameTCFunctio { var reference = CreateQualifiedSymbolReference(CreateDataNameReferenceOrConditionNameReferenceOrConditionForUPSISwitchNameReferenceOrTCFunctionProcedure(head), CreateDataNameReferenceOrFileNameReferenceOrMnemonicForUPSISwitchNameReference(tail[0]), isCOBOL); for (int c = 1; c < tail.Length; c++) reference = CreateQualifiedSymbolReference(reference, CreateDataNameReferenceOrFileNameReferenceOrMnemonicForUPSISwitchNameReference(tail[c]), isCOBOL); - symbolInformationForTokens[reference.NameLiteral.Token] = reference; + var token = reference.NameLiteral?.Token; + if (token != null) + { + symbolInformationForTokens[token] = reference; + } + return reference; } @@ -1134,7 +1162,12 @@ internal ExternalName CreateQualifiedTextName(CodeElementsParser.QualifiedTextNa { ExternalName libraryName = CreateLibraryName(context.libraryName()); var qualifiedTextName = new QualifiedTextName(textName, libraryName); - symbolInformationForTokens[qualifiedTextName.NameLiteral.Token] = qualifiedTextName; + var textNameToken = qualifiedTextName.NameLiteral?.Token; + if (textNameToken != null) + { + symbolInformationForTokens[textNameToken] = qualifiedTextName; + } + return qualifiedTextName; } } diff --git a/TypeCobol/Compiler/Parser/DiagnosticUtils.cs b/TypeCobol/Compiler/Parser/DiagnosticUtils.cs index 8d7b029a4..69e8955b7 100644 --- a/TypeCobol/Compiler/Parser/DiagnosticUtils.cs +++ b/TypeCobol/Compiler/Parser/DiagnosticUtils.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using TypeCobol.Compiler.AntlrUtils; using TypeCobol.Compiler.CodeElements; using TypeCobol.Compiler.Diagnostics; @@ -58,20 +55,25 @@ internal static void AddError(Node node, string message, Scanner.Token token, st node.AddDiagnostic(diagnostic); } - internal static void AddError(Node node, string message, SymbolReference symbol, MessageCode code = MessageCode.SyntaxErrorInParser) + internal static void AddError(Node node, string message, SymbolInformation symbol, MessageCode code = MessageCode.SyntaxErrorInParser) { - var diagnostic = new ParserDiagnostic(message, symbol.NameLiteral.Token, null, code); - node.AddDiagnostic(diagnostic); + var token = symbol?.NameLiteral?.Token; + if (token != null) + { + AddError(node, message, token, null, code); + } + else + { + AddError(node, message, code); + } } internal static void AddError(Node node, string message, DataDefinitionEntry data, MessageCode code = MessageCode.SyntaxErrorInParser) { - ParserDiagnostic diagnostic; - - if (data?.DataName != null) + var dataName = data?.DataName; + if (dataName != null) { - diagnostic = new ParserDiagnostic(message, data?.DataName != null ? data.DataName.NameLiteral.Token : data.ConsumedTokens[0], null, code); - node.AddDiagnostic(diagnostic); + AddError(node, message, dataName, code); } else { From 30cfcf1788006b25f3318043771d499623984ab2 Mon Sep 17 00:00:00 2001 From: fm-117 Date: Mon, 18 Aug 2025 17:54:28 +0200 Subject: [PATCH 2/3] WI #2306 Add unit test --- .../Cobol85/RedefinesWithReplace.PGM.txt | 19 +++++++++++++++++++ .../Cobol85/RedefinesWithReplace.rdz.cbl | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt create mode 100644 TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.rdz.cbl diff --git a/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt new file mode 100644 index 000000000..aab0140cc --- /dev/null +++ b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt @@ -0,0 +1,19 @@ +--- Diagnostics --- +Line 10[34,40] <27, Error, Syntax> - Syntax error : mismatched input ':zoneA:' expecting user defined word RuleStack=codeElement>dataDescriptionEntry>redefinesClause>dataNameReference, OffendingSymbol=[34,40::zoneA:] +Line 10[8,41] <30, Error, Semantics> - Semantic error: Illegal REDEFINES: Symbol '' is not referenced + +--- Program --- +PROGRAM: TCOBCOMP common:False initial:False recursive:False + author: ? written: ? compiled: ? installation: ? security: ? +--- Intrinsic:Namespace:Program:Global:Local +-- DATA -------- + zone1:Alphanumeric + zone1-redef:Alphanumeric + z-label:Alphanumeric + z-content:Alphanumeric +--- Intrinsic +-- TYPES ------- + BOOL:BOOL + DATE:DATE + CURRENCY:CURRENCY + STRING:STRING diff --git a/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.rdz.cbl b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.rdz.cbl new file mode 100644 index 000000000..a67df79e2 --- /dev/null +++ b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.rdz.cbl @@ -0,0 +1,16 @@ + IDENTIFICATION DIVISION. + PROGRAM-ID. TCOBCOMP. + DATA DIVISION. + WORKING-STORAGE SECTION. + REPLACE ==:zone:== BY ==zone1==. + 01 :zone: PIC X(120). + * Undefined REDEFINES target, we get 2 diagnostics: + * - one for the invalid parsing of the Redefines entry + * - one for the invalid semantics of the REDEFINES + 01 :zone:-redef REDEFINES :zoneA:. + 05 z-label PIC X(20). + 05 z-content PIC X(100). + PROCEDURE DIVISION. + GOBACK + . + END PROGRAM TCOBCOMP. \ No newline at end of file From e563a4b0fe96df71a35409a53a4b620f20b5741a Mon Sep 17 00:00:00 2001 From: fm-117 Date: Mon, 18 Aug 2025 18:29:37 +0200 Subject: [PATCH 3/3] WI #2306 Improve error message --- .../Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt | 2 +- TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt index aab0140cc..7cdc0c610 100644 --- a/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt +++ b/TypeCobol.Test/Parser/Programs/Cobol85/RedefinesWithReplace.PGM.txt @@ -1,6 +1,6 @@ --- Diagnostics --- Line 10[34,40] <27, Error, Syntax> - Syntax error : mismatched input ':zoneA:' expecting user defined word RuleStack=codeElement>dataDescriptionEntry>redefinesClause>dataNameReference, OffendingSymbol=[34,40::zoneA:] -Line 10[8,41] <30, Error, Semantics> - Semantic error: Illegal REDEFINES: Symbol '' is not referenced +Line 10[8,41] <30, Error, Semantics> - Semantic error: Illegal REDEFINES: Target cannot be identified --- Program --- PROGRAM: TCOBCOMP common:False initial:False recursive:False diff --git a/TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs b/TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs index d242d895d..fa7638d1e 100644 --- a/TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs +++ b/TypeCobol/Compiler/Diagnostics/Cobol2002Checker.cs @@ -1,12 +1,9 @@ -using System.Linq; -using System.Collections.Generic; -using TypeCobol.Compiler.AntlrUtils; +using TypeCobol.Compiler.AntlrUtils; using TypeCobol.Compiler.CodeElements; using TypeCobol.Compiler.CodeElements.Expressions; using TypeCobol.Compiler.Parser; using TypeCobol.Compiler.Parser.Generated; using TypeCobol.Compiler.Nodes; -using TypeCobol.Compiler.Scanner; namespace TypeCobol.Compiler.Diagnostics { @@ -147,7 +144,9 @@ public static void OnNode(DataRedefines redefinesNode) if (redefinedVariable == null) { - string message = "Illegal REDEFINES: Symbol \'" + redefinesSymbolReference + "\' is not referenced"; + var message = redefinesSymbolReference.Name != null + ? "Illegal REDEFINES: Symbol \'" + redefinesSymbolReference + "\' is not referenced" + : "Illegal REDEFINES: Target cannot be identified"; DiagnosticUtils.AddError(redefinesNode, message, redefinesSymbolReference, code: MessageCode.SemanticTCErrorInParser); return; }