Browse Source

Do not call ret_in_param of the current parameter manager when parsing a generic method/function. This fixes Mantis #21921.

* pparautl.pas, insert_funcret_para:
    assume that the result in a generic function/method can not be passed in a param
* pparautl.pas, insert_funcret_local: 
    don't call ret_in_param, but create the symbol as we need a valid funcretsym
* pstatmnt.pas, assembler_block:
    don't modify the framepointer for a generic method/function
* rautils.pas, TOperand.SetupResult:
    don't assume that we can't use the result for a generic function/method

git-svn-id: trunk@21608 -
svenbarth 13 years ago
parent
commit
d87b203a0a
5 changed files with 38 additions and 1 deletions
  1. 1 0
      .gitattributes
  2. 6 1
      compiler/pparautl.pas
  3. 2 0
      compiler/pstatmnt.pas
  4. 1 0
      compiler/rautils.pas
  5. 28 0
      tests/webtbs/tw21921.pp

+ 1 - 0
.gitattributes

@@ -12630,6 +12630,7 @@ tests/webtbs/tw2186.pp svneol=native#text/plain
 tests/webtbs/tw2187.pp svneol=native#text/plain
 tests/webtbs/tw2187.pp svneol=native#text/plain
 tests/webtbs/tw21878.pp svneol=native#text/plain
 tests/webtbs/tw21878.pp svneol=native#text/plain
 tests/webtbs/tw21914.pp svneol=native#text/pascal
 tests/webtbs/tw21914.pp svneol=native#text/pascal
+tests/webtbs/tw21921.pp svneol=native#text/pascal
 tests/webtbs/tw21941.pp svneol=native#text/pascal
 tests/webtbs/tw21941.pp svneol=native#text/pascal
 tests/webtbs/tw21951.pp svneol=native#text/plain
 tests/webtbs/tw21951.pp svneol=native#text/plain
 tests/webtbs/tw2196.pp svneol=native#text/plain
 tests/webtbs/tw2196.pp svneol=native#text/plain

+ 6 - 1
compiler/pparautl.pas

@@ -51,6 +51,7 @@ implementation
       begin
       begin
         if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
         if not(pd.proctypeoption in [potype_constructor,potype_destructor]) and
            not is_void(pd.returndef) and
            not is_void(pd.returndef) and
+           not (df_generic in pd.defoptions) and
            paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
            paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
          begin
          begin
            storepos:=current_tokenpos;
            storepos:=current_tokenpos;
@@ -243,7 +244,11 @@ implementation
 
 
            { We need to insert a varsym for the result in the localst
            { We need to insert a varsym for the result in the localst
              when it is returning in a register }
              when it is returning in a register }
-           if not paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
+           { we also need to do this for a generic procdef as we didn't allow
+             the creation of a result symbol in insert_funcret_para, but we need
+             a valid funcretsym }
+           if (df_generic in pd.defoptions) or
+               not paramanager.ret_in_param(pd.returndef,pd.proccalloption) then
             begin
             begin
               vs:=tlocalvarsym.create('$result',vs_value,pd.returndef,[vo_is_funcret]);
               vs:=tlocalvarsym.create('$result',vs_value,pd.returndef,[vo_is_funcret]);
               pd.localst.insert(vs);
               pd.localst.insert(vs);

+ 2 - 0
compiler/pstatmnt.pas

@@ -1382,6 +1382,7 @@ implementation
                 not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
                 not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
                 (not assigned(current_procinfo.procdef.funcretsym) or
                 (not assigned(current_procinfo.procdef.funcretsym) or
                  (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
                  (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
+                not (df_generic in current_procinfo.procdef.defoptions) and
                 not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
                 not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
                begin
                begin
                  { Only need to set the framepointer, the locals will
                  { Only need to set the framepointer, the locals will
@@ -1395,6 +1396,7 @@ implementation
           register.
           register.
         }
         }
         if assigned(current_procinfo.procdef.funcretsym) and
         if assigned(current_procinfo.procdef.funcretsym) and
+            not (df_generic in current_procinfo.procdef.defoptions) and
            (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
            (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef.proccalloption)) then
           tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
           tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
 
 

+ 1 - 0
compiler/rautils.pas

@@ -689,6 +689,7 @@ begin
     if (not is_void(returndef)) then
     if (not is_void(returndef)) then
       begin
       begin
         if (m_tp7 in current_settings.modeswitches) and
         if (m_tp7 in current_settings.modeswitches) and
+          not (df_generic in defoptions) and
           (not paramanager.ret_in_param(returndef,proccalloption)) then
           (not paramanager.ret_in_param(returndef,proccalloption)) then
           begin
           begin
             message(asmr_e_cannot_use_RESULT_here);
             message(asmr_e_cannot_use_RESULT_here);

+ 28 - 0
tests/webtbs/tw21921.pp

@@ -0,0 +1,28 @@
+{ %NORUN }
+
+program tw21921;
+
+{$mode Delphi}{$H+}
+
+type
+
+ { THashEntry }
+
+ THashEntry<T> = record
+   Key: string;
+   Value: T;
+   class function Create(const AKey: string; const AValue: T): THashEntry<T>; static; inline;
+ end;
+
+class function THashEntry<T>.Create(const AKey: string; const AValue: T): THashEntry<T>;
+begin
+  Result.Key := AKey;
+  Result.Value := AValue;
+end;
+
+var
+  Entry: THashEntry<Integer>;
+begin
+  Entry := THashEntry<Integer>.Create('One', 1);
+end.
+