Browse Source

* further fixes for parsing declarations involving nested types that are
declared inside the the current structdef hierarchy: properly deal with
multiple types of the same name nested into each other, by keeping track
of at which point in the hierarchy we found the first type (and afterwards
continuing from there, instead of from any point in the hierarchy where
a type with this name can be found)

git-svn-id: trunk@17126 -

Jonas Maebe 14 years ago
parent
commit
8e788c6fa5
3 changed files with 70 additions and 14 deletions
  1. 1 0
      .gitattributes
  2. 52 14
      compiler/ptype.pas
  3. 17 0
      tests/test/tclass13a.pp

+ 1 - 0
.gitattributes

@@ -9530,6 +9530,7 @@ tests/test/tclass12b.pp svneol=native#text/pascal
 tests/test/tclass12c.pp svneol=native#text/pascal
 tests/test/tclass12c.pp svneol=native#text/pascal
 tests/test/tclass12d.pp svneol=native#text/plain
 tests/test/tclass12d.pp svneol=native#text/plain
 tests/test/tclass13.pp svneol=native#text/pascal
 tests/test/tclass13.pp svneol=native#text/pascal
+tests/test/tclass13a.pp svneol=native#text/plain
 tests/test/tclass14a.pp svneol=native#text/pascal
 tests/test/tclass14a.pp svneol=native#text/pascal
 tests/test/tclass14b.pp svneol=native#text/pascal
 tests/test/tclass14b.pp svneol=native#text/pascal
 tests/test/tclass2.pp svneol=native#text/plain
 tests/test/tclass2.pp svneol=native#text/plain

+ 52 - 14
compiler/ptype.pas

@@ -40,9 +40,6 @@ interface
 
 
     procedure resolve_forward_types;
     procedure resolve_forward_types;
 
 
-    { reads a type identifier }
-    procedure id_type(var def : tdef;isforwarddef:boolean);
-
     { reads a string, file type or a type identifier }
     { reads a string, file type or a type identifier }
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
 
 
@@ -389,10 +386,27 @@ implementation
       end;
       end;
 
 
 
 
-    procedure parse_nested_types(var def: tdef; isforwarddef: boolean);
+    procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef:boolean); forward;
+
+    { def is the outermost type in which other types have to be searched
+
+      isforward indicates whether the current definition can be a forward definition
+
+      if assigned, currentstructstack is a list of tabstractrecorddefs that, from
+      last to first, are child types of def that are not yet visible via the
+      normal symtable searching routines because they are types that are currently
+      being parsed (so using id_type on them after pushing def on the
+      symtablestack would result in errors because they'd come back as errordef)
+    }
+    procedure parse_nested_types(var def: tdef; isforwarddef: boolean; currentstructstack: tfpobjectlist);
       var
       var
         t2: tdef;
         t2: tdef;
+        structstackindex: longint;
       begin
       begin
+        if assigned(currentstructstack) then
+          structstackindex:=currentstructstack.count-1
+        else
+          structstackindex:=-1;
         { handle types inside classes, e.g. TNode.TLongint }
         { handle types inside classes, e.g. TNode.TLongint }
         while (token=_POINT) do
         while (token=_POINT) do
           begin
           begin
@@ -403,12 +417,23 @@ implementation
               end
               end
              else if is_class_or_object(def) or is_record(def) then
              else if is_class_or_object(def) or is_record(def) then
                begin
                begin
-                 symtablestack.push(tabstractrecorddef(def).symtable);
                  consume(_POINT);
                  consume(_POINT);
-                 t2:=generrordef;
-                 id_type(t2,isforwarddef);
-                 symtablestack.pop(tabstractrecorddef(def).symtable);
-                 def:=t2;
+                 if (structstackindex>=0) and
+                    (tabstractrecorddef(currentstructstack[structstackindex]).objname^=pattern) then
+                   begin
+                     def:=tdef(currentstructstack[structstackindex]);
+                     dec(structstackindex);
+                     consume(_ID);
+                   end
+                 else
+                   begin
+                     structstackindex:=-1;
+                     symtablestack.push(tabstractrecorddef(def).symtable);
+                     t2:=generrordef;
+                     id_type(t2,isforwarddef,false);
+                     symtablestack.pop(tabstractrecorddef(def).symtable);
+                     def:=t2;
+                   end;
                end
                end
              else
              else
                break;
                break;
@@ -419,17 +444,29 @@ implementation
     function try_parse_structdef_nested_type(out def: tdef; basedef: tabstractrecorddef; isfowarddef: boolean): boolean;
     function try_parse_structdef_nested_type(out def: tdef; basedef: tabstractrecorddef; isfowarddef: boolean): boolean;
       var
       var
         structdef : tabstractrecorddef;
         structdef : tabstractrecorddef;
+        structdefstack : tfpobjectlist;
       begin
       begin
          { use of current parsed object:
          { use of current parsed object:
            classes, objects, records can be used also in themself }
            classes, objects, records can be used also in themself }
          structdef:=basedef;
          structdef:=basedef;
+         structdefstack:=nil;
          while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
          while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
            begin
            begin
              if (structdef.objname^=pattern) then
              if (structdef.objname^=pattern) then
                begin
                begin
                  consume(_ID);
                  consume(_ID);
                  def:=structdef;
                  def:=structdef;
-                 parse_nested_types(def,isfowarddef);
+                 { we found the top-most match, now check how far down we can
+                   follow }
+                 structdefstack:=tfpobjectlist.create(false);
+                 structdef:=basedef;
+                 while (structdef<>def) do
+                   begin
+                     structdefstack.add(structdef);
+                     structdef:=tabstractrecorddef(structdef.owner.defowner);
+                   end;
+                 parse_nested_types(def,isfowarddef,structdefstack);
+                 structdefstack.free;
                  result:=true;
                  result:=true;
                  exit;
                  exit;
                end;
                end;
@@ -438,7 +475,7 @@ implementation
          result:=false;
          result:=false;
       end;
       end;
 
 
-    procedure id_type(var def : tdef;isforwarddef:boolean);
+    procedure id_type(var def : tdef;isforwarddef,checkcurrentrecdef:boolean);
     { reads a type definition }
     { reads a type definition }
     { to a appropriating tdef, s gets the name of   }
     { to a appropriating tdef, s gets the name of   }
     { the type to allow name mangling          }
     { the type to allow name mangling          }
@@ -456,7 +493,8 @@ implementation
          pos:=current_tokenpos;
          pos:=current_tokenpos;
          { use of current parsed object:
          { use of current parsed object:
            classes, objects, records can be used also in themself }
            classes, objects, records can be used also in themself }
-         if try_parse_structdef_nested_type(def,current_structdef,isforwarddef) then
+         if checkcurrentrecdef and
+            try_parse_structdef_nested_type(def,current_structdef,isforwarddef) then
            exit;
            exit;
          { Use the special searchsym_type that search only types }
          { Use the special searchsym_type that search only types }
          searchsym_type(s,srsym,srsymtable);
          searchsym_type(s,srsym,srsymtable);
@@ -558,8 +596,8 @@ implementation
                      end
                      end
                    else
                    else
                      begin
                      begin
-                       id_type(def,stoIsForwardDef in options);
-                       parse_nested_types(def,stoIsForwardDef in options);
+                       id_type(def,stoIsForwardDef in options,true);
+                       parse_nested_types(def,stoIsForwardDef in options,nil);
                      end;
                      end;
                  end;
                  end;
 
 

+ 17 - 0
tests/test/tclass13a.pp

@@ -0,0 +1,17 @@
+{ %norun }
+{$mode delphi}
+
+type
+  tc = class
+   type
+    tnest = class
+    end;
+  end;
+  td = class(tc)
+   type
+     tnest = class(tc.tnest)
+     end;
+  end;
+
+begin
+end.