From cc65ac20c5150e9ce5a30b4d375f93397c202052 Mon Sep 17 00:00:00 2001
From: svenbarth <pascaldragon@googlemail.com>
Date: Sun, 24 Jun 2012 10:35:21 +0000
Subject: [PATCH] Fix for Mantis #22220

ptype.pas:
  * read_named_type:
      allow specializations for pointers in Delphi modes
  * single_type:
      correctly handle forwarddefs; as we can only specialize generics if
      they are completely defined (srsym<>nil) we don't need to return a
      forward def, but instead return the specialized def itself
+ added tests to "test" instead of "webtbs" as no explicit tests were given
  in the report

git-svn-id: trunk@21689 -
---
 .gitattributes           |  4 ++++
 compiler/ptype.pas       | 22 ++++++++++++++++++++--
 tests/test/tgeneric87.pp | 18 ++++++++++++++++++
 tests/test/tgeneric88.pp | 17 +++++++++++++++++
 tests/test/tgeneric89.pp | 17 +++++++++++++++++
 tests/test/tgeneric90.pp | 26 ++++++++++++++++++++++++++
 6 files changed, 102 insertions(+), 2 deletions(-)
 create mode 100644 tests/test/tgeneric87.pp
 create mode 100644 tests/test/tgeneric88.pp
 create mode 100644 tests/test/tgeneric89.pp
 create mode 100644 tests/test/tgeneric90.pp

diff --git a/.gitattributes b/.gitattributes
index bb9602aec3..e3ed8e9d2e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10727,7 +10727,11 @@ tests/test/tgeneric83.pp svneol=native#text/pascal
 tests/test/tgeneric84.pp svneol=native#text/pascal
 tests/test/tgeneric85.pp svneol=native#text/pascal
 tests/test/tgeneric86.pp svneol=native#text/pascal
+tests/test/tgeneric87.pp svneol=native#text/pascal
+tests/test/tgeneric88.pp svneol=native#text/pascal
+tests/test/tgeneric89.pp svneol=native#text/pascal
 tests/test/tgeneric9.pp svneol=native#text/plain
+tests/test/tgeneric90.pp svneol=native#text/pascal
 tests/test/tgoto.pp svneol=native#text/plain
 tests/test/theap.pp svneol=native#text/plain
 tests/test/theapthread.pp svneol=native#text/plain
diff --git a/compiler/ptype.pas b/compiler/ptype.pas
index d0972f94c6..cf2d8a0af8 100644
--- a/compiler/ptype.pas
+++ b/compiler/ptype.pas
@@ -439,8 +439,22 @@ implementation
         if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
            (m_delphi in current_settings.modeswitches) then
           dospecialize:=token in [_LSHARPBRACKET,_LT];
+        if dospecialize and
+            (def.typ=forwarddef) then
+          begin
+            if not assigned(srsym) or not (srsym.typ=typesym) then
+              begin
+                Message(type_e_type_is_not_completly_defined);
+                def:=generrordef;
+                dospecialize:=false;
+              end;
+          end;
         if dospecialize then
-          generate_specialization(def,stoParseClassParent in options,'',nil,'')
+          begin
+            if def.typ=forwarddef then
+              def:=ttypesym(srsym).typedef;
+            generate_specialization(def,stoParseClassParent in options,'',nil,'');
+          end
         else
           begin
             if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
@@ -1330,6 +1344,7 @@ implementation
 
       const
         SingleTypeOptionsInTypeBlock:array[Boolean] of TSingleTypeOptions = ([],[stoIsForwardDef]);
+        SingleTypeOptionsIsDelphi:array[Boolean] of TSingleTypeOptions = ([],[stoAllowSpecialization]);
       var
         p  : tnode;
         hdef : tdef;
@@ -1459,7 +1474,10 @@ implementation
            _CARET:
               begin
                 consume(_CARET);
-                single_type(tt2,SingleTypeOptionsInTypeBlock[block_type=bt_type]);
+                single_type(tt2,
+                    SingleTypeOptionsInTypeBlock[block_type=bt_type]+
+                    SingleTypeOptionsIsDelphi[m_delphi in current_settings.modeswitches]
+                  );
                 { in case of e.g. var or const sections we need to especially
                   check that we don't use a generic dummy symbol }
                 if (block_type<>bt_type) and
diff --git a/tests/test/tgeneric87.pp b/tests/test/tgeneric87.pp
new file mode 100644
index 0000000000..33e2afc92c
--- /dev/null
+++ b/tests/test/tgeneric87.pp
@@ -0,0 +1,18 @@
+{ %FAIL }
+
+program tgeneric87;
+
+{$mode objfpc}
+
+type
+  generic TTest<T> = record
+
+  end;
+
+const
+  TestLongIntNil: ^specialize TTest<LongInt> = Nil;
+  TestBooleanNil: ^specialize TTest<Boolean> = Nil;
+
+begin
+
+end.
diff --git a/tests/test/tgeneric88.pp b/tests/test/tgeneric88.pp
new file mode 100644
index 0000000000..c8233ee7e2
--- /dev/null
+++ b/tests/test/tgeneric88.pp
@@ -0,0 +1,17 @@
+{ %FAIL }
+
+program tgeneric88;
+
+{$mode objfpc}
+
+type
+  generic TTest<T> = record
+
+  end;
+
+  PTestLongInt = ^specialize TTest<LongInt>;
+  PTestBoolean = ^specialize TTest<Boolean>;
+
+begin
+
+end.
diff --git a/tests/test/tgeneric89.pp b/tests/test/tgeneric89.pp
new file mode 100644
index 0000000000..5e50ef1549
--- /dev/null
+++ b/tests/test/tgeneric89.pp
@@ -0,0 +1,17 @@
+{ %NORUN }
+
+program tgeneric89;
+
+{$mode delphi}
+
+type
+  TTest<T> = record
+
+  end;
+
+  PTestLongInt = ^TTest<LongInt>;
+  PTestBoolean = ^TTest<Boolean>;
+
+begin
+
+end.
diff --git a/tests/test/tgeneric90.pp b/tests/test/tgeneric90.pp
new file mode 100644
index 0000000000..0c9ae3c4cb
--- /dev/null
+++ b/tests/test/tgeneric90.pp
@@ -0,0 +1,26 @@
+{ %NORUN }
+
+program tgeneric90;
+
+{$mode delphi}
+
+type
+  TTest = record
+
+  end;
+
+  TTest<T> = record
+
+  end;
+
+  TTest<T, S> = record
+
+  end;
+
+  PTestLongInt = ^TTest<LongInt>;
+  PTestLongIntLongInt = ^TTest<LongInt, LongInt>;
+  PTest = ^TTest;
+
+begin
+
+end.