Przeglądaj źródła

Fix for Mantis #24687.

pgenutil.pas:
  + add new function could_be_generic which checks whether a given symbol name could be a generic (which is determined using the genericdummysyms list for the current module)
pexpr.pas:
  * factor: only do a typecheck pass (postfixoperators does one as well) if the found node can not be a generic type
  * sub_expr: do a typecheck pass if it isn't a specialization

+ added test

git-svn-id: trunk@25579 -
svenbarth 12 lat temu
rodzic
commit
e8edbd29c0
4 zmienionych plików z 57 dodań i 6 usunięć
  1. 1 0
      .gitattributes
  2. 33 6
      compiler/pexpr.pas
  3. 7 0
      compiler/pgenutil.pas
  4. 16 0
      tests/webtbs/tw24867.pp

+ 1 - 0
.gitattributes

@@ -13585,6 +13585,7 @@ tests/webtbs/tw2483.pp svneol=native#text/plain
 tests/webtbs/tw24848.pp svneol=native#text/pascal
 tests/webtbs/tw24863.pp svneol=native#text/plain
 tests/webtbs/tw24865.pp svneol=native#text/pascal
+tests/webtbs/tw24867.pp svneol=native#text/pascal
 tests/webtbs/tw24871.pp svneol=native#text/pascal
 tests/webtbs/tw2492.pp svneol=native#text/plain
 tests/webtbs/tw2494.pp svneol=native#text/plain

+ 33 - 6
compiler/pexpr.pas

@@ -2825,12 +2825,15 @@ implementation
          hdef       : tdef;
          filepos    : tfileposinfo;
          callflags  : tcallnodeflags;
+         idstr      : tidstring;
+         dopostfix,
          again,
          updatefpos,
          nodechanged  : boolean;
       begin
         { can't keep a copy of p1 and compare pointers afterwards, because
           p1 may be freed and reallocated in the same place!  }
+        dopostfix:=true;
         updatefpos:=false;
         p1:=nil;
         filepos:=current_tokenpos;
@@ -2857,7 +2860,27 @@ implementation
               filepos:=current_tokenpos;
             end;
            { handle post fix operators }
-           updatefpos:=postfixoperators(p1,again,getaddr);
+           if (m_delphi in current_settings.modeswitches) and
+               (block_type=bt_body) and
+               (token in [_LT,_LSHARPBRACKET]) then
+             begin
+               if p1.nodetype=typen then
+                 idstr:=ttypenode(p1).typesym.name
+               else
+                 if (p1.nodetype=loadvmtaddrn) and
+                     (tloadvmtaddrnode(p1).left.nodetype=typen) then
+                   idstr:=ttypenode(tloadvmtaddrnode(p1).left).typesym.name
+                 else
+                   if (p1.nodetype=loadn) then
+                     idstr:=tloadnode(p1).symtableentry.name
+                   else
+                     idstr:='';
+               { if this is the case then the postfix handling is done in
+                 sub_expr if necessary }
+               dopostfix:=not could_be_generic(idstr);
+             end;
+           if dopostfix then
+             updatefpos:=postfixoperators(p1,again,getaddr);
          end
         else
          begin
@@ -3327,8 +3350,8 @@ implementation
            updatefpos:=true;
          end;
 
-        { get the resultdef for the node }
-        if (not assigned(p1.resultdef)) then
+        { get the resultdef for the node if nothing stops us }
+        if (not assigned(p1.resultdef)) and dopostfix then
           begin
             do_typecheckpass_changed(p1,nodechanged);
             updatefpos:=updatefpos or nodechanged;
@@ -3516,9 +3539,13 @@ implementation
                      begin
                        { this is a normal "<" comparison }
 
-                       { potential generic types that are followed by a "<" }
+                       { potential generic types that are followed by a "<": }
+
+                       { a) might not have their resultdef set }
+                       if not assigned(p1.resultdef) then
+                         do_typecheckpass(p1);
 
-                       { a) are not checked whether they are an undefined def,
+                       { b) are not checked whether they are an undefined def,
                             but not a generic parameter }
                        if (p1.nodetype=typen) and
                            (ttypenode(p1).typedef.typ=undefineddef) and
@@ -3530,7 +3557,7 @@ implementation
                            p1:=cerrornode.create;
                          end;
 
-                       { b) don't have their hints checked }
+                       { c) don't have their hints checked }
                        if istypenode(p1) then
                          begin
                            gendef:=gettypedef(p1);

+ 7 - 0
compiler/pgenutil.pas

@@ -43,6 +43,7 @@ uses
     function generate_generic_name(const name:tidstring;specializename:ansistring):tidstring;
     procedure split_generic_name(const name:tidstring;out nongeneric:string;out count:longint);
     function resolve_generic_dummysym(const name:tidstring):tsym;
+    function could_be_generic(const name:tidstring):boolean;inline;
 
     type
       tspecializationstate = record
@@ -1137,6 +1138,12 @@ uses
       end;
 
 
+    function could_be_generic(const name:tidstring):boolean;
+      begin
+        result:=(name<>'') and
+                  (current_module.genericdummysyms.findindexof(name)>=0);
+      end;
+
     procedure specialization_init(genericdef:tdef;var state: tspecializationstate);
     var
       pu : tused_unit;

+ 16 - 0
tests/webtbs/tw24867.pp

@@ -0,0 +1,16 @@
+{ %NORUN }
+
+program tw24867;
+
+{$MODE DELPHi}{$H+}
+{$APPTYPE CONSOLE}
+
+uses
+  fgl;
+
+var
+  d: TFPGMap<string, string>; // ok
+begin
+  d := TFPGMap<string, string>.Create; // Error: This type can't be a generic
+end.
+