Browse Source

Allow typecasts to inline specializations as well.

For this the code which handles this inside factor_read_id had to be moved to local unit scope and is named handle_factor_typenode.

git-svn-id: branches/svenbarth/generics@17541 -
svenbarth 14 years ago
parent
commit
66748692ef
1 changed files with 105 additions and 97 deletions
  1. 105 97
      compiler/pexpr.pas

+ 105 - 97
compiler/pexpr.pas

@@ -1285,6 +1285,107 @@ implementation
            end;
       end;
 
+    function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean):tnode;
+      var
+        srsym : tsym;
+        srsymtable : tsymtable;
+      begin
+         if try_to_consume(_LKLAMMER) then
+          begin
+            result:=comp_expr(true,false);
+            consume(_RKLAMMER);
+            { type casts to class helpers aren't allowed }
+            if is_objectpascal_helper(hdef) then
+              Message(parser_e_no_category_as_types)
+              { recovery by not creating a conversion node }
+            else
+              result:=ctypeconvnode.create_explicit(result,hdef);
+          end
+         else { not LKLAMMER }
+          if (token=_POINT) and
+             (is_object(hdef) or is_record(hdef)) then
+           begin
+             consume(_POINT);
+             { handles calling methods declared in parent objects
+               using "parentobject.methodname()" }
+             if assigned(current_structdef) and
+                not(getaddr) and
+                current_structdef.is_related(hdef) then
+               begin
+                 result:=ctypenode.create(hdef);
+                 { search also in inherited methods }
+                 searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
+                 if assigned(srsym) then
+                   check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                 consume(_ID);
+                 do_member_read(tabstractrecorddef(hdef),false,srsym,result,again,[]);
+               end
+             else
+              begin
+                { handles:
+                    * @TObject.Load
+                    * static methods and variables }
+                result:=ctypenode.create(hdef);
+                { TP allows also @TMenu.Load if Load is only }
+                { defined in an anchestor class              }
+                srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
+                if assigned(srsym) then
+                  begin
+                    check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                        consume(_ID);
+                        do_member_read(tabstractrecorddef(hdef),getaddr,srsym,result,again,[]);
+                  end
+                else
+                  Message1(sym_e_id_no_member,orgpattern);
+              end;
+           end
+         else
+          begin
+            { Normally here would be the check against the usage
+              of "TClassHelper.Something", but as that might be
+              used inside of system symbols like sizeof and
+              typeinfo this check is put into ttypenode.pass_1
+              (for "TClassHelper" alone) and tcallnode.pass_1
+              (for "TClassHelper.Something") }
+            { class reference ? }
+            if is_class(hdef) or
+               is_objcclass(hdef) then
+             begin
+               if getaddr and (token=_POINT) then
+                begin
+                  consume(_POINT);
+                  { allows @Object.Method }
+                  { also allows static methods and variables }
+                  result:=ctypenode.create(hdef);
+                  { TP allows also @TMenu.Load if Load is only }
+                  { defined in an anchestor class              }
+                  srsym:=search_struct_member(tobjectdef(hdef),pattern);
+                  if assigned(srsym) then
+                   begin
+                     check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                     consume(_ID);
+                     do_member_read(tabstractrecorddef(hdef),getaddr,srsym,result,again,[]);
+                   end
+                  else
+                   begin
+                     Message1(sym_e_id_no_member,orgpattern);
+                     consume(_ID);
+                   end;
+                end
+               else
+                begin
+                  result:=ctypenode.create(hdef);
+                  { For a type block we simply return only
+                    the type. For all other blocks we return
+                    a loadvmt node }
+                  if not(block_type in [bt_type,bt_const_type,bt_var_type]) then
+                    result:=cloadvmtaddrnode.create(result);
+                end;
+             end
+            else
+             result:=ctypenode.create(hdef);
+          end;
+      end;
 
 {****************************************************************************
                                Factor
@@ -2029,101 +2130,7 @@ implementation
                        if (hdef=cvarianttype) and
                           not(cs_compilesystem in current_settings.moduleswitches) then
                          current_module.flags:=current_module.flags or uf_uses_variants;
-                       if try_to_consume(_LKLAMMER) then
-                        begin
-                          p1:=comp_expr(true,false);
-                          consume(_RKLAMMER);
-                          { type casts to class helpers aren't allowed }
-                          if is_objectpascal_helper(hdef) then
-                            Message(parser_e_no_category_as_types)
-                            { recovery by not creating a conversion node }
-                          else
-                            p1:=ctypeconvnode.create_explicit(p1,hdef);
-                        end
-                       else { not LKLAMMER }
-                        if (token=_POINT) and
-                           (is_object(hdef) or is_record(hdef)) then
-                         begin
-                           consume(_POINT);
-                           { handles calling methods declared in parent objects
-                             using "parentobject.methodname()" }
-                           if assigned(current_structdef) and
-                              not(getaddr) and
-                              current_structdef.is_related(hdef) then
-                             begin
-                               p1:=ctypenode.create(hdef);
-                               { search also in inherited methods }
-                               searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
-                               if assigned(srsym) then
-                                 check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
-                               consume(_ID);
-                               do_member_read(tabstractrecorddef(hdef),false,srsym,p1,again,[]);
-                             end
-                           else
-                            begin
-                              { handles:
-                                  * @TObject.Load
-                                  * static methods and variables }
-                              p1:=ctypenode.create(hdef);
-                              { TP allows also @TMenu.Load if Load is only }
-                              { defined in an anchestor class              }
-                              srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
-                              if assigned(srsym) then
-                                begin
-                                  check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
-                                      consume(_ID);
-                                      do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[]);
-                                end
-                              else
-                                Message1(sym_e_id_no_member,orgpattern);
-                            end;
-                         end
-                       else
-                        begin
-                          { Normally here would be the check against the usage
-                            of "TClassHelper.Something", but as that might be
-                            used inside of system symbols like sizeof and
-                            typeinfo this check is put into ttypenode.pass_1
-                            (for "TClassHelper" alone) and tcallnode.pass_1
-                            (for "TClassHelper.Something") }
-                          { class reference ? }
-                          if is_class(hdef) or
-                             is_objcclass(hdef) then
-                           begin
-                             if getaddr and (token=_POINT) then
-                              begin
-                                consume(_POINT);
-                                { allows @Object.Method }
-                                { also allows static methods and variables }
-                                p1:=ctypenode.create(hdef);
-                                { TP allows also @TMenu.Load if Load is only }
-                                { defined in an anchestor class              }
-                                srsym:=search_struct_member(tobjectdef(hdef),pattern);
-                                if assigned(srsym) then
-                                 begin
-                                   check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
-                                   consume(_ID);
-                                   do_member_read(tabstractrecorddef(hdef),getaddr,srsym,p1,again,[]);
-                                 end
-                                else
-                                 begin
-                                   Message1(sym_e_id_no_member,orgpattern);
-                                   consume(_ID);
-                                 end;
-                              end
-                             else
-                              begin
-                                p1:=ctypenode.create(hdef);
-                                { For a type block we simply return only
-                                  the type. For all other blocks we return
-                                  a loadvmt node }
-                                if not(block_type in [bt_type,bt_const_type,bt_var_type]) then
-                                  p1:=cloadvmtaddrnode.create(p1);
-                              end;
-                           end
-                          else
-                           p1:=ctypenode.create(hdef);
-                        end;
+                       p1:=handle_factor_typenode(hdef,getaddr,again);
                      end;
                   end;
 
@@ -2951,8 +2958,9 @@ implementation
                        if is_class_or_interface_or_object(gendef) or
                            is_record(gendef) then
                          gendef:=tclassrefdef.create(gendef);
-                       p1:=ctypenode.create(gendef);
-                       again:=true;
+                       again:=false;
+                       { handle potential typecasts, etc }
+                       p1:=handle_factor_typenode(gendef,false,again);
                        { parse postfix operators }
                        if postfixoperators(p1,again,false) then
                          if assigned(p1) then