diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index d689acc12ce..ab6178e08ed 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -4395,7 +4395,9 @@ if srsymtable.symtabletype=recordsymtable then (sp_generic_dummy in srsym.symoptions) and (current_scanner.token in [_LT,_LSHARPBRACKET]) then begin - result:=cspecializenode.create(nil,getaddr,srsym,unit_found) + if not is_member_read(srsym,srsymtable,result,hdef) then + result:=nil; + result:=cspecializenode.create(result,getaddr,srsym,unit_found) end { check if it's a method/class method } else if is_member_read(srsym,srsymtable,result,hdef) then diff --git a/tests/webtbs/tw41711.pp b/tests/webtbs/tw41711.pp new file mode 100644 index 00000000000..95ee0ef5d3b --- /dev/null +++ b/tests/webtbs/tw41711.pp @@ -0,0 +1,138 @@ +program tw41711; + +{$mode delphi} + +type + TTarget = class + procedure CheckPlain; + procedure CheckGeneric; + destructor Destroy; override; + end; + + TOuter = class + procedure Invoke; + end; + + TValue = record + Number: LongInt; + procedure SetPlain(AValue: LongInt); + procedure SetGeneric(AValue: LongInt); + end; + +var + Expected: TTarget; + Phase: LongInt; + ExplicitGenericMatches: LongInt; + WithVariableMatches: LongInt; + WithExpressionMatches: LongInt; + PlainWithMatches: LongInt; + WrongMatches: LongInt; + DestroyedTargets: LongInt; + +procedure TTarget.CheckPlain; +begin + if Pointer(Self) = Pointer(Expected) then + Inc(PlainWithMatches) + else + Inc(WrongMatches); +end; + +procedure TTarget.CheckGeneric; +begin + if Pointer(Self) <> Pointer(Expected) then + begin + Inc(WrongMatches); + Exit; + end; + case Phase of + 1: Inc(ExplicitGenericMatches); + 2: Inc(WithVariableMatches); + 3: Inc(WithExpressionMatches); + else + Inc(WrongMatches); + end; +end; + +procedure TValue.SetPlain(AValue: LongInt); +begin + Self.Number := AValue; +end; + +procedure TValue.SetGeneric(AValue: LongInt); +begin + Self.Number := AValue + SizeOf(T); +end; + +destructor TTarget.Destroy; +begin + Inc(DestroyedTargets); + inherited; +end; + +function MakeTarget: TTarget; +begin + Result := TTarget.Create; + Expected := Result; +end; + +procedure TOuter.Invoke; +var + Target: TTarget; +begin + Target := TTarget.Create; + try + Expected := Target; + Phase := 1; + Target.CheckGeneric; + Phase := 2; + with Target do + CheckGeneric; + with Target do + CheckPlain; + finally + Target.Free; + end; + + Phase := 3; + with MakeTarget do + begin + CheckGeneric; + Free; + end; +end; + +var + Outer: TOuter; + Value: TValue; +begin + Value.SetGeneric(20); + if Value.Number <> 22 then + Halt(7); + with Value do + SetGeneric(10); + if Value.Number <> 11 then + Halt(8); + with Value do + SetPlain(30); + if Value.Number <> 30 then + Halt(9); + + Outer := TOuter.Create; + try + Outer.Invoke; + finally + Outer.Free; + end; + if ExplicitGenericMatches <> 1 then + Halt(1); + if WithVariableMatches <> 1 then + Halt(2); + if WithExpressionMatches <> 1 then + Halt(3); + if PlainWithMatches <> 1 then + Halt(4); + if WrongMatches <> 0 then + Halt(5); + if DestroyedTargets <> 2 then + Halt(6); +end. diff --git a/tests/webtbs/tw41712.pp b/tests/webtbs/tw41712.pp new file mode 100644 index 00000000000..6bfacdc766e --- /dev/null +++ b/tests/webtbs/tw41712.pp @@ -0,0 +1,33 @@ +program tw41712; + +{$mode delphi} + +type + TTarget = class + procedure CheckGeneric; + end; + +var + Expected: TTarget; + Matches: LongInt; + +procedure TTarget.CheckGeneric; +begin + if Pointer(Self) = Pointer(Expected) then + Inc(Matches); +end; + +var + Instance: TTarget; +begin + Instance := TTarget.Create; + try + Expected := Instance; + with Instance do + CheckGeneric; + if Matches <> 1 then + Halt(1); + finally + Instance.Free; + end; +end.