Procházet zdrojové kódy

* fixed extended syntax checking {$x-} by moving it from the typecheck pass
to the parser, so that it only looks at what the programmer wrote rather
than at all statements that the compiler may generate internally
(mantis #11619)
+ several tests for {$x-} mode
* modified tenumerators1 so it compiles without extended syntax enabled
(to check for..in with {$x-})

git-svn-id: trunk@15075 -

Jonas Maebe před 15 roky
rodič
revize
a48a37d38b

+ 5 - 0
.gitattributes

@@ -9117,6 +9117,10 @@ tests/test/tmsg2.pp svneol=native#text/plain
 tests/test/tmsg3.pp svneol=native#text/plain
 tests/test/tmsg3.pp svneol=native#text/plain
 tests/test/tmsg4.pp svneol=native#text/plain
 tests/test/tmsg4.pp svneol=native#text/plain
 tests/test/tmt1.pp svneol=native#text/plain
 tests/test/tmt1.pp svneol=native#text/plain
+tests/test/tnoext1.pp svneol=native#text/plain
+tests/test/tnoext2.pp svneol=native#text/plain
+tests/test/tnoext3.pp svneol=native#text/plain
+tests/test/tnoext4.pp svneol=native#text/plain
 tests/test/tobjc1.pp svneol=native#text/plain
 tests/test/tobjc1.pp svneol=native#text/plain
 tests/test/tobjc10.pp svneol=native#text/plain
 tests/test/tobjc10.pp svneol=native#text/plain
 tests/test/tobjc11.pp svneol=native#text/plain
 tests/test/tobjc11.pp svneol=native#text/plain
@@ -10086,6 +10090,7 @@ tests/webtbs/tw11568.pp svneol=native#text/plain
 tests/webtbs/tw1157.pp svneol=native#text/plain
 tests/webtbs/tw1157.pp svneol=native#text/plain
 tests/webtbs/tw1157b.pp svneol=native#text/plain
 tests/webtbs/tw1157b.pp svneol=native#text/plain
 tests/webtbs/tw11619.pp svneol=native#text/plain
 tests/webtbs/tw11619.pp svneol=native#text/plain
+tests/webtbs/tw11619a.pp svneol=native#text/plain
 tests/webtbs/tw11638.pp svneol=native#text/plain
 tests/webtbs/tw11638.pp svneol=native#text/plain
 tests/webtbs/tw11711.pp svneol=native#text/plain
 tests/webtbs/tw11711.pp svneol=native#text/plain
 tests/webtbs/tw11762.pp svneol=native#text/plain
 tests/webtbs/tw11762.pp svneol=native#text/plain

+ 0 - 17
compiler/nbas.pas

@@ -396,14 +396,6 @@ implementation
 
 
          { left is the statement itself calln assignn or a complex one }
          { left is the statement itself calln assignn or a complex one }
          typecheckpass(left);
          typecheckpass(left);
-         if (not (cs_extsyntax in current_settings.moduleswitches)) and
-            assigned(left.resultdef) and
-            not((left.nodetype=calln) and
-                { don't complain when the value is used. And also not for constructors }
-                ((cnf_return_value_used in tcallnode(left).callnodeflags) or
-                 (tcallnode(left).procdefinition.proctypeoption=potype_constructor))) and
-            not(is_void(left.resultdef)) then
-           CGMessage(parser_e_illegal_expression);
          if codegenerror then
          if codegenerror then
            exit;
            exit;
 
 
@@ -502,15 +494,6 @@ implementation
                 begin
                 begin
                    codegenerror:=false;
                    codegenerror:=false;
                    typecheckpass(hp.left);
                    typecheckpass(hp.left);
-                   if not(codegenerror) and
-                      not(cs_extsyntax in current_settings.moduleswitches) and
-                      (hp.left.nodetype=calln) and
-                      not(is_void(hp.left.resultdef)) and
-                      not(cnf_return_value_used in tcallnode(hp.left).callnodeflags) and
-                      not((tcallnode(hp.left).procdefinition.proctypeoption=potype_constructor) and
-                          assigned(tprocdef(tcallnode(hp.left).procdefinition)._class) and
-                          is_object(tprocdef(tcallnode(hp.left).procdefinition)._class)) then
-                     CGMessagePos(hp.left.fileinfo,parser_e_illegal_expression);
                    { the resultdef of the block is the last type that is
                    { the resultdef of the block is the last type that is
                      returned. Normally this is a voidtype. But when the
                      returned. Normally this is a voidtype. But when the
                      compiler inserts a block of multiple statements then the
                      compiler inserts a block of multiple statements then the

+ 14 - 3
compiler/pstatmnt.pas

@@ -1171,13 +1171,24 @@ implementation
 
 
              if not assigned(p.resultdef) then
              if not assigned(p.resultdef) then
                do_typecheckpass(p);
                do_typecheckpass(p);
+
              { Specify that we don't use the value returned by the call.
              { Specify that we don't use the value returned by the call.
                This is used for :
                This is used for :
                 - dispose of temp stack space
                 - dispose of temp stack space
-                - dispose on FPU stack }
+                - dispose on FPU stack
+                - extended syntax checking }
              if (p.nodetype=calln) then
              if (p.nodetype=calln) then
-               exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
-
+               begin
+                 exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
+
+                 { in {$x-} state, the function result must not be ignored }
+                 if not(cs_extsyntax in current_settings.moduleswitches) and
+                    not(is_void(p.resultdef)) and
+                    not((tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
+                        assigned(tprocdef(tcallnode(p).procdefinition)._class) and
+                        is_object(tprocdef(tcallnode(p).procdefinition)._class)) then
+                   Message(parser_e_illegal_expression);
+               end;
              code:=p;
              code:=p;
            end;
            end;
          end;
          end;

+ 23 - 18
tests/test/tenumerators1.pp

@@ -4,6 +4,7 @@ program tenumerators1;
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 {$endif}
 {$endif}
 {$apptype console}
 {$apptype console}
+{$x-}
 uses
 uses
   Classes;
   Classes;
 
 
@@ -18,12 +19,13 @@ var
   Item: Pointer;
   Item: Pointer;
   List: TFPList;
   List: TFPList;
   Enumerator: TFPListEnumerator;
   Enumerator: TFPListEnumerator;
+  i: integer;
 begin
 begin
   // check TFPList enumerator
   // check TFPList enumerator
   List := TFPList.Create;
   List := TFPList.Create;
-  List.Add(Pointer(1));
-  List.Add(Pointer(2));
-  List.Add(Pointer(3));
+  i:=List.Add(Pointer(1));
+  i:=List.Add(Pointer(2));
+  i:=List.Add(Pointer(3));
 
 
   Enumerator := List.GetEnumerator;
   Enumerator := List.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do
@@ -41,12 +43,13 @@ var
   Item: Pointer;
   Item: Pointer;
   List: TList;
   List: TList;
   Enumerator: TListEnumerator;
   Enumerator: TListEnumerator;
+  i: integer;
 begin
 begin
   // check TList enumerator
   // check TList enumerator
   List := TList.Create;
   List := TList.Create;
-  List.Add(Pointer(1));
-  List.Add(Pointer(2));
-  List.Add(Pointer(3));
+  i:=List.Add(Pointer(1));
+  i:=List.Add(Pointer(2));
+  i:=List.Add(Pointer(3));
 
 
   Enumerator := List.GetEnumerator;
   Enumerator := List.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do
@@ -66,9 +69,9 @@ var
 begin
 begin
   // check TCollection enumerator
   // check TCollection enumerator
   Collection := TCollection.Create(TCollectionItem);
   Collection := TCollection.Create(TCollectionItem);
-  Collection.Add;
-  Collection.Add;
-  Collection.Add;
+  item:=Collection.Add;
+  item:=Collection.Add;
+  item:=Collection.Add;
 
 
   Enumerator := Collection.GetEnumerator;
   Enumerator := Collection.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do
@@ -85,12 +88,13 @@ var
   Item: String;
   Item: String;
   Strings: TStrings;
   Strings: TStrings;
   Enumerator: TStringsEnumerator;
   Enumerator: TStringsEnumerator;
+  i: integer;
 begin
 begin
   // check TStrings enumerator
   // check TStrings enumerator
   Strings := TStringList.Create;
   Strings := TStringList.Create;
-  Strings.Add('1');
-  Strings.Add('2');
-  Strings.Add('3');
+  i:=Strings.Add('1');
+  i:=Strings.Add('2');
+  i:=Strings.Add('3');
 
 
   Enumerator := Strings.GetEnumerator;
   Enumerator := Strings.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do
@@ -110,9 +114,9 @@ var
 begin
 begin
   // check TComponent enumerator
   // check TComponent enumerator
   Component := TComponent.Create(nil);
   Component := TComponent.Create(nil);
-  TComponent.Create(Component);
-  TComponent.Create(Component);
-  TComponent.Create(Component);
+  item:=TComponent.Create(Component);
+  item:=TComponent.Create(Component);
+  item:=TComponent.Create(Component);
 
 
   Enumerator := Component.GetEnumerator;
   Enumerator := Component.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do
@@ -129,15 +133,16 @@ var
   Item: IUnknown;
   Item: IUnknown;
   List: TInterfaceList;
   List: TInterfaceList;
   Enumerator: TInterfaceListEnumerator;
   Enumerator: TInterfaceListEnumerator;
+  i: integer;
 begin
 begin
   // check TInterfaceList enumerator
   // check TInterfaceList enumerator
   List := TInterfaceList.Create;
   List := TInterfaceList.Create;
   Item := TInterfacedObject.Create;
   Item := TInterfacedObject.Create;
-  List.Add(Item);
+  i:=List.Add(Item);
   Item := TInterfacedObject.Create;
   Item := TInterfacedObject.Create;
-  List.Add(Item);
+  i:=List.Add(Item);
   Item := TInterfacedObject.Create;
   Item := TInterfacedObject.Create;
-  List.Add(Item);
+  i:=List.Add(Item);
 
 
   Enumerator := List.GetEnumerator;
   Enumerator := List.GetEnumerator;
   while Enumerator.MoveNext do
   while Enumerator.MoveNext do

+ 10 - 0
tests/test/tnoext1.pp

@@ -0,0 +1,10 @@
+{ %fail }
+{$x-}
+
+function f: longint;
+begin
+end;
+
+begin
+  f;
+end.

+ 7 - 0
tests/test/tnoext2.pp

@@ -0,0 +1,7 @@
+{ %fail }
+{$mode objfpc}
+{$x-}
+
+begin
+  tobject.create;
+end.

+ 100 - 0
tests/test/tnoext3.pp

@@ -0,0 +1,100 @@
+{ %norun }
+{$x-}
+uses
+  variants;
+
+type
+  tobj = object
+    constructor init;
+    destructor done;
+  end;
+   
+ constructor tobj.init;
+   begin
+   end;
+
+ destructor tobj.done;
+   begin
+   end;
+
+procedure testcomplexassignments;
+var
+  s1,s2: shortstring;
+  a1,a2: ansistring;
+  w1,w2: widestring;
+  u1,u2: unicodestring;
+  v1,v2: variant;
+  arr: array[1..4] of char;
+  c: char;
+  wc: widechar;
+  p: pchar;
+  pw: pwidechar;
+  darr: array of char;
+begin
+  s1:=s2;
+  a1:=a2;
+  w1:=w2;
+  u1:=u2;
+  v1:=v2;
+  s1:=arr;
+  a1:=arr;
+  w1:=arr;
+  u1:=arr;
+  arr:=s1;
+  arr:=a1;
+  arr:=w1;
+  arr:=u1;
+  s1:=c;
+  a1:=c;
+  w1:=c;
+  u1:=c;
+  s1:=wc;
+  a1:=wc;
+  w1:=wc;
+  u1:=wc;
+  s1:=p;
+  a1:=p;
+  w1:=p;
+  u1:=p;
+  s1:=pw;
+  a1:=pw;
+  w1:=pw;
+  u1:=pw;
+  v1:=darr;
+end;
+
+
+procedure testval;
+var
+  ss: shortstring;
+  b: byte;
+  w: word;
+  c: cardinal;
+  q: qword;
+  si: shortint;
+  i: smallint;
+  l: longint;
+  ii: int64;
+begin
+  val(ss,b,w);
+  val(ss,c,b);
+{$ifdef cpu64}
+  val(ss,c,q);
+{$endif}
+  val(ss,q,si);
+  val(ss,si,i);
+  val(ss,i,l);
+{$ifdef cpu64}
+  val(ss,l,ii);
+{$endif}
+  val(ss,ii,l);
+end;
+
+var
+  o: tobj;
+  po: ^tobj;
+begin
+  o.init;
+  new(po,init);
+  dispose(po,done);
+end.

+ 21 - 0
tests/test/tnoext4.pp

@@ -0,0 +1,21 @@
+{ %norun }
+{$mode objfpc}
+{x-}
+
+type
+ tr = record end;
+
+operator +(const r1,r2: tr) res: tr;
+begin
+end;
+
+operator:=(const r: tr) res: longint;
+begin
+end;
+
+var
+ r1, r2: tr;
+ l:longint;
+begin
+  l:=r1+r2;
+end.

+ 26 - 0
tests/webtbs/tw11619a.pp

@@ -0,0 +1,26 @@
+{ %norun }
+{$mode objfpc}
+{$inline on}
+{$x-}
+
+function Min(a, b: Double): Double;inline;
+begin
+  if a < b then
+    Result := a
+  else
+    Result := b;
+end;
+
+function Max(a, b: Double): Double;inline;
+begin
+  if a > b then
+    Result := a
+  else
+    Result := b;
+end;
+
+var
+  a, b: double;
+begin
+  a:=min(max(a,b),min(a,b));
+end.