Browse Source

* Sync with trunk r23500.

git-svn-id: branches/targetandroid@23501 -
yury 12 years ago
parent
commit
8ae7c5784c
92 changed files with 1896 additions and 733 deletions
  1. 31 0
      .gitattributes
  2. 231 67
      compiler/arm/aoptcpu.pas
  3. 0 2
      compiler/cgobj.pas
  4. 0 1
      compiler/fppu.pas
  5. 4 2
      compiler/globtype.pas
  6. 1 0
      compiler/m68k/cpupara.pas
  7. 8 8
      compiler/m68k/n68kadd.pas
  8. 1 1
      compiler/mips/cpugas.pas
  9. 10 9
      compiler/mips/cpuinfo.pas
  10. 16 3
      compiler/msg/errore.msg
  11. 7 3
      compiler/msgidx.inc
  12. 329 317
      compiler/msgtxt.inc
  13. 7 1
      compiler/ncal.pas
  14. 0 2
      compiler/ncgcal.pas
  15. 2 2
      compiler/ncgcnv.pas
  16. 0 1
      compiler/ncnv.pas
  17. 0 2
      compiler/ngenutil.pas
  18. 49 23
      compiler/nmem.pas
  19. 33 2
      compiler/nset.pas
  20. 1 1
      compiler/optcse.pas
  21. 14 2
      compiler/options.pas
  22. 7 1
      compiler/pdecl.pas
  23. 10 6
      compiler/pdecobj.pas
  24. 8 3
      compiler/pexpr.pas
  25. 1 1
      compiler/pmodules.pas
  26. 5 1
      compiler/psub.pas
  27. 28 3
      compiler/ptype.pas
  28. 1 0
      compiler/scanner.pas
  29. 8 5
      compiler/symtable.pas
  30. 8 13
      compiler/x86/itx86int.pas
  31. 0 1
      compiler/x86/rax86.pas
  32. 5 2
      compiler/x86_64/cpuelf.pas
  33. 23 3
      packages/fcl-db/src/codegen/fpcgtiopf.pp
  34. 33 8
      packages/fcl-db/src/codegen/fpddcodegen.pp
  35. 5 2
      packages/fcl-db/src/sqldb/postgres/pqconnection.pp
  36. 2 1
      packages/fcl-db/src/sqldb/sqldb.pp
  37. 1 0
      packages/fcl-extra/src/daemonapp.pp
  38. 1 1
      packages/fcl-image/src/fpcanvas.pp
  39. 83 0
      packages/fcl-passrc/src/pastree.pp
  40. 3 0
      packages/fcl-passrc/src/pscanner.pp
  41. 1 0
      packages/fcl-stl/fpmake.pp
  42. 139 0
      packages/fcl-stl/src/gtree.pp
  43. 50 0
      packages/fcl-stl/tests/gtreetest.pp
  44. 4 4
      packages/fcl-xml/src/htmwrite.pp
  45. 2 0
      packages/winunits-base/src/shlobj.pp
  46. 1 2
      rtl/inc/compproc.inc
  47. 1 1
      rtl/inc/fexpand.inc
  48. 5 1
      rtl/inc/text.inc
  49. 2 2
      rtl/inc/threadvr.inc
  50. 3 9
      rtl/linux/Makefile
  51. 4 1
      rtl/linux/Makefile.fpc
  52. 125 1
      rtl/linux/mips/dllprt0.as
  53. 10 5
      rtl/m68k/m68k.inc
  54. 5 0
      rtl/win/systhrd.inc
  55. 15 13
      rtl/win64/system.pp
  56. BIN
      tests/test/cg/obj/linux/mips/cpptcl1.o
  57. BIN
      tests/test/cg/obj/linux/mips/cpptcl2.o
  58. BIN
      tests/test/cg/obj/linux/mips/ctest.o
  59. BIN
      tests/test/cg/obj/linux/mips/tcext3.o
  60. BIN
      tests/test/cg/obj/linux/mips/tcext4.o
  61. BIN
      tests/test/cg/obj/linux/mips/tcext5.o
  62. BIN
      tests/test/cg/obj/linux/mips/tcext6.o
  63. BIN
      tests/test/cg/obj/linux/mipsel/cpptcl1.o
  64. BIN
      tests/test/cg/obj/linux/mipsel/cpptcl2.o
  65. BIN
      tests/test/cg/obj/linux/mipsel/ctest.o
  66. BIN
      tests/test/cg/obj/linux/mipsel/tcext3.o
  67. BIN
      tests/test/cg/obj/linux/mipsel/tcext4.o
  68. BIN
      tests/test/cg/obj/linux/mipsel/tcext5.o
  69. BIN
      tests/test/cg/obj/linux/mipsel/tcext6.o
  70. 3 0
      tests/test/cg/obj/readme.txt
  71. 19 0
      tests/test/terecs12a.pp
  72. 20 0
      tests/test/terecs12b.pp
  73. 19 0
      tests/test/terecs12c.pp
  74. 18 0
      tests/test/terecs12d.pp
  75. 16 0
      tests/test/terecs13a.pp
  76. 17 0
      tests/test/terecs13b.pp
  77. 16 0
      tests/test/terecs13c.pp
  78. 15 0
      tests/test/terecs13d.pp
  79. 8 8
      tests/test/terecs15.pp
  80. 5 5
      tests/test/terecs16.pp
  81. 27 0
      tests/test/terecs17.pp
  82. 27 0
      tests/test/terecs17a.pp
  83. 32 0
      tests/test/terecs18.pp
  84. 32 0
      tests/test/terecs18a.pp
  85. 1 3
      tests/test/trhlp12.pp
  86. 28 0
      tests/test/trhlp45.pp
  87. 26 7
      tests/test/units/dos/tfexpand.pp
  88. 25 0
      tests/webtbs/tw19357.pp
  89. 34 0
      tests/webtbs/tw23130.pp
  90. 67 64
      utils/fpdoc/dglobals.pp
  91. 32 52
      utils/fpdoc/dw_html.pp
  92. 66 55
      utils/fpdoc/dwriter.pp

+ 31 - 0
.gitattributes

@@ -2613,6 +2613,7 @@ packages/fcl-stl/src/gpriorityqueue.pp svneol=native#text/plain
 packages/fcl-stl/src/gqueue.pp svneol=native#text/plain
 packages/fcl-stl/src/gqueue.pp svneol=native#text/plain
 packages/fcl-stl/src/gset.pp svneol=native#text/plain
 packages/fcl-stl/src/gset.pp svneol=native#text/plain
 packages/fcl-stl/src/gstack.pp svneol=native#text/plain
 packages/fcl-stl/src/gstack.pp svneol=native#text/plain
+packages/fcl-stl/src/gtree.pp svneol=native#text/plain
 packages/fcl-stl/src/gutil.pp svneol=native#text/plain
 packages/fcl-stl/src/gutil.pp svneol=native#text/plain
 packages/fcl-stl/src/gvector.pp svneol=native#text/plain
 packages/fcl-stl/src/gvector.pp svneol=native#text/plain
 packages/fcl-stl/tests/clean svneol=native#text/plain
 packages/fcl-stl/tests/clean svneol=native#text/plain
@@ -2628,6 +2629,7 @@ packages/fcl-stl/tests/gqueuetest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gsetrefcounttest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gsetrefcounttest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gsettest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gsettest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gstacktest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gstacktest.pp svneol=native#text/plain
+packages/fcl-stl/tests/gtreetest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gvectortest.pp svneol=native#text/plain
 packages/fcl-stl/tests/gvectortest.pp svneol=native#text/plain
 packages/fcl-stl/tests/run-all-tests svneol=native#text/plain
 packages/fcl-stl/tests/run-all-tests svneol=native#text/plain
 packages/fcl-stl/tests/suiteconfig.pp svneol=native#text/plain
 packages/fcl-stl/tests/suiteconfig.pp svneol=native#text/plain
@@ -9970,6 +9972,20 @@ tests/test/cg/obj/linux/i386/tcext4.o -text
 tests/test/cg/obj/linux/i386/tcext5.o -text
 tests/test/cg/obj/linux/i386/tcext5.o -text
 tests/test/cg/obj/linux/i386/tcext6.o -text
 tests/test/cg/obj/linux/i386/tcext6.o -text
 tests/test/cg/obj/linux/m68k/ctest.o -text
 tests/test/cg/obj/linux/m68k/ctest.o -text
+tests/test/cg/obj/linux/mips/cpptcl1.o -text
+tests/test/cg/obj/linux/mips/cpptcl2.o -text
+tests/test/cg/obj/linux/mips/ctest.o -text
+tests/test/cg/obj/linux/mips/tcext3.o -text
+tests/test/cg/obj/linux/mips/tcext4.o -text
+tests/test/cg/obj/linux/mips/tcext5.o -text
+tests/test/cg/obj/linux/mips/tcext6.o -text
+tests/test/cg/obj/linux/mipsel/cpptcl1.o -text
+tests/test/cg/obj/linux/mipsel/cpptcl2.o -text
+tests/test/cg/obj/linux/mipsel/ctest.o -text
+tests/test/cg/obj/linux/mipsel/tcext3.o -text
+tests/test/cg/obj/linux/mipsel/tcext4.o -text
+tests/test/cg/obj/linux/mipsel/tcext5.o -text
+tests/test/cg/obj/linux/mipsel/tcext6.o -text
 tests/test/cg/obj/linux/powerpc/cpptcl1.o -text
 tests/test/cg/obj/linux/powerpc/cpptcl1.o -text
 tests/test/cg/obj/linux/powerpc/cpptcl2.o -text
 tests/test/cg/obj/linux/powerpc/cpptcl2.o -text
 tests/test/cg/obj/linux/powerpc/ctest.o -text
 tests/test/cg/obj/linux/powerpc/ctest.o -text
@@ -10807,10 +10823,22 @@ tests/test/terecs1.pp svneol=native#text/pascal
 tests/test/terecs10.pp svneol=native#text/pascal
 tests/test/terecs10.pp svneol=native#text/pascal
 tests/test/terecs11.pp svneol=native#text/pascal
 tests/test/terecs11.pp svneol=native#text/pascal
 tests/test/terecs12.pp svneol=native#text/pascal
 tests/test/terecs12.pp svneol=native#text/pascal
+tests/test/terecs12a.pp svneol=native#text/pascal
+tests/test/terecs12b.pp svneol=native#text/pascal
+tests/test/terecs12c.pp svneol=native#text/pascal
+tests/test/terecs12d.pp svneol=native#text/pascal
 tests/test/terecs13.pp svneol=native#text/pascal
 tests/test/terecs13.pp svneol=native#text/pascal
+tests/test/terecs13a.pp svneol=native#text/pascal
+tests/test/terecs13b.pp svneol=native#text/pascal
+tests/test/terecs13c.pp svneol=native#text/pascal
+tests/test/terecs13d.pp svneol=native#text/pascal
 tests/test/terecs14.pp svneol=native#text/pascal
 tests/test/terecs14.pp svneol=native#text/pascal
 tests/test/terecs15.pp svneol=native#text/pascal
 tests/test/terecs15.pp svneol=native#text/pascal
 tests/test/terecs16.pp svneol=native#text/pascal
 tests/test/terecs16.pp svneol=native#text/pascal
+tests/test/terecs17.pp svneol=native#text/pascal
+tests/test/terecs17a.pp svneol=native#text/pascal
+tests/test/terecs18.pp svneol=native#text/pascal
+tests/test/terecs18a.pp svneol=native#text/pascal
 tests/test/terecs2.pp svneol=native#text/pascal
 tests/test/terecs2.pp svneol=native#text/pascal
 tests/test/terecs3.pp svneol=native#text/pascal
 tests/test/terecs3.pp svneol=native#text/pascal
 tests/test/terecs4.pp svneol=native#text/pascal
 tests/test/terecs4.pp svneol=native#text/pascal
@@ -11459,6 +11487,7 @@ tests/test/trhlp41.pp svneol=native#text/pascal
 tests/test/trhlp42.pp svneol=native#text/pascal
 tests/test/trhlp42.pp svneol=native#text/pascal
 tests/test/trhlp43.pp svneol=native#text/pascal
 tests/test/trhlp43.pp svneol=native#text/pascal
 tests/test/trhlp44.pp svneol=native#text/pascal
 tests/test/trhlp44.pp svneol=native#text/pascal
+tests/test/trhlp45.pp svneol=native#text/pascal
 tests/test/trhlp5.pp svneol=native#text/pascal
 tests/test/trhlp5.pp svneol=native#text/pascal
 tests/test/trhlp6.pp svneol=native#text/pascal
 tests/test/trhlp6.pp svneol=native#text/pascal
 tests/test/trhlp7.pp svneol=native#text/pascal
 tests/test/trhlp7.pp svneol=native#text/pascal
@@ -12918,6 +12947,7 @@ tests/webtbs/tw1931.pp svneol=native#text/plain
 tests/webtbs/tw1932.pp svneol=native#text/plain
 tests/webtbs/tw1932.pp svneol=native#text/plain
 tests/webtbs/tw19325.pp svneol=native#text/pascal
 tests/webtbs/tw19325.pp svneol=native#text/pascal
 tests/webtbs/tw1935.pp svneol=native#text/plain
 tests/webtbs/tw1935.pp svneol=native#text/plain
+tests/webtbs/tw19357.pp svneol=native#text/pascal
 tests/webtbs/tw1936.pp svneol=native#text/plain
 tests/webtbs/tw1936.pp svneol=native#text/plain
 tests/webtbs/tw19368.pp svneol=native#text/pascal
 tests/webtbs/tw19368.pp svneol=native#text/pascal
 tests/webtbs/tw1938.pp svneol=native#text/plain
 tests/webtbs/tw1938.pp svneol=native#text/plain
@@ -13127,6 +13157,7 @@ tests/webtbs/tw2305.pp svneol=native#text/plain
 tests/webtbs/tw2306.pp svneol=native#text/plain
 tests/webtbs/tw2306.pp svneol=native#text/plain
 tests/webtbs/tw2307.pp svneol=native#text/plain
 tests/webtbs/tw2307.pp svneol=native#text/plain
 tests/webtbs/tw2311.pp svneol=native#text/plain
 tests/webtbs/tw2311.pp svneol=native#text/plain
+tests/webtbs/tw23130.pp svneol=native#text/pascal
 tests/webtbs/tw23136.pp svneol=native#text/pascal
 tests/webtbs/tw23136.pp svneol=native#text/pascal
 tests/webtbs/tw2317.pp svneol=native#text/plain
 tests/webtbs/tw2317.pp svneol=native#text/plain
 tests/webtbs/tw2318.pp svneol=native#text/plain
 tests/webtbs/tw2318.pp svneol=native#text/plain

+ 231 - 67
compiler/arm/aoptcpu.pas

@@ -41,6 +41,9 @@ Type
     procedure RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string);
     procedure RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string);
     function RegUsedAfterInstruction(reg: Tregister; p: tai;
     function RegUsedAfterInstruction(reg: Tregister; p: tai;
                                      var AllUsedRegs: TAllUsedRegs): Boolean;
                                      var AllUsedRegs: TAllUsedRegs): Boolean;
+    { returns true if reg reaches it's end of life at p, this means it is either
+      reloaded with a new value or it is deallocated afterwards }
+    function RegEndOfLife(reg: TRegister;p: taicpu): boolean;
     { gets the next tai object after current that contains info relevant
     { gets the next tai object after current that contains info relevant
       to the optimizer in p1 which used the given register or does a 
       to the optimizer in p1 which used the given register or does a 
       change in program flow.
       change in program flow.
@@ -73,7 +76,7 @@ Type
 Implementation
 Implementation
 
 
   uses
   uses
-    cutils,verbose,globals,
+    cutils,verbose,globtype,globals,
     systems,
     systems,
     cpuinfo,
     cpuinfo,
     cgobj,cgutils,procinfo,
     cgobj,cgutils,procinfo,
@@ -302,13 +305,20 @@ Implementation
     end;
     end;
 
 
 
 
+  function TCpuAsmOptimizer.RegEndOfLife(reg : TRegister;p : taicpu) : boolean;
+    begin
+       Result:=assigned(FindRegDealloc(reg,tai(p.Next))) or
+         RegLoadedWithNewValue(reg,p);
+    end;
+
+
   function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
   function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
     var Next: tai; reg: TRegister): Boolean;
     var Next: tai; reg: TRegister): Boolean;
     begin
     begin
       Next:=Current;
       Next:=Current;
       repeat
       repeat
         Result:=GetNextInstruction(Next,Next);
         Result:=GetNextInstruction(Next,Next);
-      until not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
+      until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
         (is_calljmp(taicpu(Next).opcode)) or (RegInInstruction(NR_PC,Next));
         (is_calljmp(taicpu(Next).opcode)) or (RegInInstruction(NR_PC,Next));
     end;
     end;
 
 
@@ -763,38 +773,60 @@ Implementation
                           mov reg1,reg0, shift imm1
                           mov reg1,reg0, shift imm1
                           mov reg1,reg1, shift imm2
                           mov reg1,reg1, shift imm2
                           mov reg1,reg1, shift imm3 ...
                           mov reg1,reg1, shift imm3 ...
+                          mov reg2,reg1, shift imm3 ...
                         }
                         }
-                        else if getnextinstruction(hp1,hp2) and
+                        else if GetNextInstructionUsingReg(hp1,hp2, taicpu(hp1).oper[0]^.reg) and
                           MatchInstruction(hp2, A_MOV, [taicpu(p).condition], [PF_None]) and
                           MatchInstruction(hp2, A_MOV, [taicpu(p).condition], [PF_None]) and
                           (taicpu(hp2).ops=3) and
                           (taicpu(hp2).ops=3) and
-                          MatchOperand(taicpu(hp2).oper[0]^, taicpu(hp1).oper[0]^.reg) and
                           MatchOperand(taicpu(hp2).oper[1]^, taicpu(hp1).oper[0]^.reg) and
                           MatchOperand(taicpu(hp2).oper[1]^, taicpu(hp1).oper[0]^.reg) and
+                          RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp2)) and
                           (taicpu(hp2).oper[2]^.typ = top_shifterop) and
                           (taicpu(hp2).oper[2]^.typ = top_shifterop) and
                           (taicpu(hp2).oper[2]^.shifterop^.rs = NR_NO) then
                           (taicpu(hp2).oper[2]^.shifterop^.rs = NR_NO) then
                           begin
                           begin
                             { mov reg1,reg0, lsl imm1
                             { mov reg1,reg0, lsl imm1
                               mov reg1,reg1, lsr/asr imm2
                               mov reg1,reg1, lsr/asr imm2
-                              mov reg1,reg1, lsl imm3 ...
-
-                              if imm3<=imm1 and imm2>=imm3
+                              mov reg2,reg1, lsl imm3 ...
                               to
                               to
                               mov reg1,reg0, lsl imm1
                               mov reg1,reg0, lsl imm1
-                              mov reg1,reg1, lsr/asr imm2-imm3
+                              mov reg2,reg1, lsr/asr imm2-imm3
+                              if
+                              imm1>=imm2
                             }
                             }
                             if (taicpu(p).oper[2]^.shifterop^.shiftmode=SM_LSL) and (taicpu(hp2).oper[2]^.shifterop^.shiftmode=SM_LSL) and
                             if (taicpu(p).oper[2]^.shifterop^.shiftmode=SM_LSL) and (taicpu(hp2).oper[2]^.shifterop^.shiftmode=SM_LSL) and
                               (taicpu(hp1).oper[2]^.shifterop^.shiftmode in [SM_ASR,SM_LSR]) and
                               (taicpu(hp1).oper[2]^.shifterop^.shiftmode in [SM_ASR,SM_LSR]) and
-                              (taicpu(hp2).oper[2]^.shifterop^.shiftimm<=taicpu(p).oper[2]^.shifterop^.shiftimm) and
-                              (taicpu(hp1).oper[2]^.shifterop^.shiftimm>=taicpu(hp2).oper[2]^.shifterop^.shiftimm) then
+                              (taicpu(p).oper[2]^.shifterop^.shiftimm>=taicpu(hp1).oper[2]^.shifterop^.shiftimm) then
                               begin
                               begin
-                                dec(taicpu(hp1).oper[2]^.shifterop^.shiftimm,taicpu(hp2).oper[2]^.shifterop^.shiftimm);
-                                DebugMsg('Peephole ShiftShiftShift2ShiftShift 1 done', p);
-                                asml.remove(hp2);
-                                hp2.free;
-                                result := true;
-                                if taicpu(hp1).oper[2]^.shifterop^.shiftimm=0 then
+                                if (taicpu(hp2).oper[2]^.shifterop^.shiftimm>=taicpu(hp1).oper[2]^.shifterop^.shiftimm) then
                                   begin
                                   begin
-                                    asml.remove(hp1);
-                                    hp1.free;
+                                    if not(RegUsedBetween(taicpu(hp2).oper[0]^.reg,p,hp1)) and
+                                      not(RegUsedBetween(taicpu(hp2).oper[0]^.reg,hp1,hp2)) then
+                                      begin
+                                        DebugMsg('Peephole ShiftShiftShift2ShiftShift 1a done', p);
+                                        inc(taicpu(p).oper[2]^.shifterop^.shiftimm,taicpu(hp2).oper[2]^.shifterop^.shiftimm-taicpu(hp1).oper[2]^.shifterop^.shiftimm);
+                                        taicpu(p).oper[0]^.reg:=taicpu(hp2).oper[0]^.reg;
+                                        asml.remove(hp1);
+                                        asml.remove(hp2);
+                                        hp1.free;
+                                        hp2.free;
+
+                                        if taicpu(hp1).oper[2]^.shifterop^.shiftimm>=32 then
+                                          begin
+                                            taicpu(p).freeop(1);
+                                            taicpu(p).freeop(2);
+                                            taicpu(p).loadconst(1,0);
+                                          end;
+                                        result := true;
+                                      end;
+                                  end
+                                else if not(RegUsedBetween(taicpu(hp2).oper[0]^.reg,hp1,hp2)) then
+                                  begin
+                                    DebugMsg('Peephole ShiftShiftShift2ShiftShift 1b done', p);
+
+                                    dec(taicpu(hp1).oper[2]^.shifterop^.shiftimm,taicpu(hp2).oper[2]^.shifterop^.shiftimm);
+                                    taicpu(hp1).oper[0]^.reg:=taicpu(hp2).oper[0]^.reg;
+                                    asml.remove(hp2);
+                                    hp2.free;
+                                    result := true;
                                   end;
                                   end;
                               end
                               end
                             { mov reg1,reg0, lsr/asr imm1
                             { mov reg1,reg0, lsr/asr imm1
@@ -829,10 +861,10 @@ Implementation
                           end;
                           end;
                       end;
                       end;
                     { Change the common
                     { Change the common
-                      mov r0, r0, lsr #24
-                      and r0, r0, #255
+                      mov r0, r0, lsr #xxx
+                      and r0, r0, #yyy/bic r0, r0, #xxx
 
 
-                      and remove the superfluous and
+                      and remove the superfluous and/bic if possible
 
 
                       This could be extended to handle more cases.
                       This could be extended to handle more cases.
                     }
                     }
@@ -840,29 +872,46 @@ Implementation
                        (taicpu(p).oper[2]^.typ = top_shifterop) and
                        (taicpu(p).oper[2]^.typ = top_shifterop) and
                        (taicpu(p).oper[2]^.shifterop^.rs = NR_NO) and
                        (taicpu(p).oper[2]^.shifterop^.rs = NR_NO) and
                        (taicpu(p).oper[2]^.shifterop^.shiftmode = SM_LSR) and
                        (taicpu(p).oper[2]^.shifterop^.shiftmode = SM_LSR) and
-                       (taicpu(p).oper[2]^.shifterop^.shiftimm >= 24 ) and
                        GetNextInstructionUsingReg(p,hp1, taicpu(p).oper[0]^.reg) and
                        GetNextInstructionUsingReg(p,hp1, taicpu(p).oper[0]^.reg) and
                        (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
                        (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
-                         regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) and
-                       MatchInstruction(hp1, A_AND, [taicpu(p).condition], [taicpu(p).oppostfix]) and
-                       (taicpu(hp1).ops=3) and
-                       MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[0]^) and
-                       MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^) and
-                       (taicpu(hp1).oper[2]^.typ = top_const) and
-                       { Check if the AND actually would only mask out bits beeing already zero because of the shift
-                         For LSR #25 and an AndConst of 255 that whould go like this:
-                         255 and ((2 shl (32-25))-1)
-                         which results in 127, which is one less a power-of-2, meaning all lower bits are set.
-
-                         LSR #25 and AndConst of 254:
-                         254 and ((2 shl (32-25))-1) = 126 -> lowest bit is clear, so we can't remove it.
-                       }
-                       ispowerof2((taicpu(hp1).oper[2]^.val and ((2 shl (32-taicpu(p).oper[2]^.shifterop^.shiftimm))-1))+1) then
-                      begin
-                        DebugMsg('Peephole LsrAnd2Lsr done', hp1);
-                        asml.remove(hp1);
-                        hp1.free;
-                      end;
+                         regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) then
+                       begin
+                         if (taicpu(p).oper[2]^.shifterop^.shiftimm >= 24 ) and
+                           MatchInstruction(hp1, A_AND, [taicpu(p).condition], [taicpu(p).oppostfix]) and
+                           (taicpu(hp1).ops=3) and
+                           MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^) and
+                           (taicpu(hp1).oper[2]^.typ = top_const) and
+                           { Check if the AND actually would only mask out bits beeing already zero because of the shift
+                             For LSR #25 and an AndConst of 255 that whould go like this:
+                             255 and ((2 shl (32-25))-1)
+                             which results in 127, which is one less a power-of-2, meaning all lower bits are set.
+
+                             LSR #25 and AndConst of 254:
+                             254 and ((2 shl (32-25))-1) = 126 -> lowest bit is clear, so we can't remove it.
+                           }
+                           ispowerof2((taicpu(hp1).oper[2]^.val and ((2 shl (32-taicpu(p).oper[2]^.shifterop^.shiftimm))-1))+1) then
+                           begin
+                             DebugMsg('Peephole LsrAnd2Lsr done', hp1);
+                             taicpu(p).oper[0]^.reg:=taicpu(hp1).oper[0]^.reg;
+                             asml.remove(hp1);
+                             hp1.free;
+                             result:=true;
+                           end
+                         else if MatchInstruction(hp1, A_BIC, [taicpu(p).condition], [taicpu(p).oppostfix]) and
+                           (taicpu(hp1).ops=3) and
+                           MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^) and
+                           (taicpu(hp1).oper[2]^.typ = top_const) and
+                           { Check if the BIC actually would only mask out bits beeing already zero because of the shift }
+                           (taicpu(hp1).oper[2]^.val<>0) and
+                           (BsfDWord(taicpu(hp1).oper[2]^.val)>=32-taicpu(p).oper[2]^.shifterop^.shiftimm) then
+                           begin
+                             DebugMsg('Peephole LsrBic2Lsr done', hp1);
+                             taicpu(p).oper[0]^.reg:=taicpu(hp1).oper[0]^.reg;
+                             asml.remove(hp1);
+                             hp1.free;
+                             result:=true;
+                           end;
+                       end;
 
 
                     {
                     {
                       optimize
                       optimize
@@ -1064,7 +1113,51 @@ Implementation
                               break;
                               break;
                             end;
                             end;
                       end;
                       end;
-
+                    {
+                      Fold
+                        mov r1, r1, lsl #2
+                        ldr/ldrb r0, [r0, r1]
+                      to
+                        ldr/ldrb r0, [r0, r1, lsl #2]
+
+                      XXX: This still needs some work, as we quite often encounter something like
+                             mov r1, r2, lsl #2
+                             add r2, r3, #imm
+                             ldr r0, [r2, r1]
+                           which can't be folded because r2 is overwritten between the shift and the ldr.
+                           We could try to shuffle the registers around and fold it into.
+                             add r1, r3, #imm
+                             ldr r0, [r1, r2, lsl #2]
+                    }
+                    if (taicpu(p).opcode = A_MOV) and
+                       (taicpu(p).ops = 3) and
+                       (taicpu(p).oper[1]^.typ = top_reg) and
+                       (taicpu(p).oper[2]^.typ = top_shifterop) and
+                       { RRX is tough to handle, because it requires tracking the C-Flag,
+                         it is also extremly unlikely to be emitted this way}
+                       (taicpu(p).oper[2]^.shifterop^.shiftmode <> SM_RRX) and
+                       (taicpu(p).oper[2]^.shifterop^.shiftimm <> 0) and
+                       (taicpu(p).oppostfix = PF_NONE) and
+                       GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                       {Only LDR, LDRB, STR, STRB can handle scaled register indexing}
+                       MatchInstruction(hp1, [A_LDR, A_STR], [taicpu(p).condition],
+                                             [PF_None, PF_B]) and
+                       (taicpu(hp1).oper[1]^.ref^.index = taicpu(p).oper[0]^.reg) and
+                       (taicpu(hp1).oper[1]^.ref^.base <> taicpu(p).oper[0]^.reg) and
+                       { Only fold if there isn't another shifterop already. }
+                       (taicpu(hp1).oper[1]^.ref^.shiftmode = SM_None) and
+                       not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) and
+                       (assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) or
+                         regLoadedWithNewValue(taicpu(p).oper[0]^.reg, hp1)) then
+                       begin
+                         DebugMsg('Peephole FoldShiftLdrStr done', hp1);
+                         taicpu(hp1).oper[1]^.ref^.index := taicpu(p).oper[1]^.reg;
+                         taicpu(hp1).oper[1]^.ref^.shiftmode := taicpu(p).oper[2]^.shifterop^.shiftmode;
+                         taicpu(hp1).oper[1]^.ref^.shiftimm := taicpu(p).oper[2]^.shifterop^.shiftimm;
+                         asml.remove(p);
+                         p.free;
+                         p:=hp1;
+                       end;
                     {
                     {
                       Often we see shifts and then a superfluous mov to another register
                       Often we see shifts and then a superfluous mov to another register
                       In the future this might be handled in RedundantMovProcess when it uses RegisterTracking
                       In the future this might be handled in RedundantMovProcess when it uses RegisterTracking
@@ -1099,24 +1192,38 @@ Implementation
                         {
                         {
                           change
                           change
                           and reg2,reg1,const1
                           and reg2,reg1,const1
+                          ...
                           and reg3,reg2,const2
                           and reg3,reg2,const2
                           to
                           to
                           and reg3,reg1,(const1 and const2)
                           and reg3,reg1,(const1 and const2)
                         }
                         }
-                        if GetNextInstruction(p, hp1) and
+                        if GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
                         MatchInstruction(hp1, A_AND, [taicpu(p).condition], [PF_None]) and
                         MatchInstruction(hp1, A_AND, [taicpu(p).condition], [PF_None]) and
-                        { either reg3 and reg2 are equal or reg2 is deallocated after the and }
-                        (MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[0]^.reg) or
-                         assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next)))) and
+                        RegEndOfLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
                         MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
                         MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
                         (taicpu(hp1).oper[2]^.typ = top_const) then
                         (taicpu(hp1).oper[2]^.typ = top_const) then
                           begin
                           begin
-                            DebugMsg('Peephole AndAnd2And done', p);
-                            taicpu(p).loadConst(2,taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val);
-                            taicpu(p).oppostfix:=taicpu(hp1).oppostfix;
-                            taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
-                            asml.remove(hp1);
-                            hp1.free;
+                            if not(RegUsedBetween(taicpu(hp1).oper[0]^.reg,p,hp1)) then
+                              begin
+                                DebugMsg('Peephole AndAnd2And done', p);
+                                taicpu(p).loadConst(2,taicpu(p).oper[2]^.val and taicpu(hp1).oper[2]^.val);
+                                taicpu(p).oppostfix:=taicpu(hp1).oppostfix;
+                                taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
+                                asml.remove(hp1);
+                                hp1.free;
+                                Result:=true;
+                              end
+                            else if not(RegUsedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                              begin
+                                DebugMsg('Peephole AndAnd2And done', hp1);
+                                taicpu(hp1).loadConst(2,taicpu(hp1).oper[2]^.val and taicpu(hp1).oper[2]^.val);
+                                taicpu(hp1).oppostfix:=taicpu(p).oppostfix;
+                                taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                                asml.remove(p);
+                                p.free;
+                                p:=hp1;
+                                Result:=true;
+                              end;
                           end
                           end
                         {
                         {
                           change
                           change
@@ -1141,6 +1248,70 @@ Implementation
                             asml.remove(p);
                             asml.remove(p);
                             p.free;
                             p.free;
                             p:=hp1;
                             p:=hp1;
+                          end
+                        {
+                          from
+                          and reg1,reg0,2^n-1
+                          mov reg2,reg1, lsl imm1
+                          (mov reg3,reg2, lsr/asr imm1)
+                          remove either the and or the lsl/xsr sequence if possible
+                        }
+
+                        else if cutils.ispowerof2(taicpu(p).oper[2]^.val+1,i) and
+                          GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                          MatchInstruction(hp1, A_MOV, [taicpu(p).condition], [PF_None]) and
+                          (taicpu(hp1).ops=3) and
+                          MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                          (taicpu(hp1).oper[2]^.typ = top_shifterop) and
+                          (taicpu(hp1).oper[2]^.shifterop^.rs = NR_NO) and
+                          (taicpu(hp1).oper[2]^.shifterop^.shiftmode=SM_LSL) and
+                          RegEndOfLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) then
+                          begin
+                            {
+                              and reg1,reg0,2^n-1
+                              mov reg2,reg1, lsl imm1
+                              mov reg3,reg2, lsr/asr imm1
+                              =>
+                              and reg1,reg0,2^n-1
+                              if lsr and 2^n-1>=imm1 or asr and 2^n-1>imm1
+                            }
+                            if GetNextInstructionUsingReg(hp1,hp2,taicpu(p).oper[0]^.reg) and
+                              MatchInstruction(hp2, A_MOV, [taicpu(p).condition], [PF_None]) and
+                              (taicpu(hp2).ops=3) and
+                              MatchOperand(taicpu(hp2).oper[1]^, taicpu(hp1).oper[0]^.reg) and
+                              (taicpu(hp2).oper[2]^.typ = top_shifterop) and
+                              (taicpu(hp2).oper[2]^.shifterop^.rs = NR_NO) and
+                              (taicpu(hp2).oper[2]^.shifterop^.shiftmode in [SM_ASR,SM_LSR]) and
+                              (taicpu(hp1).oper[2]^.shifterop^.shiftimm=taicpu(hp2).oper[2]^.shifterop^.shiftimm) and
+                              RegEndOfLife(taicpu(hp1).oper[0]^.reg,taicpu(hp2)) and
+                              ((i<32-taicpu(hp1).oper[2]^.shifterop^.shiftimm) or
+                              ((i=32-taicpu(hp1).oper[2]^.shifterop^.shiftimm) and
+                               (taicpu(hp2).oper[2]^.shifterop^.shiftmode=SM_LSR))) then
+                              begin
+                                DebugMsg('Peephole AndLslXsr2And done', p);
+                                taicpu(p).oper[0]^.reg:=taicpu(hp2).oper[0]^.reg;
+                                asml.Remove(hp1);
+                                asml.Remove(hp2);
+                                hp1.free;
+                                hp2.free;
+                                result:=true;
+                              end
+                            {
+                              and reg1,reg0,2^n-1
+                              mov reg2,reg1, lsl imm1
+                              =>
+                              mov reg2,reg1, lsl imm1
+                              if imm1>i
+                            }
+                            else if i>32-taicpu(hp1).oper[2]^.shifterop^.shiftimm then
+                              begin
+                                DebugMsg('Peephole AndLsl2Lsl done', p);
+                                taicpu(hp1).oper[1]^.reg:=taicpu(p).oper[0]^.reg;
+                                asml.Remove(p);
+                                p.free;
+                                p:=hp1;
+                                result:=true;
+                              end
                           end;
                           end;
                       end;
                       end;
                     {
                     {
@@ -1410,7 +1581,8 @@ Implementation
                       into
                       into
                       b         abc
                       b         abc
                     }
                     }
-                    if MatchInstruction(p, A_STM, [C_None], [PF_FD]) and
+                    if not(ts_thumb_interworking in current_settings.targetswitches) and
+                       MatchInstruction(p, A_STM, [C_None], [PF_FD]) and
                       GetNextInstruction(p, hp1) and
                       GetNextInstruction(p, hp1) and
                       GetNextInstruction(hp1, hp2) and
                       GetNextInstruction(hp1, hp2) and
                       SkipEntryExitMarker(hp2, hp2) and
                       SkipEntryExitMarker(hp2, hp2) and
@@ -1428,27 +1600,19 @@ Implementation
                       MatchInstruction(hp1, A_SUB, [C_None], [PF_NONE]) and
                       MatchInstruction(hp1, A_SUB, [C_None], [PF_NONE]) and
                       (taicpu(hp1).oper[0]^.typ = top_reg) and
                       (taicpu(hp1).oper[0]^.typ = top_reg) and
                       (taicpu(hp1).oper[0]^.reg = NR_STACK_POINTER_REG) and
                       (taicpu(hp1).oper[0]^.reg = NR_STACK_POINTER_REG) and
-                      (taicpu(hp1).oper[1]^.typ = top_reg) and
-                      (taicpu(hp1).oper[1]^.reg = NR_STACK_POINTER_REG) and
+                      MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp1).oper[1]^) and
                       (taicpu(hp1).oper[2]^.typ = top_const) and
                       (taicpu(hp1).oper[2]^.typ = top_const) and
 
 
                       MatchInstruction(hp3, A_ADD, [C_None], [PF_NONE]) and
                       MatchInstruction(hp3, A_ADD, [C_None], [PF_NONE]) and
-                      (taicpu(hp3).oper[0]^.typ = top_reg) and
-                      (taicpu(hp3).oper[0]^.reg = NR_STACK_POINTER_REG) and
-                      (taicpu(hp3).oper[1]^.typ = top_reg) and
-                      (taicpu(hp3).oper[1]^.reg = NR_STACK_POINTER_REG) and
-                      (taicpu(hp3).oper[2]^.typ = top_const) and
-                      (taicpu(hp1).oper[2]^.val = taicpu(hp3).oper[2]^.val) and
+                      MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp3).oper[0]^) and
+                      MatchOperand(taicpu(hp1).oper[0]^,taicpu(hp3).oper[1]^) and
+                      MatchOperand(taicpu(hp1).oper[2]^,taicpu(hp3).oper[2]^) and
 
 
                       MatchInstruction(hp2, [A_BL,A_BLX], [C_None], [PF_NONE]) and
                       MatchInstruction(hp2, [A_BL,A_BLX], [C_None], [PF_NONE]) and
                       (taicpu(hp2).oper[0]^.typ = top_ref) and
                       (taicpu(hp2).oper[0]^.typ = top_ref) and
 
 
                       MatchInstruction(hp4, A_LDM, [C_None], [PF_FD]) and
                       MatchInstruction(hp4, A_LDM, [C_None], [PF_FD]) and
-                      (taicpu(hp4).oper[0]^.typ = top_ref) and
-                      (taicpu(hp4).oper[0]^.ref^.index=NR_STACK_POINTER_REG) and
-                      (taicpu(hp4).oper[0]^.ref^.base=NR_NO) and
-                      (taicpu(hp4).oper[0]^.ref^.offset=0) and
-                      (taicpu(hp4).oper[0]^.ref^.addressmode=AM_PREINDEXED) and
+                      MatchOperand(taicpu(p).oper[0]^,taicpu(hp4).oper[0]^) and
                       (taicpu(hp4).oper[1]^.typ = top_regset) and
                       (taicpu(hp4).oper[1]^.typ = top_regset) and
                       (taicpu(hp4).oper[1]^.regset^ = [RS_R15]) then
                       (taicpu(hp4).oper[1]^.regset^ = [RS_R15]) then
                       begin
                       begin

+ 0 - 2
compiler/cgobj.pas

@@ -1848,8 +1848,6 @@ implementation
 
 
 
 
     procedure tcg.a_loadmm_loc_reg(list: TAsmList; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
     procedure tcg.a_loadmm_loc_reg(list: TAsmList; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
-      var
-        tmpreg: tregister;
       begin
       begin
         case loc.loc of
         case loc.loc of
           LOC_MMREGISTER,LOC_CMMREGISTER:
           LOC_MMREGISTER,LOC_CMMREGISTER:

+ 0 - 1
compiler/fppu.pas

@@ -947,7 +947,6 @@ var
       var
       var
         b : byte;
         b : byte;
         newmodulename : string;
         newmodulename : string;
-        ns: string;
       begin
       begin
        { read interface part }
        { read interface part }
          repeat
          repeat

+ 4 - 2
compiler/globtype.pas

@@ -225,7 +225,8 @@ interface
          { when automatically generating getters/setters for properties, use
          { when automatically generating getters/setters for properties, use
            these strings as prefixes for the generated getters/setter names }
            these strings as prefixes for the generated getters/setter names }
          ts_auto_getter_prefix,
          ts_auto_getter_prefix,
-         ts_auto_setter_predix
+         ts_auto_setter_predix,
+         ts_thumb_interworking
        );
        );
        ttargetswitches = set of ttargetswitch;
        ttargetswitches = set of ttargetswitch;
 
 
@@ -300,7 +301,8 @@ interface
          (name: 'COMPACTINTARRAYINIT'; hasvalue: false),
          (name: 'COMPACTINTARRAYINIT'; hasvalue: false),
          (name:  'ENUMFIELDINIT';      hasvalue: false),
          (name:  'ENUMFIELDINIT';      hasvalue: false),
          (name: 'AUTOGETTERPREFIX';    hasvalue: true ),
          (name: 'AUTOGETTERPREFIX';    hasvalue: true ),
-         (name: 'AUTOSETTERPREFIX';    hasvalue: true )
+         (name: 'AUTOSETTERPREFIX';    hasvalue: true ),
+         (name: 'THUMBINTERWORKING';   hasvalue: true )
        );
        );
 
 
        { switches being applied to all CPUs at the given level }
        { switches being applied to all CPUs at the given level }

+ 1 - 0
compiler/m68k/cpupara.pas

@@ -87,6 +87,7 @@ unit cpupara;
               loc:=LOC_REFERENCE;
               loc:=LOC_REFERENCE;
               reference.index:=NR_STACK_POINTER_REG;
               reference.index:=NR_STACK_POINTER_REG;
               reference.offset:=target_info.first_parm_offset+nr*4;
               reference.offset:=target_info.first_parm_offset+nr*4;
+              size:=OS_INT;
            end;
            end;
       end;
       end;
 
 

+ 8 - 8
compiler/m68k/n68kadd.pas

@@ -267,10 +267,10 @@ implementation
              begin
              begin
                 if nf_swapped in flags then
                 if nf_swapped in flags then
                   case nodetype of
                   case nodetype of
-                     ltn : getresflags:=F_GE;
-                     lten : getresflags:=F_G;
-                     gtn : getresflags:=F_LE;
-                     gten : getresflags:=F_L;
+                     ltn : getresflags:=F_G;
+                     lten : getresflags:=F_GE;
+                     gtn : getresflags:=F_L;
+                     gten : getresflags:=F_LE;
                   end
                   end
                 else
                 else
                   case nodetype of
                   case nodetype of
@@ -284,10 +284,10 @@ implementation
              begin
              begin
                 if nf_swapped in flags then
                 if nf_swapped in flags then
                   case nodetype of
                   case nodetype of
-                     ltn : getresflags:=F_AE;
-                     lten : getresflags:=F_A;
-                     gtn : getresflags:=F_BE;
-                     gten : getresflags:=F_B;
+                     ltn : getresflags:=F_A;
+                     lten : getresflags:=F_AE;
+                     gtn : getresflags:=F_B;
+                     gten : getresflags:=F_BE;
                   end
                   end
                 else
                 else
                   case nodetype of
                   case nodetype of

+ 1 - 1
compiler/mips/cpugas.pas

@@ -100,7 +100,7 @@ unit cpugas;
          { ABI selection }
          { ABI selection }
          Replace(result,'$ABI','-mabi='+abitypestr[mips_abi]);
          Replace(result,'$ABI','-mabi='+abitypestr[mips_abi]);
          { ARCH selection }
          { ARCH selection }
-         Replace(result,'$ARCH','-march='+cputypestr[mips_cpu]);
+         Replace(result,'$ARCH','-march='+lower(cputypestr[mips_cpu]));
       end;
       end;
 
 
 {****************************************************************************}
 {****************************************************************************}

+ 10 - 9
compiler/mips/cpuinfo.pas

@@ -77,16 +77,17 @@ Const
    ];
    ];
 
 
    { cpu strings as accepted by 
    { cpu strings as accepted by 
-     GNU assembler in -arch=XXX option }
+     GNU assembler in -arch=XXX option 
+     this ilist needs to be uppercased }
    cputypestr : array[tcputype] of string[8] = ('',
    cputypestr : array[tcputype] of string[8] = ('',
-     { cpu_mips_default } 'mips2',
-     { cpu_mips1        } 'mips1',
-     { cpu_mips2        } 'mips2',
-     { cpu_mips3        } 'mips3',
-     { cpu_mips4        } 'mips4',
-     { cpu_mips5        } 'mips5',
-     { cpu_mips32       } 'mips32',
-     { cpu_mips32r2     } 'mips32r2'
+     { cpu_mips_default } 'MIPS2',
+     { cpu_mips1        } 'MIPS1',
+     { cpu_mips2        } 'MIPS2',
+     { cpu_mips3        } 'MIPS3',
+     { cpu_mips4        } 'MIPS4',
+     { cpu_mips5        } 'MIPS5',
+     { cpu_mips32       } 'MIPS32',
+     { cpu_mips32r2     } 'MIPS32R2'
    );
    );
 
 
    mips_cpu : tcputype = cpu_mips_default;
    mips_cpu : tcputype = cpu_mips_default;

+ 16 - 3
compiler/msg/errore.msg

@@ -392,7 +392,7 @@ scan_w_setpeoptflags_not_support=02092_W_SETPEOPTFLAGS is not supported by the t
 #
 #
 # Parser
 # Parser
 #
 #
-# 03327 is the last used one
+# 03331 is the last used one
 #
 #
 % \section{Parser messages}
 % \section{Parser messages}
 % This section lists all parser messages. The parser takes care of the
 % This section lists all parser messages. The parser takes care of the
@@ -1385,8 +1385,8 @@ parser_e_no_destructor_in_records=03300_E_Destructors aren't allowed in records
 parser_e_class_methods_only_static_in_records=03301_E_Class methods must be static in records
 parser_e_class_methods_only_static_in_records=03301_E_Class methods must be static in records
 % Class methods declarations aren't allowed in records without static modifier.
 % Class methods declarations aren't allowed in records without static modifier.
 % Records have no inheritance and therefore non static class methods have no sence for them.
 % Records have no inheritance and therefore non static class methods have no sence for them.
-parser_e_no_constructor_in_records=03302_E_Constructors aren't allowed in records or record helpers
-% Constructor declarations aren't allowed in records or record helpers.
+parser_e_no_parameterless_constructor_in_records=03302_E_Parameterless constructors aren't allowed in records or record helpers
+% Constructor declarations with no arguments aren't allowed in records or record helpers.
 parser_e_at_least_one_argument_must_be_of_type=03303_E_Either the result or at least one parameter must be of type "$1"
 parser_e_at_least_one_argument_must_be_of_type=03303_E_Either the result or at least one parameter must be of type "$1"
 % It is required that either the result of the routine or at least one of its parameters be of the specified type.
 % It is required that either the result of the routine or at least one of its parameters be of the specified type.
 % For example class operators either take an instance of the structured type in which they are defined, or they return one.
 % For example class operators either take an instance of the structured type in which they are defined, or they return one.
@@ -1471,6 +1471,18 @@ parser_w_case_difference_auto_property_getter_setter_prefix=03327_W_Case mismatc
 % not can it add one using the correct case (it could conflict with the original declaration).
 % not can it add one using the correct case (it could conflict with the original declaration).
 % Manually correct the case of the getter/setter to conform to the desired coding rules.
 % Manually correct the case of the getter/setter to conform to the desired coding rules.
 % \var{TChild} overrides
 % \var{TChild} overrides
+parser_e_no_consts_in_local_anonymous_records=03328_E_Constants declarations are not allowed in local or anonymous records
+% Records with constants must be defined globally. Constants cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_no_methods_in_local_anonymous_records=03329_E_Method declarations are not allowed in local or anonymous records
+% Records with methods must be defined globally. Methods cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_no_properties_in_local_anonymous_records=03330_E_Property declarations are not allowed in local or anonymous records
+% Records with properties must be defined globally. Properties cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
+parser_e_no_class_in_local_anonymous_records=03331_E_Class memeber declarations are not allowed in local or anonymous records
+% Records with class members must be defined globally. Class members cannot be defined inside records which are defined in a
+% procedure or function or in anonymous records.
 %
 %
 % \end{description}
 % \end{description}
 %
 %
@@ -3614,6 +3626,7 @@ A*2WP<x>_Minimum iOS deployment version: 3.0, 5.0.1, ... (Darwin)
 A*2WR_Generate relocation code (Windows)
 A*2WR_Generate relocation code (Windows)
 P*2WT_Specify MPW tool type application (Classic Mac OS)
 P*2WT_Specify MPW tool type application (Classic Mac OS)
 **2WX_Enable executable stack (Linux)
 **2WX_Enable executable stack (Linux)
+A*2Wx_Generate thumb interworking safe code if possible
 **1X_Executable options:
 **1X_Executable options:
 **2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Linux)
 **2Xc_Pass --shared/-dynamic to the linker (BeOS, Darwin, FreeBSD, Linux)
 **2Xd_Do not search default library path (sometimes required for cross-compiling when not using -XR)
 **2Xd_Do not search default library path (sometimes required for cross-compiling when not using -XR)

+ 7 - 3
compiler/msgidx.inc

@@ -397,7 +397,7 @@ const
   parser_e_no_record_published=03299;
   parser_e_no_record_published=03299;
   parser_e_no_destructor_in_records=03300;
   parser_e_no_destructor_in_records=03300;
   parser_e_class_methods_only_static_in_records=03301;
   parser_e_class_methods_only_static_in_records=03301;
-  parser_e_no_constructor_in_records=03302;
+  parser_e_no_parameterless_constructor_in_records=03302;
   parser_e_at_least_one_argument_must_be_of_type=03303;
   parser_e_at_least_one_argument_must_be_of_type=03303;
   parser_e_cant_use_type_parameters_here=03304;
   parser_e_cant_use_type_parameters_here=03304;
   parser_e_externals_no_section=03305;
   parser_e_externals_no_section=03305;
@@ -423,6 +423,10 @@ const
   parser_e_cannot_generate_property_getter_setter=03325;
   parser_e_cannot_generate_property_getter_setter=03325;
   parser_w_overriding_property_getter_setter=03326;
   parser_w_overriding_property_getter_setter=03326;
   parser_w_case_difference_auto_property_getter_setter_prefix=03327;
   parser_w_case_difference_auto_property_getter_setter_prefix=03327;
+  parser_e_no_consts_in_local_anonymous_records=03328;
+  parser_e_no_methods_in_local_anonymous_records=03329;
+  parser_e_no_properties_in_local_anonymous_records=03330;
+  parser_e_no_class_in_local_anonymous_records=03331;
   type_e_mismatch=04000;
   type_e_mismatch=04000;
   type_e_incompatible_types=04001;
   type_e_incompatible_types=04001;
   type_e_not_equal_types=04002;
   type_e_not_equal_types=04002;
@@ -963,9 +967,9 @@ const
   option_info=11024;
   option_info=11024;
   option_help_pages=11025;
   option_help_pages=11025;
 
 
-  MsgTxtSize = 68093;
+  MsgTxtSize = 68471;
 
 
   MsgIdxMax : array[1..20] of longint=(
   MsgIdxMax : array[1..20] of longint=(
-    26,93,328,120,87,56,126,26,202,63,
+    26,93,332,120,87,56,126,26,202,63,
     54,20,1,1,1,1,1,1,1,1
     54,20,1,1,1,1,1,1,1,1
   );
   );

File diff suppressed because it is too large
+ 329 - 317
compiler/msgtxt.inc


+ 7 - 1
compiler/ncal.pas

@@ -23,6 +23,8 @@ unit ncal;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
 
 
+{ $define DEBUGINLINE}
+
 interface
 interface
 
 
     uses
     uses
@@ -2300,7 +2302,11 @@ implementation
           function call }
           function call }
         if not paramanager.ret_in_param(resultdef,procdefinition) then
         if not paramanager.ret_in_param(resultdef,procdefinition) then
           begin
           begin
-            result:=true;
+            { don't replace the function result if we are inlining and if the destination is complex, this
+              could lead to lengthy code in case the function result is used often and it is assigned e.g.
+              to a threadvar }
+            result:=not(cnf_do_inline in callnodeflags) or
+              (node_complexity(aktassignmentnode.left)<=1);
             exit;
             exit;
           end;
           end;
 
 

+ 0 - 2
compiler/ncgcal.pas

@@ -493,8 +493,6 @@ implementation
 
 
     procedure tcgcallnode.copy_back_paras;
     procedure tcgcallnode.copy_back_paras;
       var
       var
-        hp,
-        hp2 : tnode;
         ppn : tcallparanode;
         ppn : tcallparanode;
       begin
       begin
         ppn:=tcallparanode(left);
         ppn:=tcallparanode(left);

+ 2 - 2
compiler/ncgcnv.pas

@@ -513,9 +513,9 @@ interface
       end;
       end;
 
 
     procedure Tcgtypeconvnode.second_nil_to_methodprocvar;
     procedure Tcgtypeconvnode.second_nil_to_methodprocvar;
-
+    {$ifdef jvm}
     var r:Treference;
     var r:Treference;
-
+    {$endif}
     begin
     begin
 {$ifdef jvm}
 {$ifdef jvm}
 {$ifndef nounsupported}
 {$ifndef nounsupported}

+ 0 - 1
compiler/ncnv.pas

@@ -1996,7 +1996,6 @@ implementation
     function ttypeconvnode.typecheck_proc_to_procvar : tnode;
     function ttypeconvnode.typecheck_proc_to_procvar : tnode;
       var
       var
         pd : tabstractprocdef;
         pd : tabstractprocdef;
-        nestinglevel : byte;
       begin
       begin
         result:=nil;
         result:=nil;
         pd:=tabstractprocdef(left.resultdef);
         pd:=tabstractprocdef(left.resultdef);

+ 0 - 2
compiler/ngenutil.pas

@@ -264,7 +264,6 @@ implementation
       stat: tstatementnode;
       stat: tstatementnode;
       block: tnode;
       block: tnode;
       psym: tsym;
       psym: tsym;
-      tcinitproc: tprocdef;
     begin
     begin
       result:=maybe_insert_trashing(pd,n);
       result:=maybe_insert_trashing(pd,n);
       if target_info.system in systems_typed_constants_node_init then
       if target_info.system in systems_typed_constants_node_init then
@@ -291,7 +290,6 @@ implementation
                     if (psym.typ<>procsym) or
                     if (psym.typ<>procsym) or
                        (tprocsym(psym).procdeflist.count<>1) then
                        (tprocsym(psym).procdeflist.count<>1) then
                       internalerror(2011040301);
                       internalerror(2011040301);
-                    tcinitproc:=tprocdef(tprocsym(psym).procdeflist[0]);
                     addstatement(stat,ccallnode.create(nil,tprocsym(psym),
                     addstatement(stat,ccallnode.create(nil,tprocsym(psym),
                       pd.struct.symtable,nil,[]));
                       pd.struct.symtable,nil,[]));
                   end;
                   end;

+ 49 - 23
compiler/nmem.pas

@@ -168,30 +168,39 @@ implementation
         case left.resultdef.typ of
         case left.resultdef.typ of
           classrefdef :
           classrefdef :
             resultdef:=left.resultdef;
             resultdef:=left.resultdef;
-          objectdef,
-          recorddef:
-            { access to the classtype while specializing? }
-            if (df_generic in left.resultdef.defoptions) then
-              begin
-                defaultresultdef:=true;
-                if assigned(current_structdef) then
-                  begin
-                    if assigned(current_structdef.genericdef) then
-                      if current_structdef.genericdef=left.resultdef then
+          recorddef,
+          objectdef:
+            begin
+              if (left.resultdef.typ=objectdef) or
+                 ((target_info.system in systems_jvm) and
+                  (left.resultdef.typ=recorddef)) then
+                begin
+                  { access to the classtype while specializing? }
+                  if (df_generic in left.resultdef.defoptions) then
+                    begin
+                      defaultresultdef:=true;
+                      if assigned(current_structdef) then
                         begin
                         begin
-                          resultdef:=tclassrefdef.create(current_structdef);
-                          defaultresultdef:=false;
+                          if assigned(current_structdef.genericdef) then
+                            if current_structdef.genericdef=left.resultdef then
+                              begin
+                                resultdef:=tclassrefdef.create(current_structdef);
+                                defaultresultdef:=false;
+                              end
+                            else
+                              CGMessage(parser_e_cant_create_generics_of_this_type);
                         end
                         end
                       else
                       else
-                        CGMessage(parser_e_cant_create_generics_of_this_type);
-                  end
-                else
-                  message(parser_e_cant_create_generics_of_this_type);
-                if defaultresultdef then
-                  resultdef:=tclassrefdef.create(left.resultdef);
-              end
-            else
-              resultdef:=tclassrefdef.create(left.resultdef);
+                        message(parser_e_cant_create_generics_of_this_type);
+                      if defaultresultdef then
+                        resultdef:=tclassrefdef.create(left.resultdef);
+                    end
+                  else
+                    resultdef:=tclassrefdef.create(left.resultdef);
+                end
+              else
+                CGMessage(parser_e_pointer_to_class_expected);
+            end
           else
           else
             CGMessage(parser_e_pointer_to_class_expected);
             CGMessage(parser_e_pointer_to_class_expected);
         end;
         end;
@@ -467,6 +476,7 @@ implementation
          hp  : tnode;
          hp  : tnode;
          hsym : tfieldvarsym;
          hsym : tfieldvarsym;
          isprocvar : boolean;
          isprocvar : boolean;
+         offset: asizeint;
       begin
       begin
         result:=nil;
         result:=nil;
         typecheckpass(left);
         typecheckpass(left);
@@ -575,10 +585,26 @@ implementation
 {$endif i386}
 {$endif i386}
                (tabsolutevarsym(tloadnode(hp).symtableentry).abstyp=toaddr) then
                (tabsolutevarsym(tloadnode(hp).symtableentry).abstyp=toaddr) then
                begin
                begin
+                 offset:=tabsolutevarsym(tloadnode(hp).symtableentry).addroffset;
+                 hp:=left;
+                 while assigned(hp)and(hp.nodetype=subscriptn) do
+                   begin
+                     hsym:=tsubscriptnode(hp).vs;
+                     if tabstractrecordsymtable(hsym.owner).is_packed then
+                       begin
+                         { can't calculate the address of a non-byte aligned field }
+                         if (hsym.fieldoffset mod 8)<>0 then
+                           exit;
+                         inc(offset,hsym.fieldoffset div 8)
+                       end
+                     else
+                       inc(offset,hsym.fieldoffset);
+                     hp:=tunarynode(hp).left;
+                   end;
                  if nf_typedaddr in flags then
                  if nf_typedaddr in flags then
-                   result:=cpointerconstnode.create(tabsolutevarsym(tloadnode(hp).symtableentry).addroffset,getpointerdef(left.resultdef))
+                   result:=cpointerconstnode.create(offset,getpointerdef(left.resultdef))
                  else
                  else
-                   result:=cpointerconstnode.create(tabsolutevarsym(tloadnode(hp).symtableentry).addroffset,voidpointertype);
+                   result:=cpointerconstnode.create(offset,voidpointertype);
                  exit;
                  exit;
                end
                end
               else if (nf_internal in flags) or
               else if (nf_internal in flags) or

+ 33 - 2
compiler/nset.pas

@@ -98,6 +98,7 @@ interface
           procedure buildderefimpl;override;
           procedure buildderefimpl;override;
           procedure derefimpl;override;
           procedure derefimpl;override;
           function dogetcopy : tnode;override;
           function dogetcopy : tnode;override;
+          procedure printnodetree(var t:text);override;
           procedure insertintolist(l : tnodelist);override;
           procedure insertintolist(l : tnodelist);override;
           function pass_typecheck:tnode;override;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
           function pass_1 : tnode;override;
@@ -829,7 +830,6 @@ implementation
 
 
 
 
     function tcasenode.dogetcopy : tnode;
     function tcasenode.dogetcopy : tnode;
-
       var
       var
          n : tcasenode;
          n : tcasenode;
          i : longint;
          i : longint;
@@ -858,11 +858,42 @@ implementation
          dogetcopy:=n;
          dogetcopy:=n;
       end;
       end;
 
 
-    procedure tcasenode.insertintolist(l : tnodelist);
 
 
+    procedure tcasenode.printnodetree(var t: text);
+      var
+        i : longint;
+      begin
+        write(t,printnodeindention,'(');
+        printnodeindent;
+        printnodeinfo(t);
+        writeln(t);
+        printnode(t,left);
+        for i:=0 to blocks.count-1 do
+          begin
+            writeln(t,printnodeindention,'(caseblock blockid: ',i);
+            printnodeindent;
+            printnode(t,pcaseblock(blocks[i])^.statement);
+            printnodeunindent;
+            writeln(t,printnodeindention,')');
+          end;
+        if assigned(elseblock) then
+          begin
+            writeln(t,printnodeindention,'(else: ',i);
+            printnodeindent;
+            printnode(t,elseblock);
+            printnodeunindent;
+            writeln(t,printnodeindention,')');
+          end;
+        printnodeunindent;
+        writeln(t,printnodeindention,')');
+      end;
+
+
+    procedure tcasenode.insertintolist(l : tnodelist);
       begin
       begin
       end;
       end;
 
 
+
     function caselabelsequal(n1,n2: pcaselabel): boolean;
     function caselabelsequal(n1,n2: pcaselabel): boolean;
       begin
       begin
         result :=
         result :=

+ 1 - 1
compiler/optcse.pas

@@ -133,7 +133,7 @@ unit optcse;
         end;
         end;
 
 
       var
       var
-        i,j : longint;
+        i : longint;
       begin
       begin
         result:=fen_false;
         result:=fen_false;
         { don't add the tree below an untyped const parameter: there is
         { don't add the tree below an untyped const parameter: there is

+ 14 - 2
compiler/options.pas

@@ -1917,7 +1917,19 @@ begin
                           end
                           end
                         else
                         else
                           IllegalPara(opt);
                           IllegalPara(opt);
-                      end
+                      end;
+                    'x':
+                      begin
+                        if target_info.cpu=systems.cpu_arm then
+                          begin
+                            if UnsetBool(More, j, opt, false) then
+                              exclude(init_settings.targetswitches,ts_thumb_interworking)
+                            else
+                              include(init_settings.targetswitches,ts_thumb_interworking);
+                          end
+                        else
+                          IllegalPara(opt);
+                      end;
                     else
                     else
                       IllegalPara(opt);
                       IllegalPara(opt);
                   end;
                   end;
@@ -2726,8 +2738,8 @@ var
   abi : tabi;
   abi : tabi;
 {$if defined(arm) or defined(avr)}
 {$if defined(arm) or defined(avr)}
   cpuflag : tcpuflags;
   cpuflag : tcpuflags;
-{$endif defined(arm) or defined(avr)}
   hs : string;
   hs : string;
+{$endif defined(arm) or defined(avr)}
 begin
 begin
   option:=coption.create;
   option:=coption.create;
   disable_configfile:=false;
   disable_configfile:=false;

+ 7 - 1
compiler/pdecl.pas

@@ -839,7 +839,13 @@ implementation
         consume(_THREADVAR);
         consume(_THREADVAR);
         if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
         if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
           message(parser_e_threadvars_only_sg);
           message(parser_e_threadvars_only_sg);
-        read_var_decls([vd_threadvar]);
+        if f_threading in features then
+          read_var_decls([vd_threadvar])
+        else
+          begin
+            Message(parser_f_unsupported_feature);
+            read_var_decls([]);
+          end;
       end;
       end;
 
 
 
 

+ 10 - 6
compiler/pdecobj.pas

@@ -901,11 +901,7 @@ implementation
               if is_objectpascal_helper(astruct) then
               if is_objectpascal_helper(astruct) then
                 if is_classdef then
                 if is_classdef then
                   { class constructors are not allowed in class helpers }
                   { class constructors are not allowed in class helpers }
-                  Message(parser_e_no_class_constructor_in_helpers)
-                else if is_record(tobjectdef(astruct).extendeddef) then
-                  { as long as constructors aren't allowed in records they
-                    aren't allowed in helpers either }
-                  Message(parser_e_no_constructor_in_records);
+                  Message(parser_e_no_class_constructor_in_helpers);
 
 
               { only 1 class constructor is allowed }
               { only 1 class constructor is allowed }
               if is_classdef and (oo_has_class_constructor in astruct.objectoptions) then
               if is_classdef and (oo_has_class_constructor in astruct.objectoptions) then
@@ -916,7 +912,15 @@ implementation
               if is_classdef then
               if is_classdef then
                 result:=class_constructor_head(current_structdef)
                 result:=class_constructor_head(current_structdef)
               else
               else
-                result:=constructor_head;
+                begin
+                  result:=constructor_head;
+                  if is_objectpascal_helper(astruct) and
+                     is_record(tobjectdef(astruct).extendeddef) and
+                     (result.minparacount=0) then
+                      { as long as parameterless constructors aren't allowed in records they
+                       aren't allowed in helpers either }
+                    MessagePos(result.procsym.fileinfo,parser_e_no_parameterless_constructor_in_records);
+                end;
 
 
               chkcpp(result);
               chkcpp(result);
 
 

+ 8 - 3
compiler/pexpr.pas

@@ -226,7 +226,6 @@ implementation
          hdef  : tdef;
          hdef  : tdef;
          temp  : ttempcreatenode;
          temp  : ttempcreatenode;
          newstatement : tstatementnode;
          newstatement : tstatementnode;
-         procinfo : tprocinfo;
        begin
        begin
          { Properties are not allowed, because the write can
          { Properties are not allowed, because the write can
            be different from the read }
            be different from the read }
@@ -923,7 +922,10 @@ implementation
                begin
                begin
                  { We are calling from the static class method which has no self node }
                  { We are calling from the static class method which has no self node }
                  if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
                  if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
-                   p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
+                   if st.symtabletype=recordsymtable then
+                     p1:=ctypenode.create(current_procinfo.procdef.struct)
+                   else
+                     p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
                  else
                  else
                    p1:=load_self_node;
                    p1:=load_self_node;
                  { We are calling a member }
                  { We are calling a member }
@@ -2445,7 +2447,10 @@ implementation
                           if assigned(current_structdef) and
                           if assigned(current_structdef) and
                               (((current_structdef<>hdef) and is_owned_by(current_structdef,hdef)) or
                               (((current_structdef<>hdef) and is_owned_by(current_structdef,hdef)) or
                                (sp_static in srsym.symoptions)) then
                                (sp_static in srsym.symoptions)) then
-                            p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
+                            if srsymtable.symtabletype=recordsymtable then
+                              p1:=ctypenode.create(hdef)
+                            else
+                              p1:=cloadvmtaddrnode.create(ctypenode.create(hdef))
                           else
                           else
                           if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
                           if assigned(current_procinfo) and current_procinfo.procdef.no_self_node then
                             p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))
                             p1:=cloadvmtaddrnode.create(ctypenode.create(current_procinfo.procdef.struct))

+ 1 - 1
compiler/pmodules.pas

@@ -1011,7 +1011,7 @@ type
         force_init_final : boolean;
         force_init_final : boolean;
         init_procinfo,
         init_procinfo,
         finalize_procinfo : tcgprocinfo;
         finalize_procinfo : tcgprocinfo;
-        i,idx : longint;
+        i : longint;
         ag : boolean;
         ag : boolean;
         finishstate : tfinishstate;
         finishstate : tfinishstate;
         globalstate : tglobalstate;
         globalstate : tglobalstate;

+ 5 - 1
compiler/psub.pas

@@ -493,7 +493,11 @@ implementation
                        end;
                        end;
                     end
                     end
                 else
                 else
-                  if not is_record(current_structdef) then
+                  if not is_record(current_structdef) and
+                     not (
+                            is_objectpascal_helper(current_structdef) and
+                            is_record(tobjectdef(current_structdef).extendeddef)
+                          ) then
                     internalerror(200305103);
                     internalerror(200305103);
                 { if self=nil then exit
                 { if self=nil then exit
                   calling fail instead of exit is useless because
                   calling fail instead of exit is useless because

+ 28 - 3
compiler/ptype.pas

@@ -520,6 +520,13 @@ implementation
 
 
 
 
     procedure parse_record_members;
     procedure parse_record_members;
+
+      function IsAnonOrLocal: Boolean;
+        begin
+          result:=(current_structdef.objname^='') or
+                  not(symtablestack.stack^.next^.symtable.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]);
+        end;
+
       var
       var
         pd : tprocdef;
         pd : tprocdef;
         oldparse_only: boolean;
         oldparse_only: boolean;
@@ -544,8 +551,7 @@ implementation
                 member_blocktype:=bt_type;
                 member_blocktype:=bt_type;
 
 
                 { local and anonymous records can not have inner types. skip top record symtable }
                 { local and anonymous records can not have inner types. skip top record symtable }
-                if (current_structdef.objname^='') or
-                   not(symtablestack.stack^.next^.symtable.symtabletype in [globalsymtable,staticsymtable,objectsymtable,recordsymtable]) then
+                if IsAnonOrLocal then
                   Message(parser_e_no_types_in_local_anonymous_records);
                   Message(parser_e_no_types_in_local_anonymous_records);
               end;
               end;
             _VAR :
             _VAR :
@@ -560,6 +566,10 @@ implementation
               begin
               begin
                 consume(_CONST);
                 consume(_CONST);
                 member_blocktype:=bt_const;
                 member_blocktype:=bt_const;
+
+                { local and anonymous records can not have constants. skip top record symtable }
+                if IsAnonOrLocal then
+                  Message(parser_e_no_consts_in_local_anonymous_records);
               end;
               end;
             _ID, _CASE, _OPERATOR :
             _ID, _CASE, _OPERATOR :
               begin
               begin
@@ -661,6 +671,8 @@ implementation
               end;
               end;
             _PROPERTY :
             _PROPERTY :
               begin
               begin
+                if IsAnonOrLocal then
+                  Message(parser_e_no_properties_in_local_anonymous_records);
                 struct_property_dec(is_classdef);
                 struct_property_dec(is_classdef);
                 fields_allowed:=false;
                 fields_allowed:=false;
                 is_classdef:=false;
                 is_classdef:=false;
@@ -676,17 +688,24 @@ implementation
                    not((token=_ID) and (idtoken=_OPERATOR)) then
                    not((token=_ID) and (idtoken=_OPERATOR)) then
                   Message(parser_e_procedure_or_function_expected);
                   Message(parser_e_procedure_or_function_expected);
 
 
+                if IsAnonOrLocal then
+                  Message(parser_e_no_class_in_local_anonymous_records);
+
                 is_classdef:=true;
                 is_classdef:=true;
               end;
               end;
             _PROCEDURE,
             _PROCEDURE,
             _FUNCTION:
             _FUNCTION:
               begin
               begin
+                if IsAnonOrLocal then
+                  Message(parser_e_no_methods_in_local_anonymous_records);
                 pd:=parse_record_method_dec(current_structdef,is_classdef);
                 pd:=parse_record_method_dec(current_structdef,is_classdef);
                 fields_allowed:=false;
                 fields_allowed:=false;
                 is_classdef:=false;
                 is_classdef:=false;
               end;
               end;
             _CONSTRUCTOR :
             _CONSTRUCTOR :
               begin
               begin
+                if IsAnonOrLocal then
+                  Message(parser_e_no_methods_in_local_anonymous_records);
                 if not is_classdef and (current_structdef.symtable.currentvisibility <> vis_public) then
                 if not is_classdef and (current_structdef.symtable.currentvisibility <> vis_public) then
                   Message(parser_w_constructor_should_be_public);
                   Message(parser_w_constructor_should_be_public);
 
 
@@ -699,7 +718,11 @@ implementation
                 if is_classdef then
                 if is_classdef then
                   pd:=class_constructor_head(current_structdef)
                   pd:=class_constructor_head(current_structdef)
                 else
                 else
-                  pd:=constructor_head;
+                  begin
+                    pd:=constructor_head;
+                    if pd.minparacount = 0 then
+                      MessagePos(pd.procsym.fileinfo,parser_e_no_parameterless_constructor_in_records);
+                  end;
 
 
                 parse_only:=oldparse_only;
                 parse_only:=oldparse_only;
                 fields_allowed:=false;
                 fields_allowed:=false;
@@ -707,6 +730,8 @@ implementation
               end;
               end;
             _DESTRUCTOR :
             _DESTRUCTOR :
               begin
               begin
+                if IsAnonOrLocal then
+                  Message(parser_e_no_methods_in_local_anonymous_records);
                 if not is_classdef then
                 if not is_classdef then
                   Message(parser_e_no_destructor_in_records);
                   Message(parser_e_no_destructor_in_records);
 
 

+ 1 - 0
compiler/scanner.pas

@@ -933,6 +933,7 @@ In case not, the value returned can be arbitrary.
            setElemType : TCTETypeSet;
            setElemType : TCTETypeSet;
 
 
         begin
         begin
+           read_factor:='';
            if current_scanner.preproc_token=_ID then
            if current_scanner.preproc_token=_ID then
              begin
              begin
                 if current_scanner.preproc_pattern='DEFINED' then
                 if current_scanner.preproc_pattern='DEFINED' then

+ 8 - 5
compiler/symtable.pas

@@ -1023,7 +1023,7 @@ implementation
 
 
     procedure tabstractrecordsymtable.addfieldlist(list: tfpobjectlist; maybereorder: boolean);
     procedure tabstractrecordsymtable.addfieldlist(list: tfpobjectlist; maybereorder: boolean);
       var
       var
-        fieldvs, insertfieldvs, bestfieldvs: tfieldvarsym;
+        fieldvs, insertfieldvs: tfieldvarsym;
         base, fieldoffset, space, insertfieldsize, insertfieldoffset, bestinsertfieldoffset, bestspaceleft: asizeint;
         base, fieldoffset, space, insertfieldsize, insertfieldoffset, bestinsertfieldoffset, bestspaceleft: asizeint;
         i, j, bestfieldindex: longint;
         i, j, bestfieldindex: longint;
         globalfieldalignment,
         globalfieldalignment,
@@ -1955,9 +1955,14 @@ implementation
         while assigned(symtable) and (symtable.symtabletype in [ObjectSymtable,recordsymtable]) do
         while assigned(symtable) and (symtable.symtabletype in [ObjectSymtable,recordsymtable]) do
           begin
           begin
             if (result='') then
             if (result='') then
-              result:=symtable.name^
+              if symtable.name<>nil then
+                result:=symtable.name^
+              else
             else
             else
-              result:=symtable.name^+delimiter+result;
+              if symtable.name<>nil then
+                result:=symtable.name^+delimiter+result
+              else
+                result:=delimiter+result;
             symtable:=symtable.defowner.owner;
             symtable:=symtable.defowner.owner;
           end;
           end;
       end;
       end;
@@ -2986,7 +2991,6 @@ implementation
     function  search_system_proc(const s: TIDString): tprocdef;
     function  search_system_proc(const s: TIDString): tprocdef;
       var
       var
         srsym: tsym;
         srsym: tsym;
-        pd: tprocdef;
       begin
       begin
         srsym:=tsym(systemunit.find(s));
         srsym:=tsym(systemunit.find(s));
         if not assigned(srsym) and
         if not assigned(srsym) and
@@ -3233,7 +3237,6 @@ implementation
     function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
     function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
     { searches n in symtable of pd and all anchestors }
     { searches n in symtable of pd and all anchestors }
       var
       var
-        srsym      : tsym;
         srsymtable : tsymtable;
         srsymtable : tsymtable;
       begin
       begin
         { in case this is a formal class, first find the real definition }
         { in case this is a formal class, first find the real definition }

+ 8 - 13
compiler/x86/itx86int.pas

@@ -60,22 +60,17 @@ implementation
 
 
     function findreg_by_intname(const s:string):integer;
     function findreg_by_intname(const s:string):integer;
       var
       var
-        i,p : integer;
-        s1: string;
-
         l,r,m: integer;
         l,r,m: integer;
       begin
       begin
         {Binary search.}
         {Binary search.}
-        p:=0;
-        i := (high(tregisterindex) + 1) shr 1;
-           l := 0;
-           r := high(tregisterindex) + 1;
-           while l < r do
-           begin
-              m := (l + r) div 2;
-              if int_regname_table[int_regname_index[m]] < s then l := m + 1
-              else r := m;
-           end;
+        l := 0;
+        r := high(tregisterindex) + 1;
+        while l < r do
+          begin
+            m := (l + r) div 2;
+            if int_regname_table[int_regname_index[m]] < s then l := m + 1
+            else r := m;
+          end;
 
 
         if int_regname_table[int_regname_index[r]]=s then
         if int_regname_table[int_regname_index[r]]=s then
           findreg_by_intname:=int_regname_index[r]
           findreg_by_intname:=int_regname_index[r]

+ 0 - 1
compiler/x86/rax86.pas

@@ -345,7 +345,6 @@ var
   memrefsize: integer;
   memrefsize: integer;
   memopsize: integer;
   memopsize: integer;
   memoffset: asizeint;
   memoffset: asizeint;
-  s1: string;
 begin
 begin
   ExistsMemRefNoSize := false;
   ExistsMemRefNoSize := false;
   ExistsMemRef       := false;
   ExistsMemRef       := false;

+ 5 - 2
compiler/x86_64/cpuelf.pas

@@ -212,8 +212,11 @@ implementation
         R_X86_64_PLTOFF64,
         R_X86_64_PLTOFF64,
         R_X86_64_GOTPLT64:
         R_X86_64_GOTPLT64:
           begin
           begin
-            objsym:=ObjReloc.symbol.exesymbol.ObjSymbol;
-            objsym.refs:=objsym.refs or symref_plt;
+            if assigned(ObjReloc.symbol) and assigned(ObjReloc.symbol.exesymbol) then
+              begin
+                objsym:=ObjReloc.symbol.exesymbol.ObjSymbol;
+                objsym.refs:=objsym.refs or symref_plt;
+              end;
           end;
           end;
       end;
       end;
 
 

+ 23 - 3
packages/fcl-db/src/codegen/fpcgtiopf.pp

@@ -30,7 +30,13 @@ TYpe
   TVisitorOption = (voRead,voReadList,voCreate,voDelete,voUpdate,
   TVisitorOption = (voRead,voReadList,voCreate,voDelete,voUpdate,
                     voCommonSetupParams,voSingleSaveVisitor,voRegisterVisitors);
                     voCommonSetupParams,voSingleSaveVisitor,voRegisterVisitors);
   TVisitorOptions = set of TVisitorOption;
   TVisitorOptions = set of TVisitorOption;
-  
+
+  { TTiOPFFieldPropDef }
+
+  TTiOPFFieldPropDef = Class(TFieldPropDef)
+  Public
+    Constructor Create(ACollection : TCollection); override;
+  end;
   { TTiOPFCodeOptions }
   { TTiOPFCodeOptions }
 
 
   TTiOPFCodeOptions = Class (TClassCodeGeneratorOptions)
   TTiOPFCodeOptions = Class (TClassCodeGeneratorOptions)
@@ -100,6 +106,7 @@ TYpe
     // Not to be overridden.
     // Not to be overridden.
     procedure WriteListAddObject(Strings: TStrings; const ListClassName, ObjectClassName: String);
     procedure WriteListAddObject(Strings: TStrings; const ListClassName, ObjectClassName: String);
     // Overrides of parent objects
     // Overrides of parent objects
+    Function CreateFieldPropDefs : TFieldPropDefs; override;
     function AllowPropertyDeclaration(F: TFieldPropDef; AVisibility: TVisibilities): Boolean; override;
     function AllowPropertyDeclaration(F: TFieldPropDef; AVisibility: TVisibilities): Boolean; override;
     Function GetInterfaceUsesClause : string; override;
     Function GetInterfaceUsesClause : string; override;
     procedure WriteVisibilityStart(V: TVisibility; Strings: TStrings); override;
     procedure WriteVisibilityStart(V: TVisibility; Strings: TStrings); override;
@@ -134,6 +141,14 @@ begin
     Delete(Result,1,1);
     Delete(Result,1,1);
 end;
 end;
 
 
+{ TTiOPFFieldPropDef }
+
+constructor TTiOPFFieldPropDef.Create(ACollection: TCollection);
+begin
+  inherited Create(ACollection);
+  PropSetters:=[psWrite];
+end;
+
 { TTiOPFCodeOptions }
 { TTiOPFCodeOptions }
 
 
 function TTiOPFCodeOptions.GetListClassName: String;
 function TTiOPFCodeOptions.GetListClassName: String;
@@ -872,7 +887,7 @@ begin
       ptSingle, ptDouble, ptExtended, ptComp :
       ptSingle, ptDouble, ptExtended, ptComp :
         S:='AsFloat';
         S:='AsFloat';
       ptCurrency :
       ptCurrency :
-        S:='AsCurrency';
+        S:='AsFloat';
       ptDateTime :
       ptDateTime :
         S:='AsDateTime';
         S:='AsDateTime';
       ptEnumerated :
       ptEnumerated :
@@ -1139,7 +1154,7 @@ begin
       AddLn(Strings,'Public');
       AddLn(Strings,'Public');
     IncIndent;
     IncIndent;
     Try
     Try
-      AddLn(Strings,'Property Items[Index : Integer] : %s Read GetObj Write SetObj; Default;',[ObjectClassname]);
+      AddLn(Strings,'Property Items[AIndex : Integer] : %s Read GetObj Write SetObj; Default;',[ObjectClassname]);
     Finally
     Finally
       DecIndent;
       DecIndent;
     end;
     end;
@@ -1178,6 +1193,11 @@ begin
    Addln(Strings);
    Addln(Strings);
 end;
 end;
 
 
+function TTiOPFCodeGenerator.CreateFieldPropDefs: TFieldPropDefs;
+begin
+  Result:=TFieldPropDefs.Create(TTiOPFFieldPropDef);
+end;
+
 function TTiOPFCodeGenerator.AllowPropertyDeclaration(F: TFieldPropDef;
 function TTiOPFCodeGenerator.AllowPropertyDeclaration(F: TFieldPropDef;
   AVisibility: TVisibilities): Boolean;
   AVisibility: TVisibilities): Boolean;
 begin
 begin

+ 33 - 8
packages/fcl-db/src/codegen/fpddcodegen.pp

@@ -38,6 +38,8 @@ Type
   TVisibility = (vPrivate,vProtected,vPublic,vPublished);
   TVisibility = (vPrivate,vProtected,vPublic,vPublished);
   TVisibilities = Set of TVisibility;
   TVisibilities = Set of TVisibility;
   TPropAccess = (paReadWrite,paReadonly,paWriteonly);
   TPropAccess = (paReadWrite,paReadonly,paWriteonly);
+  TPropSetter = (psRead,psWrite);
+  TPropSetters = set of TPropSetter;
 
 
 
 
   TFieldPropDefs = Class;
   TFieldPropDefs = Class;
@@ -51,6 +53,7 @@ Type
     FFieldType: TFieldType;
     FFieldType: TFieldType;
     FPropAccess: TPropAccess;
     FPropAccess: TPropAccess;
     FPropDef: String;
     FPropDef: String;
+    FPropSetters: TPropSetters;
     FPropType : TPropType;
     FPropType : TPropType;
     FPRopSize: Integer;
     FPRopSize: Integer;
     FPropName : String;
     FPropName : String;
@@ -66,8 +69,8 @@ Type
     Constructor Create(ACollection : TCollection) ; override;
     Constructor Create(ACollection : TCollection) ; override;
     Procedure Assign(ASource : TPersistent); override;
     Procedure Assign(ASource : TPersistent); override;
     Function FieldPropDefs : TFieldPropDefs;
     Function FieldPropDefs : TFieldPropDefs;
-    Function HasGetter : Boolean; Virtual; // Always false.
-    Function HasSetter : Boolean; Virtual; // True for streams/strings
+    Function HasGetter : Boolean; Virtual; // Checks Propsetters for psRead
+    Function HasSetter : Boolean; Virtual; // True for streams/strings or if Propsetters has pswrite
     Function ObjPasTypeDef : String; virtual; // Object pascal definition of type
     Function ObjPasTypeDef : String; virtual; // Object pascal definition of type
     Function ObjPasReadDef : String; virtual; // Object pascal definition of getter
     Function ObjPasReadDef : String; virtual; // Object pascal definition of getter
     Function ObjPasWriteDef : String; virtual; // Object pascal definition of setter
     Function ObjPasWriteDef : String; virtual; // Object pascal definition of setter
@@ -81,6 +84,7 @@ Type
     Property PropertyDef : String Read FPropDef Write FPropDef;
     Property PropertyDef : String Read FPropDef Write FPropDef;
     Property PropertyVisibility : TVisibility Read FPropVis Write FPropVis;
     Property PropertyVisibility : TVisibility Read FPropVis Write FPropVis;
     Property PropertyAccess : TPropAccess Read FPropAccess Write FPropAccess;
     Property PropertyAccess : TPropAccess Read FPropAccess Write FPropAccess;
+    Property PropSetters : TPropSetters Read FPropSetters Write FPropSetters;
   end;
   end;
   
   
   { TFieldPropDefs }
   { TFieldPropDefs }
@@ -113,6 +117,7 @@ Type
     FInterfaceUnits: String;
     FInterfaceUnits: String;
     FOptions: TCodeOptions;
     FOptions: TCodeOptions;
     FUnitName: String;
     FUnitName: String;
+    FExtraSetterLine : string;
     procedure SetImplementationUnits(const AValue: String);
     procedure SetImplementationUnits(const AValue: String);
     procedure SetInterfaceUnits(const AValue: String);
     procedure SetInterfaceUnits(const AValue: String);
     procedure SetUnitname(const AValue: String);
     procedure SetUnitname(const AValue: String);
@@ -122,9 +127,15 @@ Type
     Constructor create; virtual;
     Constructor create; virtual;
     Procedure Assign(ASource : TPersistent); override;
     Procedure Assign(ASource : TPersistent); override;
   Published
   Published
+    // Line of code that will be added to each property setter. Use %PROPNAME% to include property name in the line.
+    Property ExtraSetterLine : String Read FExtraSetterLine Write FExtraSetterLine;
+    // options
     Property Options : TCodeOptions Read FOptions Write SetOPtions;
     Property Options : TCodeOptions Read FOptions Write SetOPtions;
+    // Name of unit if a unit is generated.
     Property UnitName : String Read FUnitName Write SetUnitname;
     Property UnitName : String Read FUnitName Write SetUnitname;
+    // Comma-separated list of  units that will be put in the interface units clause
     Property InterfaceUnits : String Read FInterfaceUnits Write SetInterfaceUnits;
     Property InterfaceUnits : String Read FInterfaceUnits Write SetInterfaceUnits;
+    //  Comma-separated list of  units that will be put in the implementation units clause
     Property ImplementationUnits : String Read FImplementationUnits Write SetImplementationUnits;
     Property ImplementationUnits : String Read FImplementationUnits Write SetImplementationUnits;
   end;
   end;
   TCodeGeneratorOptionsClass = Class of TCodeGeneratorOptions;
   TCodeGeneratorOptionsClass = Class of TCodeGeneratorOptions;
@@ -539,13 +550,13 @@ end;
 
 
 function TFieldPropDef.HasGetter: Boolean;
 function TFieldPropDef.HasGetter: Boolean;
 begin
 begin
-  Result:=False;
+  Result:=psRead in PropSetters;
 end;
 end;
 
 
 function TFieldPropDef.HasSetter: Boolean;
 function TFieldPropDef.HasSetter: Boolean;
 begin
 begin
   Result:=(PropertyAccess in [paReadWrite,paWriteOnly])
   Result:=(PropertyAccess in [paReadWrite,paWriteOnly])
-          and (PropertyType in [ptStream,ptTStrings]);
+          and ((PropertyType in [ptStream,ptTStrings]) or (psWrite in Propsetters));
 end;
 end;
 
 
 function TFieldPropDef.ObjPasTypeDef: String;
 function TFieldPropDef.ObjPasTypeDef: String;
@@ -832,7 +843,7 @@ begin
   For I:=0 to Fields.Count-1 do
   For I:=0 to Fields.Count-1 do
     begin
     begin
     F:=Fields[i];
     F:=Fields[i];
-    if AllowPropertyDeclaration(F,[]) and F.HasGetter then
+    if AllowPropertyDeclaration(F,[]) and F.HasSetter then
       begin
       begin
       If not B then
       If not B then
         begin
         begin
@@ -867,22 +878,33 @@ Procedure TDDClassCodeGenerator.WritePropertySetterImpl(Strings : TStrings; F :
 
 
 Var
 Var
   S : String;
   S : String;
+  L : Integer;
 
 
 begin
 begin
-  S:=PropertyGetterDeclaration(F,True);
+  S:=PropertySetterDeclaration(F,True);
   BeginMethod(Strings,S);
   BeginMethod(Strings,S);
   AddLn(Strings,'begin');
   AddLn(Strings,'begin');
   IncIndent;
   IncIndent;
   Try
   Try
+    AddLn(Strings,Format('if (F%s=AValue) then exit;',[F.PropertyName]));
     Case F.PropertyType of
     Case F.PropertyType of
       ptTStrings :
       ptTStrings :
         S:=Format('F%s.Assign(AValue);',[F.PropertyName]);
         S:=Format('F%s.Assign(AValue);',[F.PropertyName]);
       ptStream :
       ptStream :
         S:=Format('F%s.CopyFrom(AValue,0);',[F.PropertyName]);
         S:=Format('F%s.CopyFrom(AValue,0);',[F.PropertyName]);
     else
     else
-       S:=Format('F%s:=AValue',[F.PropertyName]);
+       S:=Format('F%s:=AValue;',[F.PropertyName]);
     end;
     end;
     AddLn(Strings,S);
     AddLn(Strings,S);
+    S:=CodeOptions.ExtraSetterLine;
+    L:=Length(S);
+    if (L>0) then
+      begin
+      S:=StringReplace(S,'%PROPNAME%',F.PropertyName,[rfReplaceAll,rfIgnoreCase]);
+      if (S[L]<>';') then
+        S:=S+';';
+      AddLn(Strings,S);  
+      end;
   Finally
   Finally
     DecIndent;
     DecIndent;
   end;
   end;
@@ -1093,7 +1115,7 @@ begin
   Result:='Procedure ';
   Result:='Procedure ';
   If Impl then
   If Impl then
     Result:=Result+ClassOptions.ObjectClassName+'.';
     Result:=Result+ClassOptions.ObjectClassName+'.';
-  Result:=Result+Def.ObjPasReadDef+' (AValue  : '+Def.ObjPasTypeDef+');';
+  Result:=Result+Def.ObjPasWriteDef+' (AValue  : '+Def.ObjPasTypeDef+');';
 end;
 end;
 
 
 function TDDClassCodeGenerator.NeedsConstructor: Boolean;
 function TDDClassCodeGenerator.NeedsConstructor: Boolean;
@@ -1478,8 +1500,11 @@ begin
   If ASource is TCodeGeneratorOptions then
   If ASource is TCodeGeneratorOptions then
     begin
     begin
     CG:=ASource as TCodeGeneratorOptions;
     CG:=ASource as TCodeGeneratorOptions;
+    FInterfaceUnits:=CG.InterfaceUnits;
+    FImplementationUnits:=CG.ImplementationUnits;
     FOptions:=CG.FOptions;
     FOptions:=CG.FOptions;
     FUnitName:=CG.UnitName;
     FUnitName:=CG.UnitName;
+    FExtraSetterLine:=CG.ExtraSetterLine;
     end
     end
   else
   else
     inherited Assign(ASource);
     inherited Assign(ASource);

+ 5 - 2
packages/fcl-db/src/sqldb/postgres/pqconnection.pp

@@ -1077,6 +1077,9 @@ function TPQConnection.GetSchemaInfoSQL(SchemaType: TSchemaType;
 var s : string;
 var s : string;
 
 
 begin
 begin
+  // select * from information_schema.tables with 
+  // where table_schema [not] in ('pg_catalog','information_schema') may be better.
+  // But the following should work:
   case SchemaType of
   case SchemaType of
     stTables     : s := 'select '+
     stTables     : s := 'select '+
                           'relfilenode        as recno, '+
                           'relfilenode        as recno, '+
@@ -1086,7 +1089,7 @@ begin
                           '0                  as table_type '+
                           '0                  as table_type '+
                         'from pg_class c '+
                         'from pg_class c '+
                           'left join pg_namespace n on c.relnamespace=n.oid '+
                           'left join pg_namespace n on c.relnamespace=n.oid '+
-                        'where relkind=''r''' +
+                        'where (relkind=''r'') and not (nspname in (''pg_catalog'',''information_schema''))' +
                         'order by relname';
                         'order by relname';
 
 
     stSysTables  : s := 'select '+
     stSysTables  : s := 'select '+
@@ -1097,7 +1100,7 @@ begin
                           '0                  as table_type '+
                           '0                  as table_type '+
                         'from pg_class c '+
                         'from pg_class c '+
                           'left join pg_namespace n on c.relnamespace=n.oid '+
                           'left join pg_namespace n on c.relnamespace=n.oid '+
-                        'where relkind=''r'' and nspname=''pg_catalog'' ' + // only system tables
+                        'where (relkind=''r'') and nspname in ((''pg_catalog'',''information_schema'')) ' + // only system tables
                         'order by relname';
                         'order by relname';
     stColumns    : s := 'select '+
     stColumns    : s := 'select '+
                           'a.attnum           as recno, '+
                           'a.attnum           as recno, '+

+ 2 - 1
packages/fcl-db/src/sqldb/sqldb.pp

@@ -278,6 +278,7 @@ type
     procedure SetReadOnly(AValue : Boolean); override;
     procedure SetReadOnly(AValue : Boolean); override;
     Function LogEvent(EventType : TDBEventType) : Boolean;
     Function LogEvent(EventType : TDBEventType) : Boolean;
     Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
     Procedure Log(EventType : TDBEventType; Const Msg : String); virtual;
+    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
   public
   public
     procedure Prepare; virtual;
     procedure Prepare; virtual;
     procedure UnPrepare; virtual;
     procedure UnPrepare; virtual;
@@ -286,7 +287,6 @@ type
     destructor Destroy; override;
     destructor Destroy; override;
     procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
     procedure SetSchemaInfo( ASchemaType : TSchemaType; ASchemaObjectName, ASchemaPattern : string); virtual;
     property Prepared : boolean read IsPrepared;
     property Prepared : boolean read IsPrepared;
-    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
     function RowsAffected: TRowsCount; virtual;
     function RowsAffected: TRowsCount; virtual;
     function ParamByName(Const AParamName : String) : TParam;
     function ParamByName(Const AParamName : String) : TParam;
   protected
   protected
@@ -342,6 +342,7 @@ type
   TSQLQuery = Class(TCustomSQLQuery)
   TSQLQuery = Class(TCustomSQLQuery)
   public
   public
     property SchemaType;
     property SchemaType;
+    Property StatementType;
   Published
   Published
     property MaxIndexesCount;
     property MaxIndexesCount;
    // TDataset stuff
    // TDataset stuff

+ 1 - 0
packages/fcl-extra/src/daemonapp.pp

@@ -929,6 +929,7 @@ destructor TCustomDaemonApplication.Destroy;
 begin
 begin
   if assigned(FEventLog) then
   if assigned(FEventLog) then
     FEventLog.Free;
     FEventLog.Free;
+  inherited Destroy;
 end;
 end;
 
 
 procedure TCustomDaemonApplication.DoRun;
 procedure TCustomDaemonApplication.DoRun;

+ 1 - 1
packages/fcl-image/src/fpcanvas.pp

@@ -102,7 +102,7 @@ type
     property Bold : boolean index 5 read GetFlags write SetFlags;
     property Bold : boolean index 5 read GetFlags write SetFlags;
     property Italic : boolean index 6 read GetFlags write SetFlags;
     property Italic : boolean index 6 read GetFlags write SetFlags;
     property Underline : boolean index 7 read GetFlags write SetFlags;
     property Underline : boolean index 7 read GetFlags write SetFlags;
-    property StrikeTrough : boolean index 8 read GetFlags write SetFlags;
+    property StrikeThrough : boolean index 8 read GetFlags write SetFlags;
     property Orientation: Integer read GetOrientation write SetOrientation default 0;
     property Orientation: Integer read GetOrientation write SetOrientation default 0;
         
         
   end;
   end;

+ 83 - 0
packages/fcl-passrc/src/pastree.pp

@@ -524,6 +524,8 @@ type
     Modifiers: TStringList;
     Modifiers: TStringList;
     Interfaces : TFPList;
     Interfaces : TFPList;
     GenericTemplateTypes : TFPList;
     GenericTemplateTypes : TFPList;
+    Function FindMember(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
+    Function FindMemberInAncestors(MemberClass : TPTreeElement; Const MemberName : String) : TPasElement;
     Function IsPacked : Boolean;
     Function IsPacked : Boolean;
     Function InterfaceGUID : string;
     Function InterfaceGUID : string;
   end;
   end;
@@ -660,6 +662,8 @@ type
   { TPasProperty }
   { TPasProperty }
 
 
   TPasProperty = class(TPasVariable)
   TPasProperty = class(TPasVariable)
+  Public
+    FResolvedType : TPasType;
   public
   public
     constructor Create(const AName: string; AParent: TPasElement); override;
     constructor Create(const AName: string; AParent: TPasElement); override;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -672,6 +676,7 @@ type
     ReadAccessorName, WriteAccessorName,ImplementsName,
     ReadAccessorName, WriteAccessorName,ImplementsName,
       StoredAccessorName: string;
       StoredAccessorName: string;
     IsDefault, IsNodefault: Boolean;
     IsDefault, IsNodefault: Boolean;
+    Function ResolvedType : TPasType;
     Function IndexValue : String;
     Function IndexValue : String;
     Function DefaultValue : string;
     Function DefaultValue : string;
   end;
   end;
@@ -1363,6 +1368,49 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TPasClassType.FindMember(MemberClass: TPTreeElement; const MemberName: String): TPasElement;
+
+Var
+  I : Integer;
+
+begin
+//  Writeln('Looking for ',MemberName,'(',MemberClass.ClassName,') in ',Name);
+  Result:=Nil;
+  I:=0;
+  While (Result=Nil) and (I<Members.Count) do
+    begin
+    Result:=TPasElement(Members[i]);
+    if (Result.ClassType<>MemberClass) or (CompareText(Result.Name,MemberName)<>0) then
+      Result:=Nil;
+    Inc(I);
+    end;
+end;
+
+function TPasClassType.FindMemberInAncestors(MemberClass: TPTreeElement;
+  const MemberName: String): TPasElement;
+
+  Function A (C : TPasClassType) : TPasClassType;
+
+  begin
+    if C.AncestorType is TPasClassType then
+      C:=TPasClassType(C.AncestorType)
+    else
+      C:=Nil;
+  end;
+
+Var
+  C : TPasClassType;
+
+begin
+  Result:=Nil;
+  C:=A(Self);
+  While (Result=Nil) and (C<>Nil) do
+    begin
+    Result:=C.FindMember(MemberClass,MemberName);
+    C:=A(C);
+    end;
+end;
+
 function TPasClassType.InterfaceGUID: string;
 function TPasClassType.InterfaceGUID: string;
 begin
 begin
   If Assigned(GUIDExpr) then
   If Assigned(GUIDExpr) then
@@ -2512,6 +2560,7 @@ begin
 end;
 end;
 
 
 
 
+
 function TPasVariable.Value: String;
 function TPasVariable.Value: String;
 begin
 begin
   If Assigned(Expr) then
   If Assigned(Expr) then
@@ -2559,6 +2608,40 @@ begin
   ProcessHints(True, Result);
   ProcessHints(True, Result);
 end;
 end;
 
 
+function TPasProperty.ResolvedType: TPasType;
+
+  Function GC(P : TPasProperty) : TPasClassType;
+
+  begin
+    if Assigned(P) and Assigned(P.Parent) and (P.Parent is TPasClassType) then
+      Result:=P.Parent as TPasClassType
+    else
+      Result:=Nil;
+  end;
+
+
+Var
+  P : TPasProperty;
+  C : TPasClassType;
+
+begin
+  Result:=FResolvedType;
+  if Result=Nil then
+    Result:=VarType;
+  P:=Self;
+  While (Result=Nil) and (P<>Nil) do
+    begin
+    C:=GC(P);
+//    Writeln('Looking for ',Name,' in ancestor ',C.Name);
+    P:=TPasProperty(C.FindMemberInAncestors(TPasProperty,Name));
+    if Assigned(P) then
+      begin
+//      Writeln('Found ',Name,' in ancestor : ',P.Name);
+      Result:=P.ResolvedType;
+      end
+    end;
+end;
+
 function TPasProperty.IndexValue: String;
 function TPasProperty.IndexValue: String;
 begin
 begin
   If Assigned(IndexExpr) then
   If Assigned(IndexExpr) then

+ 3 - 0
packages/fcl-passrc/src/pscanner.pp

@@ -190,6 +190,7 @@ type
   private
   private
     FTextFile: Text;
     FTextFile: Text;
     FileOpened: Boolean;
     FileOpened: Boolean;
+    FBuffer : Array[0..4096-1] of byte;
   public
   public
     constructor Create(const AFilename: string); override;
     constructor Create(const AFilename: string); override;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -797,10 +798,12 @@ end;
   ---------------------------------------------------------------------}
   ---------------------------------------------------------------------}
 
 
 constructor TFileLineReader.Create(const AFilename: string);
 constructor TFileLineReader.Create(const AFilename: string);
+
 begin
 begin
   inherited Create(AFileName);
   inherited Create(AFileName);
   Assign(FTextFile, AFilename);
   Assign(FTextFile, AFilename);
   Reset(FTextFile);
   Reset(FTextFile);
+  SetTextBuf(FTextFile,FBuffer,SizeOf(FBuffer));
   FileOpened := true;
   FileOpened := true;
 end;
 end;
 
 

+ 1 - 0
packages/fcl-stl/fpmake.pp

@@ -47,6 +47,7 @@ begin
           AddUnit('gdeque');
           AddUnit('gdeque');
         end;
         end;
     T:=P.Targets.AddUnit('gset.pp');
     T:=P.Targets.AddUnit('gset.pp');
+    T:=P.Targets.AddUnit('gtree.pp');
     T:=P.Targets.AddUnit('gstack.pp');
     T:=P.Targets.AddUnit('gstack.pp');
       with T.Dependencies do
       with T.Dependencies do
         begin
         begin

+ 139 - 0
packages/fcl-stl/src/gtree.pp

@@ -0,0 +1,139 @@
+{
+   This file is part of the Free Pascal FCL library.
+   Copyright 2013 Mario Ray Mahardhika
+ 
+   Implements a generic Tree.
+ 
+   See the file COPYING.FPC, included in this distribution,
+   for details about the copyright.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY;without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+**********************************************************************}
+unit gtree;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  gvector,gstack,gqueue;
+
+type
+
+  { TTreeNode }
+
+  generic TTreeNode<T> = class
+  public type
+    TTreeNodeList = specialize TVector<TTreeNode>;
+  protected
+    FData: T;
+    FChildren: TTreeNodeList;
+  public
+    constructor Create;
+    constructor Create(const AData: T);
+    destructor Destroy; override;
+    property Data: T read FData write FData;
+    property Children: TTreeNodeList read FChildren;
+  end;
+
+  generic TDepthFirstCallback<T> = procedure (const AData: T);
+  generic TBreadthFirstCallback<T> = procedure (const AData: T);
+
+  generic TTree<T> = class
+  public type
+    TTreeNodeType = specialize TTreeNode<T>;
+    TDepthFirstCallbackType = specialize TDepthFirstCallback<T>;
+    TBreadthFirstCallbackType = specialize TBreadthFirstCallback<T>;
+  private type
+  type
+    TStackType = specialize TStack<TTreeNodeType>;
+    TQueueType = specialize TQueue<TTreeNodeType>;
+  private
+    FRoot: TTreeNodeType;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    procedure DepthFirstTraverse(Callback: TDepthFirstCallbackType);
+    procedure BreadthFirstTraverse(Callback: TBreadthFirstCallbackType);
+    property Root: TTreeNodeType read FRoot write FRoot;
+  end;
+
+implementation
+
+
+{ TTreeNode }
+
+constructor TTreeNode.Create;
+begin
+  FChildren := TTreeNodeList.Create;
+end;
+
+constructor TTreeNode.Create(const AData: T);
+begin
+  FData := AData;
+  FChildren := TTreeNodeList.Create;
+end;
+
+destructor TTreeNode.Destroy;
+var
+  Child: TTreeNode;
+begin
+  for Child in FChildren do begin
+    Child.Free;
+  end;
+  FChildren.Free;
+end;
+
+{ TTree }
+
+constructor TTree.Create;
+begin
+  FRoot := nil;
+end;
+
+destructor TTree.Destroy;
+begin
+  FRoot.Free;
+end;
+
+procedure TTree.DepthFirstTraverse(Callback: TDepthFirstCallbackType);
+var
+  Stack: TStackType;
+  Node,Child: TTreeNodeType;
+begin
+  if Assigned(FRoot) then begin
+    Stack := TStackType.Create;
+    Stack.Push(FRoot);
+    while Stack.Size > 0 do begin
+      Node := Stack.Top;
+      Stack.Pop;
+      Callback(Node.Data);
+      for Child in Node.Children do Stack.Push(Child);
+    end;
+    Stack.Free;
+  end;
+end;
+
+procedure TTree.BreadthFirstTraverse(Callback: TBreadthFirstCallbackType);
+var
+  Queue: TQueueType;
+  Node,Child: TTreeNodeType;
+begin
+  if Assigned(FRoot) then begin
+    Queue := TQueueType.Create;
+    Queue.Push(FRoot);
+    while Queue.Size > 0 do begin
+      Node := Queue.Front;
+      Queue.Pop;
+      Callback(Node.Data);
+      for Child in Node.Children do Queue.Push(Child);
+    end;
+    Queue.Free;
+  end;
+end;
+
+end.
+

+ 50 - 0
packages/fcl-stl/tests/gtreetest.pp

@@ -0,0 +1,50 @@
+program gtreetest;
+
+{$mode objfpc}{$H+}
+
+uses
+  gtree;
+
+procedure WriteIntegerCallback(const i: Integer);
+begin
+  Write(i,' ');
+end;
+
+type
+  TIntegerTreeNode = specialize TTreeNode<Integer>;
+  TIntegerTree = specialize TTree<Integer>;
+var
+  Tree: TIntegerTree;
+  Node,Tmp: TIntegerTreeNode;
+  i: Integer;
+begin
+  Node := TIntegerTreeNode.Create(0);
+  for i := 1 to 3 do begin
+    Tmp := TIntegerTreeNode.Create(i);
+    Node.Children.PushBack(Tmp);
+  end;
+  Tmp := Node;
+  Node := TIntegerTreeNode.Create(4);
+  Node.Children.PushBack(Tmp);
+  for i := 5 to 7 do begin
+    Tmp := TIntegerTreeNode.Create(i);
+    Node.Children.PushBack(Tmp);
+  end;
+  Tmp := Node;
+  Node := TIntegerTreeNode.Create(8);
+  Node.Children.PushBack(Tmp);
+  for i := 9 to 10 do begin
+    Tmp := TIntegerTreeNode.Create(i);
+    Node.Children.PushBack(Tmp);
+  end;
+
+  Tree := TIntegerTree.Create;
+  Tree.Root := Node;
+
+  WriteLn('Depth first:');
+  Tree.DepthFirstTraverse(@WriteIntegerCallback);WriteLn;
+  WriteLn('Breadth first:');
+  Tree.BreadthFirstTraverse(@WriteIntegerCallback);WriteLn;
+
+  Tree.Free;
+end.

+ 4 - 4
packages/fcl-xml/src/htmwrite.pp

@@ -72,7 +72,7 @@ type
     procedure VisitDocumentType(Node: TDOMNode);
     procedure VisitDocumentType(Node: TDOMNode);
     procedure VisitPI(Node: TDOMNode);
     procedure VisitPI(Node: TDOMNode);
   public
   public
-    constructor Create(AStream: TStream);
+    constructor Create(AStream: TStream; ACapacity : Cardinal = 4096);
     destructor Destroy; override;
     destructor Destroy; override;
   end;
   end;
 
 
@@ -111,14 +111,14 @@ end;
     THTMLWriter
     THTMLWriter
   ---------------------------------------------------------------------}
   ---------------------------------------------------------------------}
 
 
-constructor THTMLWriter.Create(AStream: TStream);
+constructor THTMLWriter.Create(AStream: TStream; ACapacity : Cardinal = 4096);
 begin
 begin
   inherited Create;
   inherited Create;
   FStream := AStream;
   FStream := AStream;
   // some overhead - always be able to write at least one extra UCS4
   // some overhead - always be able to write at least one extra UCS4
-  FBuffer := AllocMem(512+32);
+  FCapacity := ACapacity;
+  FBuffer := AllocMem(FCapacity+32);
   FBufPos := FBuffer;
   FBufPos := FBuffer;
-  FCapacity := 512;
   // Later on, this may be put under user control
   // Later on, this may be put under user control
   // for now, take OS setting
   // for now, take OS setting
   FLineBreak := sLineBreak;
   FLineBreak := sLineBreak;

+ 2 - 0
packages/winunits-base/src/shlobj.pp

@@ -876,6 +876,8 @@ Const
   FOS_FORCESHOWHIDDEN     = $10000000;
   FOS_FORCESHOWHIDDEN     = $10000000;
   FOS_DEFAULTNOMINIMODE	  = $20000000;
   FOS_DEFAULTNOMINIMODE	  = $20000000;
   FOS_FORCEPREVIEWPANEON  = $40000000;
   FOS_FORCEPREVIEWPANEON  = $40000000;
+  SHGFP_TYPE_CURRENT      =  0;   // shgetfolderpath, current value for user, verify it exists
+  SHGFP_TYPE_DEFAULT  	  =  1;   // shgetfolderpath, default value, may not exist
    
    
 Type
 Type
       SFGAOF  = ULONG;
       SFGAOF  = ULONG;

+ 1 - 2
rtl/inc/compproc.inc

@@ -554,11 +554,10 @@ procedure fpc_raise_nested; compilerproc;
 function fpc_help_constructor(_self:pointer;var _vmt:pointer;_vmt_pos:cardinal):pointer;compilerproc;
 function fpc_help_constructor(_self:pointer;var _vmt:pointer;_vmt_pos:cardinal):pointer;compilerproc;
 procedure fpc_help_destructor(_self,_vmt:pointer;vmt_pos:cardinal);compilerproc;
 procedure fpc_help_destructor(_self,_vmt:pointer;vmt_pos:cardinal);compilerproc;
 procedure fpc_help_fail(_self:pointer;var _vmt:pointer;vmt_pos:cardinal);compilerproc;
 procedure fpc_help_fail(_self:pointer;var _vmt:pointer;vmt_pos:cardinal);compilerproc;
-{$endif FPC_HAS_FEATURE_OBJECTS}
-
 
 
 procedure fpc_check_object(_vmt:pointer); compilerproc;
 procedure fpc_check_object(_vmt:pointer); compilerproc;
 procedure fpc_check_object_ext(vmt,expvmt:pointer);compilerproc;
 procedure fpc_check_object_ext(vmt,expvmt:pointer);compilerproc;
+{$endif FPC_HAS_FEATURE_OBJECTS}
 
 
 
 
 {$ifdef FPC_HAS_FEATURE_RTTI}
 {$ifdef FPC_HAS_FEATURE_RTTI}

+ 1 - 1
rtl/inc/fexpand.inc

@@ -161,7 +161,7 @@ begin
             S := GetEnv ('HOME');
             S := GetEnv ('HOME');
   {$ENDIF FPC_FEXPAND_GETENV_PCHAR}
   {$ENDIF FPC_FEXPAND_GETENV_PCHAR}
  {$ENDIF FPC_FEXPAND_SYSUTILS}
  {$ENDIF FPC_FEXPAND_SYSUTILS}
-            if (S = '') or (Length (S) = 1)
+            if (S = '') or (Length (S) = 1) and (Length (Pa) > 1)
                                           and (S [1] = DirectorySeparator) then
                                           and (S [1] = DirectorySeparator) then
                 Delete (Pa, 1, 1)
                 Delete (Pa, 1, 1)
             else
             else

+ 5 - 1
rtl/inc/text.inc

@@ -1698,7 +1698,11 @@ const
   { how many bytes of the string have been processed already (used for readstr) }
   { how many bytes of the string have been processed already (used for readstr) }
   BytesReadIndex = 17;
   BytesReadIndex = 17;
 
 
-threadvar
+{$ifdef FPC_HAS_FEATURE_THREADING}
+ThreadVar
+{$else FPC_HAS_FEATURE_THREADING}
+Var
+{$endif FPC_HAS_FEATURE_THREADING}
   ReadWriteStrText: textrec;
   ReadWriteStrText: textrec;
 
 
 procedure WriteStrShort(var t: textrec);
 procedure WriteStrShort(var t: textrec);

+ 2 - 2
rtl/inc/threadvr.inc

@@ -50,7 +50,7 @@ end;
 
 
 procedure init_all_unit_threadvars;
 procedure init_all_unit_threadvars;
 var
 var
-  i : integer;
+  i : longint;
 begin
 begin
 {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
 {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
   with PltvInitTablesTable(EntryInformation.ThreadvarTablesTable)^ do
   with PltvInitTablesTable(EntryInformation.ThreadvarTablesTable)^ do
@@ -84,7 +84,7 @@ end;
 
 
 procedure copy_all_unit_threadvars;
 procedure copy_all_unit_threadvars;
 var
 var
-  i : integer;
+  i: longint;
 begin
 begin
 {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
 {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
   with PltvInitTablesTable(EntryInformation.ThreadvarTablesTable)^ do
   with PltvInitTablesTable(EntryInformation.ThreadvarTablesTable)^ do

+ 3 - 9
rtl/linux/Makefile

@@ -210,14 +210,6 @@ endif
 ifeq ($(OS_TARGET),linux)
 ifeq ($(OS_TARGET),linux)
 linuxHier=1
 linuxHier=1
 endif
 endif
-ifndef CROSSCOMPILE
-BUILDFULLNATIVE=1
-export BUILDFULLNATIVE
-endif
-ifdef BUILDFULLNATIVE
-BUILDNATIVE=1
-export BUILDNATIVE
-endif
 export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
 export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
 ifdef FPCDIR
 ifdef FPCDIR
 override FPCDIR:=$(subst \,/,$(FPCDIR))
 override FPCDIR:=$(subst \,/,$(FPCDIR))
@@ -3248,9 +3240,11 @@ ifeq ($(ARCH),powerpc64)
 endif
 endif
 ifeq ($(ARCH),mips)
 ifeq ($(ARCH),mips)
   ASTARGET=-32 -mips32 -EB
   ASTARGET=-32 -mips32 -EB
+  ASSHAREDOPT=-KPIC
 endif
 endif
 ifeq ($(ARCH),mipsel)
 ifeq ($(ARCH),mipsel)
   ASTARGET=-32 -mips32 -EL
   ASTARGET=-32 -mips32 -EL
+  ASSHAREDOPT=-KPIC
 endif
 endif
 ifeq ($(ARCH),sparc)
 ifeq ($(ARCH),sparc)
   ifneq ($(findstring -Cg ,$(COMPILER)),)
   ifneq ($(findstring -Cg ,$(COMPILER)),)
@@ -3263,7 +3257,7 @@ endif
 prt0$(OEXT) : $(ARCH)/prt0.as
 prt0$(OEXT) : $(ARCH)/prt0.as
 	$(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)prt0$(OEXT) $(ARCH)/prt0.as
 	$(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)prt0$(OEXT) $(ARCH)/prt0.as
 dllprt0$(OEXT) : $(ARCH)/dllprt0.as
 dllprt0$(OEXT) : $(ARCH)/dllprt0.as
-	$(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)dllprt0$(OEXT) $(ARCH)/dllprt0.as
+	$(AS) $(ASTARGET) $(ASSHAREDOPT) -o $(UNITTARGETDIRPREFIX)dllprt0$(OEXT) $(ARCH)/dllprt0.as
 gprt0$(OEXT) : $(ARCH)/gprt0.as
 gprt0$(OEXT) : $(ARCH)/gprt0.as
 	$(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)gprt0$(OEXT) $(ARCH)/gprt0.as
 	$(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)gprt0$(OEXT) $(ARCH)/gprt0.as
 cprt0$(OEXT) : $(ARCH)/cprt0.as
 cprt0$(OEXT) : $(ARCH)/cprt0.as

+ 4 - 1
rtl/linux/Makefile.fpc

@@ -129,9 +129,11 @@ endif
 # Select 32/64 mode
 # Select 32/64 mode
 ifeq ($(ARCH),mips)
 ifeq ($(ARCH),mips)
   ASTARGET=-32 -mips32 -EB
   ASTARGET=-32 -mips32 -EB
+  ASSHAREDOPT=-KPIC
 endif
 endif
 ifeq ($(ARCH),mipsel)
 ifeq ($(ARCH),mipsel)
   ASTARGET=-32 -mips32 -EL
   ASTARGET=-32 -mips32 -EL
+  ASSHAREDOPT=-KPIC
 endif
 endif
 
 
 ifeq ($(ARCH),sparc)
 ifeq ($(ARCH),sparc)
@@ -150,8 +152,9 @@ endif
 prt0$(OEXT) : $(ARCH)/prt0.as
 prt0$(OEXT) : $(ARCH)/prt0.as
         $(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)prt0$(OEXT) $(ARCH)/prt0.as
         $(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)prt0$(OEXT) $(ARCH)/prt0.as
 
 
+# ASSHAREDOPT adds -KPIC mandatoy for mips/mipsel objects in shared libs
 dllprt0$(OEXT) : $(ARCH)/dllprt0.as
 dllprt0$(OEXT) : $(ARCH)/dllprt0.as
-        $(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)dllprt0$(OEXT) $(ARCH)/dllprt0.as
+        $(AS) $(ASTARGET) $(ASSHAREDOPT) -o $(UNITTARGETDIRPREFIX)dllprt0$(OEXT) $(ARCH)/dllprt0.as
 
 
 gprt0$(OEXT) : $(ARCH)/gprt0.as
 gprt0$(OEXT) : $(ARCH)/gprt0.as
         $(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)gprt0$(OEXT) $(ARCH)/gprt0.as
         $(AS) $(ASTARGET) -o $(UNITTARGETDIRPREFIX)gprt0$(OEXT) $(ARCH)/gprt0.as

+ 125 - 1
rtl/linux/mips/dllprt0.as

@@ -1 +1,125 @@
-.include "mips/prt0.as"
+/*
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2009 by Michael Van Canneyt and David Zhang
+
+    Startup code for elf32-mipsel/elf32-mips
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+*/
+        .set noat
+
+	.section ".text"
+
+	.align 4
+	.global _dynamic_start
+	.ent	_dynamic_start
+	.type _dynamic_start,@function
+_dynamic_start:
+        .set noreorder
+	.cpload $25
+        /* TODO: check whether this code is correct */
+        la      $v0,__dl_fini
+        lw      $v0,($v0)
+	lw      $v1,%call16(_start)($gp)
+	move    $t9,$v1
+        jalr	$t9
+	nop
+
+	.end	_dynamic_start
+	.size 	_dynamic_start, .-_dynamic_start
+
+	.align 4
+	.global _start
+        .set    nomips16
+        .ent    _start
+ 	.type	_start,@function
+/*  This is the canonical entry point, usually the first thing in the text
+    segment.  The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
+    point runs, most registers' values are unspecified, except for:
+
+    v0 ($2)	Function pointer of a function to be executed at exit
+
+    sp ($29)	The stack contains the arguments and environment:
+ 		0(%sp)			argc
+ 		4(%sp)			argv[0]
+
+ 		...
+ 		(4*argc)(%sp)		NULL
+ 		(4*(argc+1))(%sp)	envp[0]
+ 		...
+ 					NULL
+    ra ($31)	Return address set to zero.
+*/
+_start:
+        /* load fp */
+        .set noreorder
+	.cpload $25
+	addiu   $sp,$sp,-32
+        move    $s8,$sp
+	.cprestore 16
+        la      $t1,__stkptr
+        sw      $s8,($t1)
+
+        /* align stack */
+        li      $at,-8
+        and     $sp,$sp,$at
+
+        addiu   $sp,$sp,-32
+
+        lui     $s7,0x3d
+        addiu   $s7,$s7,2304
+        li      $at,-8
+        and     $s7,$s7,$at
+        addiu   $s7,$s7,-32
+
+        /* store argc */
+        lw      $a0,0($s8)
+        la      $a1,operatingsystem_parameter_argc
+        sw      $a0,($a1)
+
+        /* store argv */
+        addiu   $a1,$s8,4
+        la      $a2,operatingsystem_parameter_argv
+        sw      $a1,($a2)
+
+        /* store envp */
+        addiu   $a2,$a0,1
+        sll     $a2,$a2,0x2
+        addu    $a2,$a2,$a1
+        la      $a3,operatingsystem_parameter_envp
+        sw      $a2,($a3)
+        la      $t9,PASCALMAIN
+        jalr    $t9
+        nop
+	b       _haltproc
+        nop
+
+	.end	_start
+	.size 	_start, .-_start
+
+	.globl  _haltproc
+	.ent	_haltproc
+	.type   _haltproc,@function
+_haltproc:
+        /* TODO: need to check whether __dl_fini is non-zero and call the function pointer in case */
+
+        li      $v0,4001
+        syscall
+        b       _haltproc
+        nop
+
+	.end _haltproc
+	.size _haltproc, .-_haltproc
+
+        .comm __stkptr,4
+        .comm __dl_fini,4
+
+        .comm operatingsystem_parameter_envp,4
+        .comm operatingsystem_parameter_argc,4
+        .comm operatingsystem_parameter_argv,4
+

+ 10 - 5
rtl/m68k/m68k.inc

@@ -92,6 +92,8 @@ procedure FillChar(var x;count:longint;value:byte); assembler;
      move.l x, a0          { destination                   }
      move.l x, a0          { destination                   }
      move.l count, d1      { number of bytes to fill       }
      move.l count, d1      { number of bytes to fill       }
      move.b value, d0      { fill data                     }
      move.b value, d0      { fill data                     }
+     tst.l d1              { anything to fill at all?      }
+     beq    @LMEMSET5
      cmpi.l #65535, d1     { check, if this is a word move }
      cmpi.l #65535, d1     { check, if this is a word move }
      ble    @LMEMSET3      { use fast dbra mode            }
      ble    @LMEMSET3      { use fast dbra mode            }
      bra @LMEMSET2
      bra @LMEMSET2
@@ -318,9 +320,11 @@ end;
 procedure fillword(var x;count : longint;value : word);
 procedure fillword(var x;count : longint;value : word);
   begin
   begin
     asm
     asm
-     move.l x, a0         { destination             }
-     move.l count, d1     { number of bytes to fill }
-     move.w value, d0     { fill data               }
+     move.l x, a0         { destination              }
+     move.l count, d1     { number of bytes to fill  }
+     move.w value, d0     { fill data                }
+     tst.l d1             { anything to fill at all? }
+     beq @LMEMSET3
      bra @LMEMSET21
      bra @LMEMSET21
    @LMEMSET11:
    @LMEMSET11:
      move.w d0,(a0)+
      move.w d0,(a0)+
@@ -328,6 +332,7 @@ procedure fillword(var x;count : longint;value : word);
      subq.l #1,d1
      subq.l #1,d1
      cmp.b #-1,d1
      cmp.b #-1,d1
      bne  @LMEMSET11
      bne  @LMEMSET11
+   @LMEMSET3:
     end ['d0','d1','a0'];
     end ['d0','d1','a0'];
   end;
   end;
 
 
@@ -349,16 +354,16 @@ function abs(l : longint) : longint;
 function InterLockedDecrement (var Target: longint) : longint;
 function InterLockedDecrement (var Target: longint) : longint;
   begin
   begin
   {$warning FIX ME}
   {$warning FIX ME}
-    Result := Target;
     Dec(Target);
     Dec(Target);
+    Result := Target;
   end;
   end;
 
 
 
 
 function InterLockedIncrement (var Target: longint) : longint;
 function InterLockedIncrement (var Target: longint) : longint;
   begin
   begin
   {$warning FIX ME}
   {$warning FIX ME}
-    Result := Target;
     Inc(Target);
     Inc(Target);
+    Result := Target;
   end;
   end;
 
 
 
 

+ 5 - 0
rtl/win/systhrd.inc

@@ -225,7 +225,12 @@ var
 {$ifdef DEBUG_MT}
 {$ifdef DEBUG_MT}
         writeln('Jumping to thread function of thread ',Win32GetCurrentThreadId);
         writeln('Jumping to thread function of thread ',Win32GetCurrentThreadId);
 {$endif DEBUG_MT}
 {$endif DEBUG_MT}
+{$ifdef FPC_USE_WIN64_SEH}
+        { use special 'top-level' exception handler around the thread function }
+        ThreadMain:=main_wrapper(ti.p,pointer(ti.f));
+{$else FPC_USE_WIN64_SEH}
         ThreadMain:=ti.f(ti.p);
         ThreadMain:=ti.f(ti.p);
+{$endif FPC_USE_WIN64_SEH}
       end;
       end;
 
 
 
 

+ 15 - 13
rtl/win64/system.pp

@@ -125,6 +125,19 @@ implementation
 var
 var
   SysInstance : qword;public;
   SysInstance : qword;public;
 
 
+{$ifdef FPC_USE_WIN64_SEH}
+function main_wrapper(arg: Pointer; proc: Pointer): ptrint; assembler; nostackframe;
+asm
+    subq   $40, %rsp
+.seh_stackalloc 40
+.seh_endprologue
+    call   %rdx             { "arg" is passed in %rcx }
+    nop                     { this nop is critical for exception handling }
+    addq   $40, %rsp
+.seh_handler __FPC_default_handler,@except,@unwind
+end;
+{$endif FPC_USE_WIN64_SEH}
+
 { include system independent routines }
 { include system independent routines }
 {$I system.inc}
 {$I system.inc}
 
 
@@ -179,18 +192,6 @@ var
     to check if the call stack can be written on exceptions }
     to check if the call stack can be written on exceptions }
   _SS : Cardinal;
   _SS : Cardinal;
 
 
-{$ifdef FPC_USE_WIN64_SEH}
-procedure main_wrapper(p: TProcedure); assembler; nostackframe;
-asm
-    subq   $40, %rsp
-.seh_stackalloc 40
-.seh_endprologue
-    call   %rcx
-    nop                     { this nop is critical for exception handling }
-    addq   $40, %rsp
-.seh_handler __FPC_default_handler,@except,@unwind
-end;
-{$endif FPC_USE_WIN64_SEH}
 
 
 
 
 procedure Exe_entry;[public,alias:'_FPC_EXE_Entry'];
 procedure Exe_entry;[public,alias:'_FPC_EXE_Entry'];
@@ -209,7 +210,8 @@ procedure Exe_entry;[public,alias:'_FPC_EXE_Entry'];
         movq %rbp,%rsi
         movq %rbp,%rsi
         xorq %rbp,%rbp
         xorq %rbp,%rbp
 {$ifdef FPC_USE_WIN64_SEH}
 {$ifdef FPC_USE_WIN64_SEH}
-        lea  PASCALMAIN(%rip),%rcx
+        xor  %rcx,%rcx
+        lea  PASCALMAIN(%rip),%rdx
         call main_wrapper
         call main_wrapper
 {$else FPC_USE_WIN64_SEH}
 {$else FPC_USE_WIN64_SEH}
         call PASCALMAIN
         call PASCALMAIN

BIN
tests/test/cg/obj/linux/mips/cpptcl1.o


BIN
tests/test/cg/obj/linux/mips/cpptcl2.o


BIN
tests/test/cg/obj/linux/mips/ctest.o


BIN
tests/test/cg/obj/linux/mips/tcext3.o


BIN
tests/test/cg/obj/linux/mips/tcext4.o


BIN
tests/test/cg/obj/linux/mips/tcext5.o


BIN
tests/test/cg/obj/linux/mips/tcext6.o


BIN
tests/test/cg/obj/linux/mipsel/cpptcl1.o


BIN
tests/test/cg/obj/linux/mipsel/cpptcl2.o


BIN
tests/test/cg/obj/linux/mipsel/ctest.o


BIN
tests/test/cg/obj/linux/mipsel/tcext3.o


BIN
tests/test/cg/obj/linux/mipsel/tcext4.o


BIN
tests/test/cg/obj/linux/mipsel/tcext5.o


BIN
tests/test/cg/obj/linux/mipsel/tcext6.o


+ 3 - 0
tests/test/cg/obj/readme.txt

@@ -33,6 +33,9 @@ FreeBSD-i386 : gcc (GCC) 4.2.1 20070719  [FreeBSD] 8.2-RELEASE
 Linux-sparc : gcc (Debian 4.3.2-1.1) 4.3.2
 Linux-sparc : gcc (Debian 4.3.2-1.1) 4.3.2
 OpenBSD-x86_64 : gcc (GCC) 4.2.1 20070719 
 OpenBSD-x86_64 : gcc (GCC) 4.2.1 20070719 
 Linux-arm-gnueabihf : gcc version 4.6.3 (Debian 4.6.3-8+rpi1)
 Linux-arm-gnueabihf : gcc version 4.6.3 (Debian 4.6.3-8+rpi1)
+Linux-mipsel : gcc (Debian 4.4.5-8) 4.4.5
+Linux-mips : gcc (Debian 4.4.5-8) 4.4.5
+
 
 
 Android-arm  : GCC 4.7
 Android-arm  : GCC 4.7
 Android-i386 : GCC 4.7
 Android-i386 : GCC 4.7

+ 19 - 0
tests/test/terecs12a.pp

@@ -0,0 +1,19 @@
+{ %FAIL }
+{ %NORUN }
+program terecs12a;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+procedure Test;
+type
+  TRecord = record
+  private const
+    TestConst = 0;
+  end;
+begin
+end;
+
+begin
+end.

+ 20 - 0
tests/test/terecs12b.pp

@@ -0,0 +1,20 @@
+{ %FAIL }
+{ %NORUN }
+program terecs12b;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+procedure Test;
+type
+  TRecord = record
+  var
+    TestField: Integer;
+    property TestProperty: Integer read TestField;
+  end;
+begin
+end;
+
+begin
+end.

+ 19 - 0
tests/test/terecs12c.pp

@@ -0,0 +1,19 @@
+{ %FAIL }
+{ %NORUN }
+program terecs12c;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+procedure Test;
+type
+  TRecord = record
+  class var
+    TestField: Integer;
+  end;
+begin
+end;
+
+begin
+end.

+ 18 - 0
tests/test/terecs12d.pp

@@ -0,0 +1,18 @@
+{ %FAIL }
+{ %NORUN }
+program terecs12d;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+procedure Test;
+type
+  TRecord = record
+    procedure Test;
+  end;
+begin
+end;
+
+begin
+end.

+ 16 - 0
tests/test/terecs13a.pp

@@ -0,0 +1,16 @@
+{ %FAIL }
+{ %NORUN }
+program terecs13a;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+var
+  R: record
+    private const
+      TestConst = 0;
+  end;
+
+begin
+end.

+ 17 - 0
tests/test/terecs13b.pp

@@ -0,0 +1,17 @@
+{ %FAIL }
+{ %NORUN }
+program terecs13b;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+var
+  R: record
+    var
+      TestField: Integer;
+      property TestProperty: Integer read TestField;
+  end;
+
+begin
+end.

+ 16 - 0
tests/test/terecs13c.pp

@@ -0,0 +1,16 @@
+{ %FAIL }
+{ %NORUN }
+program terecs13c;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+var
+  R: record
+    class var
+      TestField: Integer;
+  end;
+
+begin
+end.

+ 15 - 0
tests/test/terecs13d.pp

@@ -0,0 +1,15 @@
+{ %FAIL }
+{ %NORUN }
+program terecs13d;
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+var
+  R: record
+    procedure Test;
+  end;
+
+begin
+end.

+ 8 - 8
tests/test/terecs15.pp

@@ -12,15 +12,15 @@ type
     Y: Integer;
     Y: Integer;
   public
   public
     // delphi does not allow constructors without arguments
     // delphi does not allow constructors without arguments
-    constructor CreateAndTest;
-    constructor Create; overload;
+    constructor CreateAndTest(dummy: byte);
+    constructor Create(dummy: boolean); overload;
     constructor Create(AX, AY: Integer); overload;
     constructor Create(AX, AY: Integer); overload;
     constructor Create(AY: Integer); overload;
     constructor Create(AY: Integer); overload;
   end;
   end;
 
 
 { TRec }
 { TRec }
 
 
-constructor TRec.CreateAndTest;
+constructor TRec.CreateAndTest(dummy: byte);
 begin
 begin
   X := 1;
   X := 1;
   if X <> 1 then
   if X <> 1 then
@@ -30,7 +30,7 @@ begin
     halt(2);
     halt(2);
 end;
 end;
 
 
-constructor TRec.Create;
+constructor TRec.Create(dummy: boolean);
 begin
 begin
   X := 10;
   X := 10;
   Y := 20;
   Y := 20;
@@ -44,7 +44,7 @@ end;
 
 
 constructor TRec.Create(AY: Integer);
 constructor TRec.Create(AY: Integer);
 begin
 begin
-  Create;
+  Create(false);
   Y := AY;
   Y := AY;
 end;
 end;
 
 
@@ -59,8 +59,8 @@ end;
 var
 var
   R: TRec;
   R: TRec;
 begin
 begin
-  R.CreateAndTest;
-  R := TRec.Create;
+  R.CreateAndTest(0);
+  R := TRec.Create(false);
   if R.X <> 10 then
   if R.X <> 10 then
     halt(3);
     halt(3);
   if R.Y <> 20 then
   if R.Y <> 20 then
@@ -68,6 +68,6 @@ begin
   TestRec(TRec.Create(1, 2), 1, 2, 5, 6);
   TestRec(TRec.Create(1, 2), 1, 2, 5, 6);
   TestRec(TRec.Create(2), 10, 2, 7, 8);
   TestRec(TRec.Create(2), 10, 2, 7, 8);
   // delphi has an internal error here
   // delphi has an internal error here
-  TestRec(R.Create, 10, 20, 9, 10);
+  TestRec(R.Create(false), 10, 20, 9, 10);
 end.
 end.
 
 

+ 5 - 5
tests/test/terecs16.pp

@@ -4,18 +4,18 @@ program terecs16;
 type
 type
   TRec = record
   TRec = record
     l: longint;
     l: longint;
-    constructor Create;
+    constructor Create(a: longint);
   end;
   end;
 
 
 
 
 var
 var
   r: TRec;
   r: TRec;
 
 
-  constructor TRec.Create;
+  constructor TRec.Create(a: longint);
   begin
   begin
-    l := 0;
+    l := a;
     r.l := 4;
     r.l := 4;
-    if l <> 0 then
+    if l <> a then
       halt(1);
       halt(1);
     l := 5;
     l := 5;
     if r.l <> 4 then
     if r.l <> 4 then
@@ -24,7 +24,7 @@ var
   end;
   end;
 
 
 begin
 begin
-  r := TRec.Create;
+  r := TRec.Create(10);
   if r.l <> 5 then
   if r.l <> 5 then
     halt(3);
     halt(3);
 end.
 end.

+ 27 - 0
tests/test/terecs17.pp

@@ -0,0 +1,27 @@
+{ %FAIL }
+{ %NORUN }
+program terecs17;
+
+{$mode delphi}
+
+type
+
+  { TRec }
+
+  TRec = record
+    X: Integer;
+    constructor Create;
+  end;
+
+{ TRec }
+
+constructor TRec.Create;
+begin
+
+end;
+
+var
+  R: TRec;
+begin
+  R := TRec.Create;
+end.

+ 27 - 0
tests/test/terecs17a.pp

@@ -0,0 +1,27 @@
+{ %FAIL }
+{ %NORUN }
+program terecs17a;
+
+{$mode delphi}
+
+type
+
+  { TRec }
+
+  TRec = record
+    X: Integer;
+    constructor Create(I: integer = 0);
+  end;
+
+{ TRec }
+
+constructor TRec.Create(I: integer = 0);
+begin
+
+end;
+
+var
+  R: TRec;
+begin
+  R := TRec.Create;
+end.

+ 32 - 0
tests/test/terecs18.pp

@@ -0,0 +1,32 @@
+{ %FAIL }
+{ %NORUN }
+program terecs18;
+
+{$mode delphi}
+
+type
+
+  { TRec }
+
+  TRec = record
+    X: Integer;
+  end;
+
+  { TRecHelper }
+
+  TRecHelper = record helper for TRec
+    constructor Create;
+  end;
+
+{ TRecHelper }
+
+constructor TRecHelper.Create;
+begin
+
+end;
+
+var
+  R: TRec;
+begin
+  R := TRec.Create;
+end.

+ 32 - 0
tests/test/terecs18a.pp

@@ -0,0 +1,32 @@
+{ %FAIL }
+{ %NORUN }
+program terecs18a;
+
+{$mode delphi}
+
+type
+
+  { TRec }
+
+  TRec = record
+    X: Integer;
+  end;
+
+  { TRecHelper }
+
+  TRecHelper = record helper for TRec
+    constructor Create(I: Integer = 0);
+  end;
+
+{ TRecHelper }
+
+constructor TRecHelper.Create;
+begin
+
+end;
+
+var
+  R: TRec;
+begin
+  R := TRec.Create;
+end.

+ 1 - 3
tests/test/trhlp12.pp

@@ -1,6 +1,4 @@
-{ %FAIL }
-
-{ for now constructors are forbidden in record helpers }
+{ constructors in record helpers }
 program trhlp12;
 program trhlp12;
 
 
 {$ifdef fpc}
 {$ifdef fpc}

+ 28 - 0
tests/test/trhlp45.pp

@@ -0,0 +1,28 @@
+program trhlp45;
+
+{$mode delphi}
+
+type
+  TRec = record
+    X: Integer;
+  end;
+
+  THelpRec = record helper for TRec
+    constructor Create(AX: Integer);
+  end;
+
+
+{ THelpRec }
+
+constructor THelpRec.Create(AX: Integer);
+begin
+  X := AX;
+end;
+
+var
+  R: TRec;
+begin
+  R := TRec.Create(1);
+  if R.X <> 1 then
+    halt(1);
+end.

+ 26 - 7
tests/test/units/dos/tfexpand.pp

@@ -398,18 +398,37 @@ if CDir [Length (CDir)] = DirSep then Check ('c:anything', CDir + 'anything')
  S := GetEnv ('HOME');
  S := GetEnv ('HOME');
  { On m68k netbsd at least, HOME contains a final slash
  { On m68k netbsd at least, HOME contains a final slash
    remove it PM }
    remove it PM }
- if S[length(S)]=DirSep then
+ if (Length (S) > 1) and (S [Length (S)] = DirSep) then
    S:=Copy(S,1,Length(S)-1);
    S:=Copy(S,1,Length(S)-1);
- Check ('~', S);
- Check ('~' + DirSep + '.', S);
- if (Length (S) > 0) and (S [Length (S)] <> DirSep) then S := S + DirSep;
+ if Length (S) = 0 then
+  begin
+   Check ('~', CurDir);
+   Check ('~' + DirSep + '.', DirSep);
+  end
+ else
+  begin
+   Check ('~', S);
+   Check ('~' + DirSep + '.', S);
+  end;
+ if (Length (S) > 0) and (S [Length (S)] <> DirSep) then
+  S := S + DirSep;
  Check ('~NobodyWithThisNameShouldEverExist.test/nothing', CurDir + DirSep +
  Check ('~NobodyWithThisNameShouldEverExist.test/nothing', CurDir + DirSep +
                             '~NobodyWithThisNameShouldEverExist.test/nothing');
                             '~NobodyWithThisNameShouldEverExist.test/nothing');
  Check ('/tmp/~NoSuchUserAgain', '/tmp/~NoSuchUserAgain');
  Check ('/tmp/~NoSuchUserAgain', '/tmp/~NoSuchUserAgain');
- Check ('~' + DirSep, S);
- Check ('~' + DirSep + '.' + DirSep, S);
- Check ('~' + DirSep + 'directory' + DirSep + 'another',
+ if Length (S) = 0 then
+  begin
+   Check ('~' + DirSep, DirSep);
+   Check ('~' + DirSep + '.' + DirSep, DirSep);
+   Check ('~' + DirSep + 'directory' + DirSep + 'another',
+                                    DirSep + 'directory' + DirSep + 'another');
+  end
+ else
+  begin
+   Check ('~' + DirSep, S);
+   Check ('~' + DirSep + '.' + DirSep, S);
+   Check ('~' + DirSep + 'directory' + DirSep + 'another',
                                          S + 'directory' + DirSep + 'another');
                                          S + 'directory' + DirSep + 'another');
+  end;
 {$ELSE UNIX}
 {$ELSE UNIX}
  {$IFNDEF NODRIVEC}
  {$IFNDEF NODRIVEC}
  Check (TestDrive + '..', TestDir + TestDir1Name);
  Check (TestDrive + '..', TestDir + TestDir1Name);

+ 25 - 0
tests/webtbs/tw19357.pp

@@ -0,0 +1,25 @@
+program tw19357;
+type
+  TLvl0 = bitpacked record
+    a,b: longword;
+  end;
+
+  TTest = packed record
+    a,b: longword;
+    c: TLvl0;
+  end;
+
+var
+  h: TTest absolute 100;
+const
+  x: pointer = @h.c.b;
+begin
+  if ptruint(@h.a) <> 100 then
+    halt(1);
+  if ptruint(@h.b) <> 104 then
+    halt(2);
+  if ptruint(@h.c.b) <> 112 then
+    halt(3);
+  if ptruint(x) <> 112 then
+    halt(4);
+end.

+ 34 - 0
tests/webtbs/tw23130.pp

@@ -0,0 +1,34 @@
+program tw23130;
+{$MODE DELPHI}
+
+type
+  TFunction<TArgument, TResult> = function (const arg: TArgument): TResult;
+
+  TWrapper = record
+    class function Z(const arg: Integer): Boolean; static;
+    class procedure W; static;
+  end;
+
+  TWrapper2 = class
+    procedure ZZ(f: TFunction<Integer, Boolean>);
+  end;
+
+class function TWrapper.Z(const arg: Integer): Boolean;
+begin
+  Result := arg < 0;
+end;
+
+class procedure TWrapper.W;
+begin
+  with TWrapper2.Create do begin
+    ZZ(@Z);  { Replace with @TWrapper.Z to get rid of the error }
+    Free;
+  end;
+end;
+
+procedure TWrapper2.ZZ(f: TFunction<Integer, Boolean>);
+begin
+end;
+
+begin
+end.

+ 67 - 64
utils/fpdoc/dglobals.pp

@@ -25,6 +25,10 @@ interface
 
 
 uses Classes, DOM, PasTree, PParser, StrUtils,uriparser;
 uses Classes, DOM, PasTree, PParser, StrUtils,uriparser;
 
 
+Const
+  CacheSize = 20;
+  ContentBufSize = 4096 * 8;
+
 Var
 Var
   LEOL : Integer;
   LEOL : Integer;
   modir : string;
   modir : string;
@@ -297,6 +301,8 @@ type
   private
   private
     FDocLogLevels: TFPDocLogLevels;
     FDocLogLevels: TFPDocLogLevels;
     FOnParseUnit: TOnParseUnitEvent;
     FOnParseUnit: TOnParseUnitEvent;
+    function ResolveLinkInPackages(AModule: TPasModule; const ALinkDest: String; Strict: Boolean=False): String;
+    function ResolveLinkInUsedUnits(AModule: TPasModule; const ALinkDest: String; Strict: Boolean=False): String;
   protected
   protected
     DescrDocs: TObjectList;             // List of XML documents
     DescrDocs: TObjectList;             // List of XML documents
     DescrDocNames: TStringList;         // Names of the XML documents
     DescrDocNames: TStringList;         // Names of the XML documents
@@ -332,7 +338,7 @@ type
     // Link tree support
     // Link tree support
     procedure AddLink(const APathName, ALinkTo: String);
     procedure AddLink(const APathName, ALinkTo: String);
     function FindAbsoluteLink(const AName: String): String;
     function FindAbsoluteLink(const AName: String): String;
-    function ResolveLink(AModule: TPasModule; const ALinkDest: String): String;
+    function ResolveLink(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
     function FindLinkedNode(ANode: TDocNode): TDocNode;
     function FindLinkedNode(ANode: TDocNode): TDocNode;
 
 
     // Documentation file support
     // Documentation file support
@@ -615,7 +621,6 @@ var
 begin
 begin
   for i := 0 to FPackages.Count - 1 do
   for i := 0 to FPackages.Count - 1 do
     TPasPackage(FPackages[i]).Release;
     TPasPackage(FPackages[i]).Release;
-  FPackages.Free;
   FRootDocNode.Free;
   FRootDocNode.Free;
   FRootLinkNode.Free;
   FRootLinkNode.Free;
   DescrDocNames.Free;
   DescrDocNames.Free;
@@ -977,11 +982,14 @@ end;
 
 
 var
 var
   s: String;
   s: String;
+  buf : Array[1..ContentBufSize-1] of byte;
+
 begin
 begin
   if not FileExists(AFileName) then
   if not FileExists(AFileName) then
     raise EInOutError.Create('File not found: ' + AFileName);
     raise EInOutError.Create('File not found: ' + AFileName);
   Assign(f, AFilename);
   Assign(f, AFilename);
   Reset(f);
   Reset(f);
+  SetTextBuf(F,Buf,SizeOf(Buf));
   while not EOF(f) do
   while not EOF(f) do
   begin
   begin
     ReadLn(f, s);
     ReadLn(f, s);
@@ -1031,9 +1039,11 @@ var
   ClassDecl: TPasClassType;
   ClassDecl: TPasClassType;
   Member: TPasElement;
   Member: TPasElement;
   s: String;
   s: String;
+  Buf : Array[0..ContentBufSize-1] of byte;
 begin
 begin
   Assign(ContentFile, AFilename);
   Assign(ContentFile, AFilename);
   Rewrite(ContentFile);
   Rewrite(ContentFile);
+  SetTextBuf(ContentFile,Buf,SizeOf(Buf));
   try
   try
     WriteLn(ContentFile, '# FPDoc Content File');
     WriteLn(ContentFile, '# FPDoc Content File');
     WriteLn(ContentFile, ':link tree');
     WriteLn(ContentFile, ':link tree');
@@ -1243,84 +1253,77 @@ begin
     SetLength(Result, 0);
     SetLength(Result, 0);
 end;
 end;
 
 
-function TFPDocEngine.ResolveLink(AModule: TPasModule;
-  const ALinkDest: String): String;
-var
-  i: Integer;
-  ThisPackage: TLinkNode;
-  UnitList: TFPList;
+function TFPDocEngine.ResolveLinkInPackages(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
 
 
-  function CanWeExit(AResult: string): boolean;
-  var
-    s: string;
-  begin
-    s := StringReplace(Lowercase(ALinkDest), '.', '_', [rfReplaceAll]);
-    Result := pos(s, AResult) > 0;
-  end;
+Var
+  ThisPackage: TLinkNode;
 
 
 begin
 begin
-  // system.WriteLn('ResolveLink(', AModule.Name, ' - ', ALinkDest, ')... ');
-  if Length(ALinkDest) = 0 then
-  begin
-    SetLength(Result, 0);
-    exit;
-  end;
-
-  if (ALinkDest[1] = '#') or (not assigned(AModule)) then
-    Result := FindAbsoluteLink(ALinkDest)
-  else
-  begin
-    if Pos(AModule.Name, ALinkDest) = 1 then
-    begin
-      Result := ResolveLink(AModule, amodule.packagename + '.' + ALinkDest);
-      if CanWeExit(Result) then
-        Exit;
-    end
-    else
+  { Try all packages }
+  Result:='';
+  ThisPackage:=RootLinkNode.FirstChild;
+  while Assigned(ThisPackage) and (Result='') do
     begin
     begin
-      Result := ResolveLink(AModule, AModule.PathName + '.' + ALinkDest);
-      if CanWeExit(Result) then
-        Exit;
+    Result:=ResolveLink(AModule, ThisPackage.Name + '.' + ALinkDest, Strict);
+    ThisPackage := ThisPackage.NextSibling;
     end;
     end;
+end;
 
 
-    { Try all packages }
-    SetLength(Result, 0);
-    ThisPackage := RootLinkNode.FirstChild;
-    while Assigned(ThisPackage) do
+function TFPDocEngine.ResolveLinkInUsedUnits(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
+
+var
+  i: Integer;
+  UL: TFPList;
+
+begin
+  Result:='';
+  UL:=AModule.InterfaceSection.UsesList;
+  I:=UL.Count-1;
+  While (Result='') and (I>=0) do
     begin
     begin
-      Result := ResolveLink(AModule, ThisPackage.Name + '.' + ALinkDest);
-      if CanWeExit(Result) then
-        Exit;
-      ThisPackage := ThisPackage.NextSibling;
+    Result:=ResolveLinkInPackages(AModule,TPasType(UL[i]).Name+'.'+ALinkDest, strict);
+    Dec(I);
     end;
     end;
+end;
 
 
-    if not CanWeExit(Result) then
+function TFPDocEngine.ResolveLink(AModule: TPasModule; const ALinkDest: String; Strict : Boolean = False): String;
+var
+  i: Integer;
+
+begin
+{
+  if Assigned(AModule) then
+      system.WriteLn('ResolveLink(', AModule.Name, ' - ', ALinkDest, ')... ')
+    else
+      system.WriteLn('ResolveLink(Nil - ', ALinkDest, ')... ');
+}
+  if (ALinkDest='') then
+    Exit('');
+  if (ALinkDest[1] = '#') then
+    Result := FindAbsoluteLink(ALinkDest)
+  else if (AModule=Nil) then
+    Result:= FindAbsoluteLink(RootLinkNode.FirstChild.Name+'.'+ALinkDest)
+  else
     begin
     begin
-      { Okay, then we have to try all imported units of the current module }
-      UnitList := AModule.InterfaceSection.UsesList;
-      for i := UnitList.Count - 1 downto 0 do
+    if Pos(AModule.Name,ALinkDest) = 1 then
+      Result := ResolveLink(AModule, AModule.packagename + '.' + ALinkDest, Strict)
+    else
+      Result := ResolveLink(AModule, AModule.PathName + '.' + ALinkDest, Strict);
+    if (Result='') then
       begin
       begin
-        { Try all packages }
-        ThisPackage := RootLinkNode.FirstChild;
-        while Assigned(ThisPackage) do
-        begin
-          Result := ResolveLink(AModule, ThisPackage.Name + '.' +
-            TPasType(UnitList[i]).Name + '.' + ALinkDest);
-            if CanWeExit(Result) then
-              Exit;
-          ThisPackage := ThisPackage.NextSibling;
-        end;
+      Result:=ResolveLinkInPackages(AModule,ALinkDest,Strict);
+      if (Result='') then
+        Result:=ResolveLinkInUsedUnits(Amodule,AlinkDest,Strict);
       end;
       end;
     end;
     end;
-  end;
-
-  if Length(Result) = 0 then
+  // Match on parent : class/enumerated/record/module
+  if (Result='') and not strict then
     for i := Length(ALinkDest) downto 1 do
     for i := Length(ALinkDest) downto 1 do
       if ALinkDest[i] = '.' then
       if ALinkDest[i] = '.' then
-      begin
-        Result := ResolveLink(AModule, Copy(ALinkDest, 1, i - 1));
+        begin
+        Result := ResolveLink(AModule, Copy(ALinkDest, 1, i - 1), Strict);
         exit;
         exit;
-      end;
+        end;
 end;
 end;
 
 
 procedure ReadXMLFileALT(OUT ADoc:TXMLDocument;const AFileName:ansistring);
 procedure ReadXMLFileALT(OUT ADoc:TXMLDocument;const AFileName:ansistring);

+ 32 - 52
utils/fpdoc/dw_html.pp

@@ -123,7 +123,7 @@ type
 
 
     Procedure CreateAllocator; virtual;
     Procedure CreateAllocator; virtual;
     procedure CreateCSSFile; virtual;
     procedure CreateCSSFile; virtual;
-    function ResolveLinkID(const Name: String): DOMString;
+    function ResolveLinkID(const Name: String; Level : Integer = 0): DOMString;
     function ResolveLinkIDInUnit(const Name,AUnitName: String): DOMString;
     function ResolveLinkIDInUnit(const Name,AUnitName: String): DOMString;
     function ResolveLinkWithinPackage(AElement: TPasElement;
     function ResolveLinkWithinPackage(AElement: TPasElement;
       ASubpageIndex: Integer): String;
       ASubpageIndex: Integer): String;
@@ -917,46 +917,13 @@ begin
     Result:=ResolveLinkID(AUnitName+'.'+Name);
     Result:=ResolveLinkID(AUnitName+'.'+Name);
 end;
 end;
 
 
-function THTMLWriter.ResolveLinkID(const Name: String): DOMString;
+function THTMLWriter.ResolveLinkID(const Name: String; Level : Integer = 0): DOMString;
+
 var
 var
   i: Integer;
   i: Integer;
   ThisPackage: TLinkNode;
   ThisPackage: TLinkNode;
 begin
 begin
-  if Length(Name) = 0 then
-  begin
-    SetLength(Result, 0);
-    exit;
-  end;
-
-  if Name[1] = '#' then
-    Result := Engine.FindAbsoluteLink(Name)
-  else
-  begin
-    SetLength(Result, 0);
-    { Try all packages }
-    ThisPackage := Engine.RootLinkNode.FirstChild;
-    while Assigned(ThisPackage) do
-    begin
-      Result := Engine.FindAbsoluteLink(ThisPackage.Name + '.' + Name);
-      if Length(Result) = 0 then
-      begin
-        if Assigned(Module) then
-          begin
-          Result := Engine.FindAbsoluteLink(Module.PathName + '.' + Name);
-//          WriteLn('Searching for ', Module.PathName + '.' + Name, ' => ', Result);
-          end;
-        if Length(Result) = 0 then
-          for i := Length(Name) downto 1 do
-            if Name[i] = '.' then
-            begin
-              Result := ResolveLinkID(Copy(Name, 1, i - 1));
-              exit;
-            end;
-      end;
-      ThisPackage := ThisPackage.NextSibling;
-    end;
-  end;
-
+  Result:=Engine.ResolveLink(Module,Name, False);
   if Length(Result) > 0 then
   if Length(Result) > 0 then
     if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
     if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
       Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
       Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
@@ -1192,7 +1159,7 @@ end;
 
 
 procedure THTMLWriter.DescrBeginLink(const AId: DOMString);
 procedure THTMLWriter.DescrBeginLink(const AId: DOMString);
 var
 var
-  a,s: String;
+  a,s,n : String;
 begin
 begin
   a:=AId;
   a:=AId;
   s := ResolveLinkID(a);
   s := ResolveLinkID(a);
@@ -1203,7 +1170,11 @@ begin
     else
     else
       s:='?';
       s:='?';
     if a='' then a:='<empty>';
     if a='' then a:='<empty>';
-    DoLog(SErrUnknownLinkID, [s,a]);
+    if Assigned(CurrentContext) then
+      N:=CurrentContext.Name
+    else
+      N:='?';
+    DoLog(SErrUnknownLinkID, [s,n,a]);
     PushOutputNode(CreateEl(CurOutputNode, 'b'));
     PushOutputNode(CreateEl(CurOutputNode, 'b'));
   end else
   end else
     PushOutputNode(CreateLink(CurOutputNode, s));
     PushOutputNode(CreateLink(CurOutputNode, s));
@@ -2146,7 +2117,7 @@ Procedure THTMLWriter.AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDoc
 var
 var
   Node: TDOMNode;
   Node: TDOMNode;
   TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
   TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
-  l,s: String;
+  l,s,n: String;
   f: Text;
   f: Text;
   IsFirstSeeAlso : Boolean;
   IsFirstSeeAlso : Boolean;
 
 
@@ -2177,7 +2148,11 @@ begin
          else
          else
            s:='?';
            s:='?';
          if l='' then l:='<empty>';
          if l='' then l:='<empty>';
-         DoLog(SErrUnknownLinkID, [s,l]);
+         if Assigned(AElement) then
+           N:=AElement.Name
+         else
+           N:='?';
+         DoLog(SErrUnknownLinkID, [s,N,l]);
          NewEl := CreateEl(ParaEl,'b')
          NewEl := CreateEl(ParaEl,'b')
          end
          end
        else
        else
@@ -3167,6 +3142,7 @@ var
     CurVisibility: TPasMemberVisibility;
     CurVisibility: TPasMemberVisibility;
     i: Integer;
     i: Integer;
     s: String;
     s: String;
+    t : TPasType;
     ah,ol,wt,ct,wc,cc  : boolean;
     ah,ol,wt,ct,wc,cc  : boolean;
     ThisInterface,
     ThisInterface,
     ThisClass: TPasClassType;
     ThisClass: TPasClassType;
@@ -3285,13 +3261,6 @@ var
           AppendSym(CodeEl, ' = ');
           AppendSym(CodeEl, ' = ');
           AppendText(CodeEl,TPasConst(Member).Expr.GetDeclaration(True));
           AppendText(CodeEl,TPasConst(Member).Expr.GetDeclaration(True));
           end
           end
-        else if (Member is TPasVariable) then
-          begin
-          AppendHyperlink(CodeEl, Member);
-          AppendSym(CodeEl, ': ');
-          AppendHyperlink(CodeEl, TPasVariable(Member).VarType);
-          AppendSym(CodeEl, ';');
-          end
         else if (Member is TPasType) then
         else if (Member is TPasType) then
           begin
           begin
           AppendHyperlink(CodeEl, Member);
           AppendHyperlink(CodeEl, Member);
@@ -3302,10 +3271,11 @@ var
           begin
           begin
           AppendKw(CodeEl, 'property ');
           AppendKw(CodeEl, 'property ');
           AppendHyperlink(CodeEl, Member);
           AppendHyperlink(CodeEl, Member);
-          if Assigned(TPasProperty(Member).VarType) then
+          t:=TPasProperty(Member).ResolvedType;
+          if Assigned(T) then
           begin
           begin
             AppendSym(CodeEl, ': ');
             AppendSym(CodeEl, ': ');
-            AppendHyperlink(CodeEl, TPasProperty(Member).VarType);
+            AppendHyperlink(CodeEl, T);
           end;
           end;
           AppendSym(CodeEl, ';');
           AppendSym(CodeEl, ';');
           if TPasProperty(Member).IsDefault then
           if TPasProperty(Member).IsDefault then
@@ -3329,6 +3299,13 @@ var
           if Length(s) > 0 then
           if Length(s) > 0 then
             AppendText(CodeEl, '  [' + s + ']');
             AppendText(CodeEl, '  [' + s + ']');
           end
           end
+        else if (Member is TPasVariable) then
+          begin
+          AppendHyperlink(CodeEl, Member);
+          AppendSym(CodeEl, ': ');
+          AppendHyperlink(CodeEl, TPasVariable(Member).VarType);
+          AppendSym(CodeEl, ';');
+          end
         else
         else
           AppendText(CreateWarning(CodeEl), '<' + Member.ClassName + '>');
           AppendText(CreateWarning(CodeEl), '<' + Member.ClassName + '>');
       end;
       end;
@@ -3602,15 +3579,18 @@ var
   procedure CreatePropertyPage(Element: TPasProperty);
   procedure CreatePropertyPage(Element: TPasProperty);
   var
   var
     NeedBreak: Boolean;
     NeedBreak: Boolean;
+    T : TPasType;
+
   begin
   begin
     AppendKw(CodeEl, 'property ');
     AppendKw(CodeEl, 'property ');
     AppendHyperlink(CodeEl, Element.Parent);
     AppendHyperlink(CodeEl, Element.Parent);
     AppendSym(CodeEl, '.');
     AppendSym(CodeEl, '.');
     AppendText(CodeEl, Element.Name);
     AppendText(CodeEl, Element.Name);
-    if Assigned(Element.VarType) then
+    T:=Element.ResolvedType;
+    if Assigned(T) then
     begin
     begin
       AppendSym(CodeEl, ' : ');
       AppendSym(CodeEl, ' : ');
-      AppendType(CodeEl, TableEl, Element.VarType, False);
+      AppendType(CodeEl, TableEl, T, False);
     end;
     end;
 
 
     NeedBreak := False;
     NeedBreak := False;

+ 66 - 55
utils/fpdoc/dwriter.pp

@@ -47,7 +47,7 @@ resourcestring
 
 
   SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
   SErrDescrTagUnknown = 'Warning: Unknown tag "%s" in description';
   SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
   SErrUnknownEntityReference = 'Warning: Unknown entity reference "&%s;" found';
-  SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s" is unknown: "%s"';
+  SErrUnknownLinkID = 'Warning: Target ID of <link> in unit "%s", element "%s", is unknown: "%s"';
   SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
   SErrUnknownPrintShortID = 'Warning: Target ID of <printshort> is unknown: "%s"';
   SErrUnknownLink = 'Could not resolve link to "%s"';
   SErrUnknownLink = 'Could not resolve link to "%s"';
   SErralreadyRegistered = 'Class for output format "%s" already registered';
   SErralreadyRegistered = 'Class for output format "%s" already registered';
@@ -75,6 +75,7 @@ type
     FEmitNotes: Boolean;
     FEmitNotes: Boolean;
     FEngine  : TFPDocEngine;
     FEngine  : TFPDocEngine;
     FPackage : TPasPackage;
     FPackage : TPasPackage;
+    FContext : TPasElement;
     FTopics  : TList;
     FTopics  : TList;
     FImgExt : String;
     FImgExt : String;
     FBeforeEmitNote : TWriterNoteEvent;
     FBeforeEmitNote : TWriterNoteEvent;
@@ -159,6 +160,7 @@ type
     procedure DescrEndTableRow; virtual; abstract;
     procedure DescrEndTableRow; virtual; abstract;
     procedure DescrBeginTableCell; virtual; abstract;
     procedure DescrBeginTableCell; virtual; abstract;
     procedure DescrEndTableCell; virtual; abstract;
     procedure DescrEndTableCell; virtual; abstract;
+    Property CurrentContext : TPasElement Read FContext ;
   public
   public
     Constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); virtual;
     Constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); virtual;
     destructor Destroy;  override;
     destructor Destroy;  override;
@@ -491,20 +493,24 @@ begin
   Result := False;
   Result := False;
   if not Assigned(El) then
   if not Assigned(El) then
     exit;
     exit;
-
-  Node := El.FirstChild;
-  while Assigned(Node) do
-  begin
-    if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'link') then
-      ConvertLink(AContext, TDOMElement(Node))
-    else if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'url') then
-      ConvertURL(AContext, TDOMElement(Node))
-    else
-      if not ConvertBaseShort(AContext, Node) then
-        exit;
-    Node := Node.NextSibling;
+  FContext:=AContext;
+  try
+    Node := El.FirstChild;
+    while Assigned(Node) do
+    begin
+      if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'link') then
+        ConvertLink(AContext, TDOMElement(Node))
+      else if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'url') then
+        ConvertURL(AContext, TDOMElement(Node))
+      else
+        if not ConvertBaseShort(AContext, Node) then
+          exit;
+      Node := Node.NextSibling;
+    end;
+    Result := True;
+  finally
+    FContext:=Nil;
   end;
   end;
-  Result := True;
 end;
 end;
 
 
 function TFPDocWriter.ConvertNotes(AContext: TPasElement; El: TDOMElement
 function TFPDocWriter.ConvertNotes(AContext: TPasElement; El: TDOMElement
@@ -732,53 +738,58 @@ var
   Node, Child: TDOMNode;
   Node, Child: TDOMNode;
   ParaCreated: Boolean;
   ParaCreated: Boolean;
 begin
 begin
-  if AutoInsertBlock then
-    if IsExtShort(El.FirstChild) then
-      DescrBeginParagraph
-    else
-      AutoInsertBlock := False;
+  FContext:=AContext;
+  try
+    if AutoInsertBlock then
+      if IsExtShort(El.FirstChild) then
+        DescrBeginParagraph
+      else
+        AutoInsertBlock := False;
 
 
-  Node := El.FirstChild;
-  if not ConvertExtShort(AContext, Node) then
-  begin
-    while Assigned(Node) do
+    Node := El.FirstChild;
+    if not ConvertExtShort(AContext, Node) then
     begin
     begin
-      if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'section') then
+      while Assigned(Node) do
       begin
       begin
-        DescrBeginSectionTitle;
-        Child := Node.FirstChild;
-        while Assigned(Child) and (Child.NodeType <> ELEMENT_NODE) do
+        if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'section') then
         begin
         begin
-          if not IsDescrNodeEmpty(Child) then
-            Warning(AContext, SErrInvalidContentBeforeSectionTitle);
-          Child := Child.NextSibling;
-        end;
-        if not Assigned(Child) or (Child.NodeName <> 'title') then
-          Warning(AContext, SErrSectionTitleExpected)
-        else
-          ConvertShort(AContext, TDOMElement(Child));
-
-        DescrBeginSectionBody;
-
-        if IsExtShort(Child) then
-        begin
-          DescrBeginParagraph;
-          ParaCreated := True;
-        end else
-          ParaCreated := False;
+          DescrBeginSectionTitle;
+          Child := Node.FirstChild;
+          while Assigned(Child) and (Child.NodeType <> ELEMENT_NODE) do
+          begin
+            if not IsDescrNodeEmpty(Child) then
+              Warning(AContext, SErrInvalidContentBeforeSectionTitle);
+            Child := Child.NextSibling;
+          end;
+          if not Assigned(Child) or (Child.NodeName <> 'title') then
+            Warning(AContext, SErrSectionTitleExpected)
+          else
+            ConvertShort(AContext, TDOMElement(Child));
 
 
-        ConvertExtShortOrNonSectionBlocks(AContext, Child.NextSibling);
+          DescrBeginSectionBody;
 
 
-        if ParaCreated then
-          DescrEndParagraph;
-        DescrEndSection;
-      end else if not ConvertNonSectionBlock(AContext, Node) then
-        Warning(AContext, SErrInvalidDescr, [Node.NodeName]);
-      Node := Node.NextSibling;
-    end;
-  end else
-    if AutoInsertBlock then
-      DescrEndParagraph;
+          if IsExtShort(Child) then
+          begin
+            DescrBeginParagraph;
+            ParaCreated := True;
+          end else
+            ParaCreated := False;
+
+          ConvertExtShortOrNonSectionBlocks(AContext, Child.NextSibling);
+
+          if ParaCreated then
+            DescrEndParagraph;
+          DescrEndSection;
+        end else if not ConvertNonSectionBlock(AContext, Node) then
+          Warning(AContext, SErrInvalidDescr, [Node.NodeName]);
+        Node := Node.NextSibling;
+      end;
+    end else
+      if AutoInsertBlock then
+        DescrEndParagraph;
+  finally
+    FContext:=Nil;
+  end;
 end;
 end;
 
 
 procedure TFPDocWriter.ConvertExtShortOrNonSectionBlocks(AContext: TPasElement;
 procedure TFPDocWriter.ConvertExtShortOrNonSectionBlocks(AContext: TPasElement;

Some files were not shown because too many files changed in this diff