Selaa lähdekoodia

compiler: replace MODESWTICH POINTERARITHMETICS with $POINTERMATH directive, disable pointer arithmetic in delphi mode by default (compatible with delphi), enable pointer arithmetic in fpc/objfpc modes as they had it enabled by default before, add has_pointer_math field to tpointerdef to allow pointer arithmetic with such pointer even if pointer math mode is off (delphi compatible) + tests

git-svn-id: trunk@16651 -
paul 14 vuotta sitten
vanhempi
commit
86d3e41442

+ 3 - 0
.gitattributes

@@ -9641,6 +9641,9 @@ tests/test/tparray7.pp svneol=native#text/plain
 tests/test/tparray8.pp svneol=native#text/plain
 tests/test/tparray8.pp svneol=native#text/plain
 tests/test/tparray9.pp svneol=native#text/plain
 tests/test/tparray9.pp svneol=native#text/plain
 tests/test/tpftch1.pp svneol=native#text/plain
 tests/test/tpftch1.pp svneol=native#text/plain
+tests/test/tpointermath1.pp svneol=native#text/pascal
+tests/test/tpointermath2.pp svneol=native#text/pascal
+tests/test/tpointermath3.pp svneol=native#text/pascal
 tests/test/tpoll.pp svneol=native#text/plain
 tests/test/tpoll.pp svneol=native#text/plain
 tests/test/tprec1.pp svneol=native#text/plain
 tests/test/tprec1.pp svneol=native#text/plain
 tests/test/tprec10.pp svneol=native#text/plain
 tests/test/tprec10.pp svneol=native#text/plain

+ 4 - 4
compiler/globals.pas

@@ -51,15 +51,15 @@ interface
        delphimodeswitches =
        delphimodeswitches =
          [m_delphi,m_all,m_class,m_objpas,m_result,m_string_pchar,
          [m_delphi,m_all,m_class,m_objpas,m_result,m_string_pchar,
           m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
           m_pointer_2_procedure,m_autoderef,m_tp_procvar,m_initfinal,m_default_ansistring,
-          m_out,m_default_para,m_duplicate_names,m_hintdirective,m_add_pointer,
+          m_out,m_default_para,m_duplicate_names,m_hintdirective,
           m_property,m_default_inline,m_except,m_extended_records];
           m_property,m_default_inline,m_except,m_extended_records];
        fpcmodeswitches =
        fpcmodeswitches =
          [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
          [m_fpc,m_all,m_string_pchar,m_nested_comment,m_repeat_forward,
-          m_cvar_support,m_initfinal,m_add_pointer,m_hintdirective,
+          m_cvar_support,m_initfinal,m_hintdirective,
           m_property,m_default_inline];
           m_property,m_default_inline];
        objfpcmodeswitches =
        objfpcmodeswitches =
          [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
          [m_objfpc,m_fpc,m_all,m_class,m_objpas,m_result,m_string_pchar,m_nested_comment,
-          m_repeat_forward,m_cvar_support,m_initfinal,m_add_pointer,m_out,m_default_para,m_hintdirective,
+          m_repeat_forward,m_cvar_support,m_initfinal,m_out,m_default_para,m_hintdirective,
           m_property,m_default_inline,m_except];
           m_property,m_default_inline,m_except];
        tpmodeswitches =
        tpmodeswitches =
          [m_tp7,m_all,m_tp_procvar,m_duplicate_names];
          [m_tp7,m_all,m_tp_procvar,m_duplicate_names];
@@ -350,7 +350,7 @@ interface
         );
         );
         globalswitches : [cs_check_unit_name,cs_link_static];
         globalswitches : [cs_check_unit_name,cs_link_static];
         moduleswitches : [cs_extsyntax,cs_implicit_exceptions];
         moduleswitches : [cs_extsyntax,cs_implicit_exceptions];
-        localswitches : [cs_check_io,cs_typed_const_writable];
+        localswitches : [cs_check_io,cs_typed_const_writable,cs_pointermath];
         modeswitches : fpcmodeswitches;
         modeswitches : fpcmodeswitches;
         optimizerswitches : [];
         optimizerswitches : [];
         genwpoptimizerswitches : [];
         genwpoptimizerswitches : [];

+ 1 - 3
compiler/globtype.pas

@@ -110,7 +110,7 @@ interface
          cs_mmx,cs_mmx_saturation,
          cs_mmx,cs_mmx_saturation,
          { parser }
          { parser }
          cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
          cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
-         cs_varpropsetter,cs_scopedenums,
+         cs_varpropsetter,cs_scopedenums,cs_pointermath,
          { macpas specific}
          { macpas specific}
          cs_external_var, cs_externally_visible
          cs_external_var, cs_externally_visible
        );
        );
@@ -261,7 +261,6 @@ interface
                                   procedure variables                     }
                                   procedure variables                     }
          m_autoderef,           { does auto dereferencing of struct. vars }
          m_autoderef,           { does auto dereferencing of struct. vars }
          m_initfinal,           { initialization/finalization for units }
          m_initfinal,           { initialization/finalization for units }
-         m_add_pointer,         { allow pointer add/sub operations }
          m_default_ansistring,  { ansistring turned on by default }
          m_default_ansistring,  { ansistring turned on by default }
          m_out,                 { support the calling convention OUT }
          m_out,                 { support the calling convention OUT }
          m_default_para,        { support default parameters }
          m_default_para,        { support default parameters }
@@ -382,7 +381,6 @@ interface
          'POINTERTOPROCVAR',
          'POINTERTOPROCVAR',
          'AUTODEREF',
          'AUTODEREF',
          'INITFINAL',
          'INITFINAL',
-         'POINTERARITHMETICS',
          'ANSISTRINGS',
          'ANSISTRINGS',
          'OUT',
          'OUT',
          'DEFAULTPARAMETERS',
          'DEFAULTPARAMETERS',

+ 2 - 2
compiler/nadd.pas

@@ -1737,7 +1737,7 @@ implementation
             if nodetype=addn then
             if nodetype=addn then
               begin
               begin
                 if not(cs_extsyntax in current_settings.moduleswitches) or
                 if not(cs_extsyntax in current_settings.moduleswitches) or
-                   (not(is_pchar(ld)) and not(m_add_pointer in current_settings.modeswitches)) then
+                   (not(is_pchar(ld)) and not(cs_pointermath in current_settings.localswitches) and not tpointerdef(ld).has_pointer_math) then
                   CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
                   CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
                 if (rd.typ=pointerdef) and
                 if (rd.typ=pointerdef) and
                    (tpointerdef(rd).pointeddef.size>1) then
                    (tpointerdef(rd).pointeddef.size>1) then
@@ -1768,7 +1768,7 @@ implementation
                  if (lt=niln) then
                  if (lt=niln) then
                    CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),'NIL',rd.typename);
                    CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),'NIL',rd.typename);
                  if not(cs_extsyntax in current_settings.moduleswitches) or
                  if not(cs_extsyntax in current_settings.moduleswitches) or
-                    (not(is_pchar(ld)) and not(m_add_pointer in current_settings.modeswitches)) then
+                    (not(is_pchar(ld)) and not(cs_pointermath in current_settings.localswitches) and not tpointerdef(ld).has_pointer_math) then
                    CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
                    CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),ld.typename,rd.typename);
                  if (ld.typ=pointerdef) then
                  if (ld.typ=pointerdef) then
                  begin
                  begin

+ 2 - 1
compiler/nmem.pas

@@ -863,7 +863,8 @@ implementation
                  (except voidpointer) in delphi/tp7 it's only allowed for pchars. }
                  (except voidpointer) in delphi/tp7 it's only allowed for pchars. }
                if not is_voidpointer(left.resultdef) and
                if not is_voidpointer(left.resultdef) and
                   (
                   (
-                   (m_fpc in current_settings.modeswitches) or
+                   (cs_pointermath in current_settings.localswitches) or
+                   tpointerdef(left.resultdef).has_pointer_math or
                    is_pchar(left.resultdef) or
                    is_pchar(left.resultdef) or
                    is_pwidechar(left.resultdef)
                    is_pwidechar(left.resultdef)
                   ) then
                   ) then

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 {$endif Test_Double_checksum}
 
 
 const
 const
-  CurrentPPUVersion = 124;
+  CurrentPPUVersion = 125;
 
 
 { buffer sizes }
 { buffer sizes }
   maxentrysize = 1024;
   maxentrysize = 1024;

+ 6 - 0
compiler/scandir.pas

@@ -946,6 +946,11 @@ unit scandir;
       recordpendingverbosityfullswitch(switchesstatestack[switchesstatestackpos].verbosity);
       recordpendingverbosityfullswitch(switchesstatestack[switchesstatestackpos].verbosity);
     end;
     end;
 
 
+    procedure dir_pointermath;
+      begin
+        do_localswitch(cs_pointermath);
+      end;
+
     procedure dir_profile;
     procedure dir_profile;
       begin
       begin
         do_moduleswitch(cs_profile);
         do_moduleswitch(cs_profile);
@@ -1450,6 +1455,7 @@ unit scandir;
         AddDirective('PACKSET',directive_all, @dir_packset);
         AddDirective('PACKSET',directive_all, @dir_packset);
         AddDirective('PASCALMAINNAME',directive_all, @dir_pascalmainname);
         AddDirective('PASCALMAINNAME',directive_all, @dir_pascalmainname);
         AddDirective('PIC',directive_all, @dir_pic);
         AddDirective('PIC',directive_all, @dir_pic);
+        AddDirective('POINTERMATH',directive_all, @dir_pointermath);
         AddDirective('POP',directive_all, @dir_pop);
         AddDirective('POP',directive_all, @dir_pop);
         AddDirective('PROFILE',directive_all, @dir_profile);
         AddDirective('PROFILE',directive_all, @dir_profile);
         AddDirective('PUSH',directive_all, @dir_push);
         AddDirective('PUSH',directive_all, @dir_push);

+ 14 - 0
compiler/scanner.pas

@@ -378,6 +378,20 @@ implementation
                  include(init_settings.moduleswitches,cs_support_goto);
                  include(init_settings.moduleswitches,cs_support_goto);
              end;
              end;
 
 
+           { support pointer math by default in fpc/objfpc modes }
+           if ([m_fpc,m_objfpc] * current_settings.modeswitches <> []) then
+             begin
+               include(current_settings.localswitches,cs_pointermath);
+               if changeinit then
+                 include(init_settings.localswitches,cs_pointermath);
+             end
+           else
+             begin
+               exclude(current_settings.localswitches,cs_pointermath);
+               if changeinit then
+                 exclude(init_settings.localswitches,cs_pointermath);
+             end;
+
            { Default enum and set packing for delphi/tp7 }
            { Default enum and set packing for delphi/tp7 }
            if (m_tp7 in current_settings.modeswitches) or
            if (m_tp7 in current_settings.modeswitches) or
               (m_delphi in current_settings.modeswitches) then
               (m_delphi in current_settings.modeswitches) then

+ 6 - 0
compiler/symdef.pas

@@ -161,6 +161,7 @@ interface
 
 
        tpointerdef = class(tabstractpointerdef)
        tpointerdef = class(tabstractpointerdef)
           is_far : boolean;
           is_far : boolean;
+          has_pointer_math : boolean;
           constructor create(def:tdef);
           constructor create(def:tdef);
           constructor createfar(def:tdef);
           constructor createfar(def:tdef);
           function getcopy:tstoreddef;override;
           function getcopy:tstoreddef;override;
@@ -2085,6 +2086,7 @@ implementation
       begin
       begin
         inherited create(pointerdef,def);
         inherited create(pointerdef,def);
         is_far:=false;
         is_far:=false;
+        has_pointer_math:=cs_pointermath in current_settings.localswitches;
       end;
       end;
 
 
 
 
@@ -2092,6 +2094,7 @@ implementation
       begin
       begin
         inherited create(pointerdef,def);
         inherited create(pointerdef,def);
         is_far:=true;
         is_far:=true;
+        has_pointer_math:=cs_pointermath in current_settings.localswitches;
       end;
       end;
 
 
 
 
@@ -2099,6 +2102,7 @@ implementation
       begin
       begin
          inherited ppuload(pointerdef,ppufile);
          inherited ppuload(pointerdef,ppufile);
          is_far:=(ppufile.getbyte<>0);
          is_far:=(ppufile.getbyte<>0);
+         has_pointer_math:=(ppufile.getbyte<>0);
       end;
       end;
 
 
 
 
@@ -2112,6 +2116,7 @@ implementation
         else
         else
           result:=tpointerdef.create(pointeddef);
           result:=tpointerdef.create(pointeddef);
         tpointerdef(result).is_far:=is_far;
         tpointerdef(result).is_far:=is_far;
+        tpointerdef(result).has_pointer_math:=has_pointer_math;
         tpointerdef(result).savesize:=savesize;
         tpointerdef(result).savesize:=savesize;
       end;
       end;
 
 
@@ -2120,6 +2125,7 @@ implementation
       begin
       begin
          inherited ppuwrite(ppufile);
          inherited ppuwrite(ppufile);
          ppufile.putbyte(byte(is_far));
          ppufile.putbyte(byte(is_far));
+         ppufile.putbyte(byte(has_pointer_math));
          ppufile.writeentry(ibpointerdef);
          ppufile.writeentry(ibpointerdef);
       end;
       end;
 
 

+ 1 - 0
compiler/utils/ppudump.pp

@@ -1933,6 +1933,7 @@ begin
              write  (space,'     Pointed Type : ');
              write  (space,'     Pointed Type : ');
              readderef('');
              readderef('');
              writeln(space,'           Is Far : ',(getbyte<>0));
              writeln(space,'           Is Far : ',(getbyte<>0));
+             writeln(space,' Has Pointer Math : ',(getbyte<>0));
            end;
            end;
 
 
          iborddef :
          iborddef :

+ 24 - 0
tests/test/tpointermath1.pp

@@ -0,0 +1,24 @@
+{ %norun }
+program tpointermath1;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+type
+  {$POINTERMATH ON}
+  PByte = ^Byte; // Pointer arithmetic can be applied to types declared with PointerMath ON
+  {$POINTERMATH OFF}
+  PInteger = ^Integer;
+var
+  PB: PByte;
+  PI: PInteger;
+begin
+  // This checks even with PointerMath=Off it still can be used for types declared with PointerMath=On
+  PB := PB + 1;
+  WriteLn(PB[1]);
+  {$POINTERMATH ON}
+  // It can also be used if explicitely declared in the code
+  PI := PI + 1;
+  WriteLn(PI[1]);
+end.
+

+ 15 - 0
tests/test/tpointermath2.pp

@@ -0,0 +1,15 @@
+{ %fail }
+program tpointermath2;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+type
+  PByte = ^Byte;
+var
+  PB: PByte;
+begin
+  // Pointer math must fail in delphi mode without pointermath directive
+  PB := PB + 1;
+end.
+

+ 14 - 0
tests/test/tpointermath3.pp

@@ -0,0 +1,14 @@
+{ %norun }
+program tpointermath3;
+
+{$MODE FPC}
+type
+  PByte = ^Byte;
+var
+  PB: PByte;
+begin
+  // in FPC/ObjFPC mode pointer math is ON by default
+  PB := PB + 1;
+  WriteLn(PB[1]);
+end.
+