Browse Source

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 -
svenbarth 13 years ago
parent
commit
cc65ac20c5
6 changed files with 102 additions and 2 deletions
  1. 4 0
      .gitattributes
  2. 20 2
      compiler/ptype.pas
  3. 18 0
      tests/test/tgeneric87.pp
  4. 17 0
      tests/test/tgeneric88.pp
  5. 17 0
      tests/test/tgeneric89.pp
  6. 26 0
      tests/test/tgeneric90.pp

+ 4 - 0
.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

+ 20 - 2
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

+ 18 - 0
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.

+ 17 - 0
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.

+ 17 - 0
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.

+ 26 - 0
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.