fcl-passrc: allow using unit twice with different alias

git-svn-id: trunk@43810 -
This commit is contained in:
Mattias Gaertner 2019-12-29 21:34:03 +00:00
parent 9a496c2470
commit a3a67b13d8
4 changed files with 63 additions and 45 deletions

View File

@ -5676,7 +5676,7 @@ end;
procedure TPasResolver.FinishUsesClause; procedure TPasResolver.FinishUsesClause;
var var
Section, CurSection: TPasSection; Section: TPasSection;
i, j: Integer; i, j: Integer;
PublicEl, UseModule: TPasElement; PublicEl, UseModule: TPasElement;
Scope: TPasSectionScope; Scope: TPasSectionScope;
@ -5723,25 +5723,6 @@ begin
+UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName); +UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
UsesScope:=TPasSectionScope(PublicEl.CustomData); UsesScope:=TPasSectionScope(PublicEl.CustomData);
// check if module was already used by a different name
j:=i;
CurSection:=Section;
repeat
dec(j);
if j<0 then
begin
if CurSection.ClassType<>TImplementationSection then
break;
CurSection:=CurSection.GetModule.InterfaceSection;
if CurSection=nil then break;
j:=length(CurSection.UsesClause)-1;
if j<0 then break;
end;
if CurSection.UsesClause[j].Module=UseModule then
RaiseMsg(20170503004022,nDuplicateIdentifier,sDuplicateIdentifier,
[UseModule.Name,GetElementSourcePosStr(CurSection.UsesClause[j])],UseUnit);
until false;
// add full uses name // add full uses name
AddIdentifier(Scope,UseUnit.Name,UseUnit,pikSimple); AddIdentifier(Scope,UseUnit.Name,UseUnit,pikSimple);

View File

@ -3792,16 +3792,6 @@ function TPasParser.AddUseUnit(ASection: TPasSection;
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]); ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
end; end;
procedure CheckDuplicateInUsesList(UnitRef: TPasElement; UsesClause: TPasUsesClause);
var
i: Integer;
begin
if UsesClause=nil then exit;
for i:=0 to length(UsesClause)-1 do
if UsesClause[i].Module=UnitRef then
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
end;
var var
UnitRef: TPasElement; UnitRef: TPasElement;
UsesUnit: TPasUsesUnit; UsesUnit: TPasUsesUnit;
@ -3820,22 +3810,18 @@ begin
ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]); ParseExc(nParserDuplicateIdentifier,SParserDuplicateIdentifier,[AUnitName]);
end; end;
// Note: The alias (AUnitName) must be unique within a module.
// Using an unit module twice with different alias is allowed.
CheckDuplicateInUsesList(ASection.UsesClause);
if ASection.ClassType=TImplementationSection then
CheckDuplicateInUsesList(CurModule.InterfaceSection.UsesClause);
UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr); UnitRef := Engine.FindModule(AUnitName,NameExpr,InFileExpr);
if Assigned(UnitRef) then if Assigned(UnitRef) then
begin UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF}
UnitRef.AddRef{$IFDEF CheckPasTreeRefCount}('TPasUsesUnit.Module'){$ENDIF};
CheckDuplicateInUsesList(UnitRef,ASection.UsesClause);
if ASection.ClassType=TImplementationSection then
CheckDuplicateInUsesList(UnitRef,CurModule.InterfaceSection.UsesClause);
end
else else
begin
CheckDuplicateInUsesList(ASection.UsesClause);
if ASection.ClassType=TImplementationSection then
CheckDuplicateInUsesList(CurModule.InterfaceSection.UsesClause);
UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef, UnitRef := TPasUnresolvedUnitRef(CreateElement(TPasUnresolvedUnitRef,
AUnitName, ASection, NamePos)); AUnitName, ASection, NamePos));
end;
UsesUnit:=TPasUsesUnit(CreateElement(TPasUsesUnit,AUnitName,ASection,NamePos)); UsesUnit:=TPasUsesUnit(CreateElement(TPasUsesUnit,AUnitName,ASection,NamePos));
Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef,UsesUnit); Result:=ASection.AddUnitToUsesList(AUnitName,NameExpr,InFileExpr,UnitRef,UsesUnit);

View File

@ -370,7 +370,7 @@ type
Procedure TestUnit_DottedUnit; Procedure TestUnit_DottedUnit;
Procedure TestUnit_DottedExpr; Procedure TestUnit_DottedExpr;
Procedure TestUnit_DuplicateDottedUsesFail; Procedure TestUnit_DuplicateDottedUsesFail;
Procedure TestUnit_DuplicateUsesDiffNameFail; Procedure TestUnit_DuplicateUsesDiffName;
Procedure TestUnit_Unit1DotUnit2Fail; Procedure TestUnit_Unit1DotUnit2Fail;
Procedure TestUnit_InFilename; Procedure TestUnit_InFilename;
Procedure TestUnit_InFilenameAliasDelphiFail; Procedure TestUnit_InFilenameAliasDelphiFail;
@ -5924,7 +5924,7 @@ begin
nParserDuplicateIdentifier); nParserDuplicateIdentifier);
end; end;
procedure TTestResolver.TestUnit_DuplicateUsesDiffNameFail; procedure TTestResolver.TestUnit_DuplicateUsesDiffName;
begin begin
MainFilename:='unitdots.main1.pas'; MainFilename:='unitdots.main1.pas';
AddModuleWithIntfImplSrc('unitdots.unit1.pp', AddModuleWithIntfImplSrc('unitdots.unit1.pp',
@ -5942,8 +5942,7 @@ begin
' if unit1.j1=0 then ;', ' if unit1.j1=0 then ;',
' if unitdots.unit1.j1=0 then ;', ' if unitdots.unit1.j1=0 then ;',
'']); '']);
CheckParserException('Duplicate identifier "unit1" at token ";" in file unitdots.main1.pas at line 2 column 27', ParseProgram;
nParserDuplicateIdentifier);
end; end;
procedure TTestResolver.TestUnit_Unit1DotUnit2Fail; procedure TTestResolver.TestUnit_Unit1DotUnit2Fail;

View File

@ -145,10 +145,15 @@ type
procedure TestUS_Program_FE_o; procedure TestUS_Program_FE_o;
procedure TestUS_IncludeSameDir; procedure TestUS_IncludeSameDir;
// uses 'in' modifier
procedure TestUS_UsesInFile; procedure TestUS_UsesInFile;
procedure TestUS_UsesInFile_Duplicate; procedure TestUS_UsesInFile_Duplicate;
procedure TestUS_UsesInFile_IndirectDuplicate; procedure TestUS_UsesInFile_IndirectDuplicate;
procedure TestUS_UsesInFile_WorkNotEqProgDir; procedure TestUS_UsesInFile_WorkNotEqProgDir;
procedure TestUS_UsesInFileTwice;
procedure TestUS_UseUnitTwiceFail;
procedure TestUS_UseUnitTwiceViaNameSpace;
end; end;
function LinesToStr(const Lines: array of string): string; function LinesToStr(const Lines: array of string): string;
@ -738,6 +743,7 @@ end;
procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate; procedure TTestCLI_UnitSearch.TestUS_UsesInFile_Duplicate;
begin begin
// check if using two different units with same name
AddUnit('system.pp',[''],['']); AddUnit('system.pp',[''],['']);
AddUnit('unit1.pas', AddUnit('unit1.pas',
['var a: longint;'], ['var a: longint;'],
@ -757,6 +763,7 @@ end;
procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate; procedure TTestCLI_UnitSearch.TestUS_UsesInFile_IndirectDuplicate;
begin begin
// check if using two different units with same name
AddUnit('system.pp',[''],['']); AddUnit('system.pp',[''],['']);
AddUnit('unit1.pas', AddUnit('unit1.pas',
['var a: longint;'], ['var a: longint;'],
@ -791,6 +798,51 @@ begin
Compile(['sub/test1.pas','-Jc']); Compile(['sub/test1.pas','-Jc']);
end; end;
procedure TTestCLI_UnitSearch.TestUS_UsesInFileTwice;
begin
AddUnit('system.pp',[''],['']);
AddUnit('unit1.pas',
['var a: longint;'],
['']);
AddFile('test1.pas',[
'uses foo in ''unit1.pas'', bar in ''unit1.pas'';',
'begin',
' bar.a:=foo.a;',
' a:=a;',
'end.']);
Compile(['test1.pas','-Jc']);
end;
procedure TTestCLI_UnitSearch.TestUS_UseUnitTwiceFail;
begin
AddUnit('system.pp',[''],['']);
AddUnit('sub.unit1.pas',
['var a: longint;'],
['']);
AddFile('test1.pas',[
'uses sub.Unit1, sub.unit1;',
'begin',
' a:=a;',
'end.']);
Compile(['test1.pas','-FNsub','-Jc'],ExitCodeSyntaxError);
AssertEquals('ErrorMsg','Duplicate identifier "sub.unit1"',ErrorMsg);
end;
procedure TTestCLI_UnitSearch.TestUS_UseUnitTwiceViaNameSpace;
begin
AddUnit('system.pp',[''],['']);
AddUnit('sub.unit1.pas',
['var a: longint;'],
['']);
AddFile('test1.pas',[
'uses unit1, sub.unit1;',
'begin',
' unit1.a:=sub.unit1.a;',
' a:=a;',
'end.']);
Compile(['test1.pas','-FNsub','-Jc']);
end;
Initialization Initialization
RegisterTests([TTestCLI_UnitSearch]); RegisterTests([TTestCLI_UnitSearch]);
end. end.