fpc/tests/test/ugeneric102.pp
svenbarth f27ce0b159 Rework the way the method bodies for specializations are generated: instead of walking the global and local symboltable all pending specializations are kept in a list of the current module which is (for now) walked at the end of a unit/program to generate the method bodies as before.
fmodule.pas, tmodule:
  + new list pendingspecializations which keeps track of all pending specializations of the current module
psub.pas:
  * move generate_specialization_procs and related routines to pgenutil
  + new procedure read_proc_body to read a routine's body, cause generate_specialization_procs needs it (unlike the already existing overload in the implementation section, this one can only handle bodies of non-nested routines) 
pgenutil.pas:
  * generate_specialization_phase2: add the newly specialized generic to the current module's pending specializations
  * generate_specialization_procs: reworked so that it uses the new pendingspecializations field instead of walking the global and local symboltable of the current unit
pmodules.pas:
  + add pgenutil to uses due to the moved generate_specialization_procs

+ added test

git-svn-id: trunk@33826 -
2016-05-26 18:56:16 +00:00

73 lines
1.6 KiB
ObjectPascal

unit ugeneric102;
{$mode objfpc}{$H+}
interface
type
generic TTest<T> = class
class function Test(aTest: T): T; inline;
class function Test2(aTest: T): T; inline;
end;
TTestLongInt = specialize TTest<LongInt>;
generic function TestFunc<T>(aTest: T): T; inline;
procedure Test;
procedure Test2;
implementation
class function TTest.Test(aTest: T): T;
begin
Result := aTest;
end;
type
TTestBoolean = specialize TTest<Boolean>;
{ here the functions won't be inlined, cause the bodies are missing }
procedure Test;
begin
Writeln(TTestLongInt.Test(42));
Writeln(TTestBoolean.Test(True));
Writeln(specialize TTest<String>.Test('Hello World'));
Writeln(TTestLongInt.Test2(42));
Writeln(TTestBoolean.Test2(True));
Writeln(specialize TTest<String>.Test2('Hello World'));
Writeln(specialize TestFunc<LongInt>(42));
Writeln(specialize TestFunc<Boolean>(True));
Writeln(specialize TestFunc<String>('Hello World'));
end;
class function TTest.Test2(aTest: T): T;
begin
Result := aTest;
end;
generic function TestFunc<T>(aTest: T): T;
begin
Result := aTest;
end;
{ here the functions will be inlined as now the bodies are available }
procedure Test2;
begin
Writeln(TTestLongInt.Test(42));
Writeln(TTestBoolean.Test(True));
Writeln(specialize TTest<String>.Test('Hello World'));
Writeln(TTestLongInt.Test2(42));
Writeln(TTestBoolean.Test2(True));
Writeln(specialize TTest<String>.Test2('Hello World'));
Writeln(specialize TestFunc<LongInt>(42));
Writeln(specialize TestFunc<Boolean>(True));
Writeln(specialize TestFunc<String>('Hello World'));
end;
end.