fpc/tests/webtbs/tw19499.pp
svenbarth dbc410de63 Allow the usage of a generic's name without type arguments inside of nested classes inside the generic. This fixes Mantis #19499, but also Mantis #18688.
* symtable.pas:
    + add function "get_generic_in_hierarchy_by_name" which returns a def with the name of the symbol in the given object/record hierarchy (useful only in non-Delphi modes)
    + add function "return_specialization_of_generic" which returns the specialization def of a given class inside the given object/record hierarchy
* pexpr.pas, factor, factor_read_id: instead of checking whether the names of the found symbol and the current_structdef are equal, check whether the generic appears in hierarchy of current_structdef
* ptype.pas:
    * id_type: check whether the found symbol is a generic dummy and we are currently parsing a generic then return the correct def of the generic instead of the dummy one
    * single_type: when using the generic type without type parameters the def must resolve to the specialized def when specializing the class instead of the generic def which the dummy symbol points to
    * read_named_type, expr_type: like in "single_type" we need to resolve the use of the parameterless type name to the correct specialization def instead of the generic def
* pdecobj.pas, object_dec: also set the typesym of the current_structdef as otherwise some assumptions about generics with the above mentioned changes aren't valid anymore (like the def the typesym is unset again afterwards)
+ add tests for both bug reports (the one for 19499 is slightly modified so that it does not contain any errors)

git-svn-id: trunk@21361 -
2012-05-22 12:19:11 +00:00

72 lines
1.5 KiB
Plaintext

{$MODE OBJFPC} { -*- text -*- }
program tw19499;
{$apptype console}
type
generic THashTable <TKey, TValue> = class
type
THashTableEnumerator = class
private
FOwner: THashTable;
function GetCurrent(): TValue;
public
constructor Create(Owner: THashTable);
function MoveNext(): Boolean;
property Current: TValue read GetCurrent;
end;
function GetEnumerator(): THashTableEnumerator;
// note that this works:
var
Foo: THashTable;
procedure Bar(Arg: THashTable);
end;
function THashTable.THashTableEnumerator.GetCurrent(): TValue;
begin
// this did not compile in the original test
// Result := TValue(nil);
Result := Default(TValue);
end;
constructor THashTable.THashTableEnumerator.Create(Owner: THashTable);
begin
FOwner := Owner;
end;
function THashTable.THashTableEnumerator.MoveNext(): Boolean;
begin
Result := False;
end;
function THashTable.GetEnumerator(): THashTableEnumerator;
begin
Result := THashTableEnumerator.Create(Self);
end;
procedure THashTable.Bar(Arg: THashTable);
var
Quux: THashTable; // this works also
begin
end;
type
TIntegerToStringHashTable = specialize THashTable<Integer, AnsiString>;
var
Test: TIntegerToStringHashTable;
S: AnsiString;
begin
// this was incorrect in the original test
//Test.Create();
Test := TIntegerToStringHashTable.Create();
try
for S in Test do
Writeln(S);
finally
Test.Destroy();
end;
Writeln('PASS');
end.