Browse Source

* synchronized with trunk

git-svn-id: branches/wasm@47896 -
nickysn 4 years ago
parent
commit
57b976535f

+ 2 - 0
.gitattributes

@@ -18108,6 +18108,7 @@ tests/webtbs/tw2886.pp svneol=native#text/plain
 tests/webtbs/tw2891.pp svneol=native#text/plain
 tests/webtbs/tw2891.pp svneol=native#text/plain
 tests/webtbs/tw28916.pp svneol=native#text/pascal
 tests/webtbs/tw28916.pp svneol=native#text/pascal
 tests/webtbs/tw2892.pp svneol=native#text/plain
 tests/webtbs/tw2892.pp svneol=native#text/plain
+tests/webtbs/tw28927.pp svneol=native#text/pascal
 tests/webtbs/tw28934.pp svneol=native#text/plain
 tests/webtbs/tw28934.pp svneol=native#text/plain
 tests/webtbs/tw28948.pp svneol=native#text/plain
 tests/webtbs/tw28948.pp svneol=native#text/plain
 tests/webtbs/tw28964.pp svneol=native#text/plain
 tests/webtbs/tw28964.pp svneol=native#text/plain
@@ -18657,6 +18658,7 @@ tests/webtbs/tw38202.pp svneol=native#text/pascal
 tests/webtbs/tw38225.pp svneol=native#text/pascal
 tests/webtbs/tw38225.pp svneol=native#text/pascal
 tests/webtbs/tw38238.pp svneol=native#text/pascal
 tests/webtbs/tw38238.pp svneol=native#text/pascal
 tests/webtbs/tw38249.pp svneol=native#text/pascal
 tests/webtbs/tw38249.pp svneol=native#text/pascal
+tests/webtbs/tw38259.pp svneol=native#text/pascal
 tests/webtbs/tw3827.pp svneol=native#text/plain
 tests/webtbs/tw3827.pp svneol=native#text/plain
 tests/webtbs/tw3829.pp svneol=native#text/plain
 tests/webtbs/tw3829.pp svneol=native#text/plain
 tests/webtbs/tw3833.pp svneol=native#text/plain
 tests/webtbs/tw3833.pp svneol=native#text/plain

+ 15 - 3
compiler/optdfa.pas

@@ -508,20 +508,32 @@ unit optdfa;
 
 
             exitn:
             exitn:
               begin
               begin
-                if not(is_void(current_procinfo.procdef.returndef)) then
+                { in case of inlining, an exit node can have a successor, in this case, we do not have to
+                  use the faked resultnode }
+                if assigned(node.successor) then
+                  begin
+                    l:=node.optinfo^.life;
+                    DFASetIncludeSet(l,node.successor.optinfo^.life);
+                    UpdateLifeInfo(node,l);
+                  end
+                else if assigned(resultnode) and (resultnode.nodetype<>nothingn) then
                   begin
                   begin
                     if not(assigned(node.optinfo^.def)) and
                     if not(assigned(node.optinfo^.def)) and
                        not(assigned(node.optinfo^.use)) then
                        not(assigned(node.optinfo^.use)) then
                       begin
                       begin
                         if assigned(texitnode(node).left) then
                         if assigned(texitnode(node).left) then
                           begin
                           begin
-                            node.optinfo^.def:=resultnode.optinfo^.def;
+{                           this should never happen as
+                            texitnode.pass_typecheck converts the left node into a separate node already
+
+                             node.optinfo^.def:=resultnode.optinfo^.def;
 
 
                             dfainfo.use:[email protected]^.use;
                             dfainfo.use:[email protected]^.use;
                             dfainfo.def:[email protected]^.def;
                             dfainfo.def:[email protected]^.def;
                             dfainfo.map:=map;
                             dfainfo.map:=map;
                             foreachnodestatic(pm_postprocess,texitnode(node).left,@AddDefUse,@dfainfo);
                             foreachnodestatic(pm_postprocess,texitnode(node).left,@AddDefUse,@dfainfo);
-                            calclife(node);
+                            calclife(node); }
+                            Internalerror(2020122901);
                           end
                           end
                         else
                         else
                           begin
                           begin

+ 8 - 2
compiler/optutils.pas

@@ -163,11 +163,12 @@ unit optutils;
       var
       var
         Continuestack : TFPList;
         Continuestack : TFPList;
         Breakstack : TFPList;
         Breakstack : TFPList;
+        Exitsuccessor: TNode;
       { sets the successor nodes of a node tree block
       { sets the successor nodes of a node tree block
         returns the first node of the tree if it's a controll flow node }
         returns the first node of the tree if it's a controll flow node }
       function DoSet(p : tnode;succ : tnode) : tnode;
       function DoSet(p : tnode;succ : tnode) : tnode;
         var
         var
-          hp1,hp2 : tnode;
+          hp1,hp2, oldexitsuccessor: tnode;
           i : longint;
           i : longint;
         begin
         begin
           result:=nil;
           result:=nil;
@@ -203,11 +204,15 @@ unit optutils;
             blockn:
             blockn:
               begin
               begin
                 result:=p;
                 result:=p;
+                oldexitsuccessor:=Exitsuccessor;
+                if nf_block_with_exit in p.flags then
+                  Exitsuccessor:=succ;
                 DoSet(tblocknode(p).statements,succ);
                 DoSet(tblocknode(p).statements,succ);
                 if assigned(tblocknode(p).statements) then
                 if assigned(tblocknode(p).statements) then
                   p.successor:=tblocknode(p).statements
                   p.successor:=tblocknode(p).statements
                 else
                 else
                   p.successor:=succ;
                   p.successor:=succ;
+                Exitsuccessor:=oldexitsuccessor;
               end;
               end;
             forn:
             forn:
               begin
               begin
@@ -288,7 +293,7 @@ unit optutils;
             exitn:
             exitn:
               begin
               begin
                 result:=p;
                 result:=p;
-                p.successor:=nil;
+                p.successor:=Exitsuccessor;
               end;
               end;
             casen:
             casen:
               begin
               begin
@@ -337,6 +342,7 @@ unit optutils;
       begin
       begin
         Breakstack:=TFPList.Create;
         Breakstack:=TFPList.Create;
         Continuestack:=TFPList.Create;
         Continuestack:=TFPList.Create;
+        Exitsuccessor:=nil;
         DoSet(p,last);
         DoSet(p,last);
         Continuestack.Free;
         Continuestack.Free;
         Breakstack.Free;
         Breakstack.Free;

+ 9 - 0
compiler/ptype.pas

@@ -992,6 +992,7 @@ implementation
          old_parse_generic: boolean;
          old_parse_generic: boolean;
          recst: trecordsymtable;
          recst: trecordsymtable;
          hadgendummy : boolean;
          hadgendummy : boolean;
+         alignment: Integer;
       begin
       begin
          old_current_structdef:=current_structdef;
          old_current_structdef:=current_structdef;
          old_current_genericdef:=current_genericdef;
          old_current_genericdef:=current_genericdef;
@@ -1063,6 +1064,14 @@ implementation
                add_typedconst_init_routine(current_structdef);
                add_typedconst_init_routine(current_structdef);
              consume(_END);
              consume(_END);
             end;
             end;
+         if (token=_ID) and (pattern='ALIGN') then
+           begin
+             consume(_ID);
+             alignment:=get_intconst.svalue;
+             if not(alignment in [1,2,4,8,16,32,64]) then
+             else
+               recst.recordalignment:=shortint(alignment);
+           end;
          { make the record size aligned (has to be done before inserting the
          { make the record size aligned (has to be done before inserting the
            parameters, because that may depend on the record's size) }
            parameters, because that may depend on the record's size) }
          recst.addalignmentpadding;
          recst.addalignmentpadding;

+ 1 - 1
compiler/x86/nx86inl.pas

@@ -651,7 +651,7 @@ implementation
            LOC_MMREGISTER,LOC_CMMREGISTER:
            LOC_MMREGISTER,LOC_CMMREGISTER:
              begin
              begin
                location:=lnode.location;
                location:=lnode.location;
-               hlcg.location_force_fpureg(current_asmdata.CurrAsmList,location,resultdef,false);
+               hlcg.location_force_fpureg(current_asmdata.CurrAsmList,location,lnode.resultdef,false);
              end;
              end;
            else
            else
              internalerror(309991);
              internalerror(309991);

+ 32 - 28
packages/fcl-passrc/src/pasresolveeval.pas

@@ -4147,10 +4147,12 @@ function TResExprEvaluator.EvalPrimitiveExprString(Expr: TPrimitiveExpr
  //   Source codepage is needed for reading non ASCII string literals 'ä'.
  //   Source codepage is needed for reading non ASCII string literals 'ä'.
  //   Target codepage is needed for reading non ASCII # literals.
  //   Target codepage is needed for reading non ASCII # literals.
  //   Target codepage costs time to compute.
  //   Target codepage costs time to compute.
+var
+  Value: TResEvalValue;
 
 
   procedure RangeError(id: TMaxPrecInt);
   procedure RangeError(id: TMaxPrecInt);
   begin
   begin
-    Result.Free;
+    Value.Free;
     RaiseRangeCheck(id,Expr);
     RaiseRangeCheck(id,Expr);
   end;
   end;
 
 
@@ -4183,13 +4185,13 @@ var
   var
   var
     h: RawByteString;
     h: RawByteString;
   begin
   begin
-    if Result.Kind=revkString then
+    if Value.Kind=revkString then
       begin
       begin
       // switch to unicodestring
       // switch to unicodestring
-      h:=TResEvalString(Result).S;
-      Result.Free;
-      Result:=nil; // in case of exception in GetUnicodeStr
-      Result:=TResEvalUTF16.CreateValue(GetUnicodeStr(h,Expr));
+      h:=TResEvalString(Value).S;
+      Value.Free;
+      Value:=nil; // in case of exception in GetUnicodeStr
+      Value:=TResEvalUTF16.CreateValue(GetUnicodeStr(h,Expr));
       end;
       end;
   end;
   end;
 {$ENDIF}
 {$ENDIF}
@@ -4197,7 +4199,7 @@ var
   procedure AddSrc(h: String);
   procedure AddSrc(h: String);
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
   var
   var
-    Value: TResEvalString;
+    ValueAnsi: TResEvalString;
     OnlyASCII: Boolean;
     OnlyASCII: Boolean;
     i: Integer;
     i: Integer;
   {$ENDIF}
   {$ENDIF}
@@ -4216,13 +4218,13 @@ var
         break;
         break;
         end;
         end;
 
 
-    if Result.Kind=revkString then
+    if Value.Kind=revkString then
       begin
       begin
-      Value:=TResEvalString(Result);
-      if OnlyASCII and Value.OnlyASCII then
+      ValueAnsi:=TResEvalString(Value);
+      if OnlyASCII and ValueAnsi.OnlyASCII then
         begin
         begin
         // concatenate ascii strings
         // concatenate ascii strings
-        Value.S:=Value.S+h;
+        ValueAnsi.S:=ValueAnsi.S+h;
         exit;
         exit;
         end;
         end;
 
 
@@ -4232,47 +4234,47 @@ var
       CP_UTF16:
       CP_UTF16:
         begin
         begin
         ForceUTF16;
         ForceUTF16;
-        TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+GetUnicodeStr(h,Expr);
-        //writeln('AddSrc len(h)=',length(h),' StringCodePage=',StringCodePage(h),' GetCodePage=',GetCodePage(h),' S=',length(TResEvalUTF16(Result).S));
+        TResEvalUTF16(Value).S:=TResEvalUTF16(Value).S+GetUnicodeStr(h,Expr);
+        //writeln('AddSrc len(h)=',length(h),' StringCodePage=',StringCodePage(h),' GetCodePage=',GetCodePage(h),' S=',length(TResEvalUTF16(Value).S));
         end;
         end;
       CP_UTF16BE:
       CP_UTF16BE:
         RaiseNotYetImplemented(20201220222608,Expr);
         RaiseNotYetImplemented(20201220222608,Expr);
       else
       else
         begin
         begin
-        if Value.S<>'' then
+        if ValueAnsi.S<>'' then
         begin
         begin
-          if Value.OnlyASCII then
-            SetCodePage(Value.S,TargetCP,false);
-          Value.S:=Value.S+h;
+          if ValueAnsi.OnlyASCII then
+            SetCodePage(ValueAnsi.S,TargetCP,false);
+          ValueAnsi.S:=ValueAnsi.S+h;
         end else begin
         end else begin
-          Value.S:=h;
+          ValueAnsi.S:=h;
         end;
         end;
         end;
         end;
       end;
       end;
 
 
       end
       end
     else
     else
-      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+GetUnicodeStr(h,Expr);
+      TResEvalUTF16(Value).S:=TResEvalUTF16(Value).S+GetUnicodeStr(h,Expr);
     {$else}
     {$else}
-    TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+h;
+    TResEvalUTF16(Value).S:=TResEvalUTF16(Value).S+h;
     {$endif}
     {$endif}
   end;
   end;
 
 
   procedure AddHash(u: longword);
   procedure AddHash(u: longword);
   {$ifdef FPC_HAS_CPSTRING}
   {$ifdef FPC_HAS_CPSTRING}
   begin
   begin
-    if Result.Kind=revkString then
-      TResEvalString(Result).s:=TResEvalString(Result).S+Chr(u)
+    if Value.Kind=revkString then
+      TResEvalString(Value).s:=TResEvalString(Value).S+Chr(u)
     else
     else
-      TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
+      TResEvalUTF16(Value).S:=TResEvalUTF16(Value).S+WideChar(u);
   end;
   end;
   {$else}
   {$else}
   begin
   begin
-    TResEvalUTF16(Result).S:=TResEvalUTF16(Result).S+WideChar(u);
+    TResEvalUTF16(Value).S:=TResEvalUTF16(Value).S+WideChar(u);
   end;
   end;
   {$endif}
   {$endif}
 
 
-  function ReadHash(Value: TResEvalValue; const S: string; p, l: integer): integer;
+  function ReadHash(const S: string; p, l: integer): integer;
   var
   var
     StartP: Integer;
     StartP: Integer;
     u: longword;
     u: longword;
@@ -4283,6 +4285,7 @@ var
     OldCP: TSystemCodePage;
     OldCP: TSystemCodePage;
     {$ENDIF}
     {$ENDIF}
   begin
   begin
+    //writeln('ReadHash S="',S,'" p=',p,' l=',l,' ',StringCodePage(S));
     Result:=p;
     Result:=p;
     inc(Result);
     inc(Result);
     if Result>l then
     if Result>l then
@@ -4402,9 +4405,9 @@ begin
   TargetCP:=CP_ACP;
   TargetCP:=CP_ACP;
   SourceCPValid:=false;
   SourceCPValid:=false;
   SourceCP:=CP_ACP;
   SourceCP:=CP_ACP;
-  Result:=TResEvalString.Create;
+  Value:=TResEvalString.Create;
   {$else}
   {$else}
-  Result:=TResEvalUTF16.Create;
+  Value:=TResEvalUTF16.Create;
   {$endif}
   {$endif}
   p:=1;
   p:=1;
   //writeln('TResExprEvaluator.EvalPrimitiveExprString ',GetObjPath(Expr),' ',Expr.SourceFilename,' ',Expr.SourceLinenumber div 2048,' S=[',S,']');
   //writeln('TResExprEvaluator.EvalPrimitiveExprString ',GetObjPath(Expr),' ',Expr.SourceFilename,' ',Expr.SourceLinenumber div 2048,' S=[',S,']');
@@ -4442,7 +4445,7 @@ begin
         AddSrc(copy(S,StartP,p-StartP));
         AddSrc(copy(S,StartP,p-StartP));
       end;
       end;
     '#':
     '#':
-      p:=ReadHash(Result,S,p,l);
+      p:=ReadHash(S,p,l);
     '^':
     '^':
       begin
       begin
       // ^A is #1
       // ^A is #1
@@ -4460,6 +4463,7 @@ begin
     else
     else
       RaiseNotYetImplemented(20170523123815,Expr,'ord='+IntToStr(ord(S[p])));
       RaiseNotYetImplemented(20170523123815,Expr,'ord='+IntToStr(ord(S[p])));
     end;
     end;
+  Result:=Value;
   {$IFDEF VerbosePasResEval}
   {$IFDEF VerbosePasResEval}
   //writeln('TResExprEvaluator.EvalPrimitiveExprString Result=',Result.AsString);
   //writeln('TResExprEvaluator.EvalPrimitiveExprString Result=',Result.AsString);
   {$ENDIF}
   {$ENDIF}

+ 15 - 4
packages/fcl-passrc/src/pasresolver.pp

@@ -4734,7 +4734,7 @@ end;
 
 
 procedure TPasResolver.GetParamsOfNameExpr(El: TPasExpr; out
 procedure TPasResolver.GetParamsOfNameExpr(El: TPasExpr; out
   ParentParams: TPRParentParams);
   ParentParams: TPRParentParams);
-// Checks is El is the name expression of a call or array access
+// Checks if El is the name expression of a call or array access
 // For example: a.b.El()  a.El[]
 // For example: a.b.El()  a.El[]
 // Note: TPasParser guarantees that there is at most one TBinaryExpr
 // Note: TPasParser guarantees that there is at most one TBinaryExpr
 //       and one TInlineSpecializeExpr between El and TParamsExpr
 //       and one TInlineSpecializeExpr between El and TParamsExpr
@@ -10176,7 +10176,6 @@ begin
   if ParentParams.InlineSpec<>nil then
   if ParentParams.InlineSpec<>nil then
     begin
     begin
     TypeCnt:=InlParams.Count;
     TypeCnt:=InlParams.Count;
-    // ToDo: generic functions without params
     DeclEl:=FindGenericEl(aName,TypeCnt,FindData,El);
     DeclEl:=FindGenericEl(aName,TypeCnt,FindData,El);
     if DeclEl<>nil then
     if DeclEl<>nil then
       begin
       begin
@@ -10207,9 +10206,19 @@ begin
       begin
       begin
       TemplTypes:=GetProcTemplateTypes(Proc);
       TemplTypes:=GetProcTemplateTypes(Proc);
       if (TemplTypes<>nil) then
       if (TemplTypes<>nil) then
+        begin
         // implicit function specialization without bracket
         // implicit function specialization without bracket
+        {$IFDEF VerbosePasResolver}
+        DeclEl:=El;
+        while DeclEl.Parent is TPasExpr do
+          DeclEl:=DeclEl.Parent;
+        {AllowWriteln}
+        writeln('TPasResolver.ResolveNameExpr ',WritePasElTree(TPasExpr(DeclEl),'  '));
+        {AllowWriteln-}
+        {$ENDIF}
         RaiseMsg(20191007222004,nCouldNotInferTypeArgXForMethodY,
         RaiseMsg(20191007222004,nCouldNotInferTypeArgXForMethodY,
           sCouldNotInferTypeArgXForMethodY,[TPasGenericTemplateType(TemplTypes[0]).Name,Proc.Name],El);
           sCouldNotInferTypeArgXForMethodY,[TPasGenericTemplateType(TemplTypes[0]).Name,Proc.Name],El);
+        end;
       end;
       end;
 
 
     if El.Parent.ClassType=TPasProperty then
     if El.Parent.ClassType=TPasProperty then
@@ -10757,7 +10766,7 @@ begin
   else if Value.ClassType=TInlineSpecializeExpr then
   else if Value.ClassType=TInlineSpecializeExpr then
     begin
     begin
     // e.g. Name<>()
     // e.g. Name<>()
-    ResolveInlineSpecializeExpr(TInlineSpecializeExpr(Value),rraRead);
+    ResolveInlineSpecializeExpr(TInlineSpecializeExpr(Value),Access);
     end
     end
   else if Value.ClassType=TParamsExpr then
   else if Value.ClassType=TParamsExpr then
     begin
     begin
@@ -27370,7 +27379,7 @@ procedure TPasResolver.ComputeElement(El: TPasElement; out
             end
             end
           else if ParentNeedsExprResult(Expr) then
           else if ParentNeedsExprResult(Expr) then
             begin
             begin
-            // a procedure
+            // a procedure address
             exit;
             exit;
             end;
             end;
           if rcSetReferenceFlags in Flags then
           if rcSetReferenceFlags in Flags then
@@ -28235,6 +28244,8 @@ begin
     else
     else
       Result:=true;
       Result:=true;
     end
     end
+  else if C=TInlineSpecializeExpr then
+    Result:=ParentNeedsExprResult(TInlineSpecializeExpr(P))
   else if C.InheritsFrom(TPasExpr) then
   else if C.InheritsFrom(TPasExpr) then
     Result:=true
     Result:=true
   else if (C=TPasEnumValue)
   else if (C=TPasEnumValue)

+ 72 - 0
packages/fcl-passrc/src/pastree.pp

@@ -1789,6 +1789,7 @@ function GenericTemplateTypesAsString(List: TFPList): string;
 procedure ReleaseProcNameParts(var NameParts: TProcedureNameParts);
 procedure ReleaseProcNameParts(var NameParts: TProcedureNameParts);
 
 
 function dbgs(const s: TProcTypeModifiers): string; overload;
 function dbgs(const s: TProcTypeModifiers): string; overload;
+function WritePasElTree(Expr: TPasExpr; FollowPrefix: string = ''): string;
 
 
 {$IFDEF HasPTDumpStack}
 {$IFDEF HasPTDumpStack}
 procedure PTDumpStack;
 procedure PTDumpStack;
@@ -1903,6 +1904,77 @@ begin
   Result:='['+Result+']';
   Result:='['+Result+']';
 end;
 end;
 
 
+function WritePasElTree(Expr: TPasExpr; FollowPrefix: string): string;
+{  TBinary Kind= OpCode=
+    +Left=TBinary Kind= OpCode=
+    | +Left=TParamsExpr[]
+    | | +Value=Prim Kind= Value=
+    | | +Params[1]=Prim Kind= Value=
+    +Right=Prim
+}
+var
+  C: TClass;
+  s: string;
+  ParamsExpr: TParamsExpr;
+  InlineSpecExpr: TInlineSpecializeExpr;
+  SubEl: TPasElement;
+  ArrayValues: TArrayValues;
+  i: Integer;
+begin
+  if Expr=nil then exit('nil');
+  C:=Expr.ClassType;
+
+  Result:=C.ClassName;
+  str(Expr.Kind,s);
+  Result:=Result+' '+s;
+  str(Expr.OpCode,s);
+  Result:=Result+' '+s;
+
+  if C=TPrimitiveExpr then
+    Result:=Result+' Value="'+TPrimitiveExpr(Expr).Value+'"'
+  else if C=TUnaryExpr then
+    Result:=Result+' Operand='+WritePasElTree(TUnaryExpr(Expr).Operand,FollowPrefix)
+  else if C=TBoolConstExpr then
+    Result:=Result+' Value='+BoolToStr(TBoolConstExpr(Expr).Value,'True','False')
+  else if C=TArrayValues then
+    begin
+    ArrayValues:=TArrayValues(Expr);
+    for i:=0 to length(ArrayValues.Values)-1 do
+      Result:=Result+sLineBreak+FollowPrefix+'+Values['+IntToStr(i)+']='+WritePasElTree(ArrayValues.Values[i],FollowPrefix+'| ');
+    end
+  else if C=TBinaryExpr then
+    begin
+    Result:=Result+sLineBreak+FollowPrefix+'+Left='+WritePasElTree(TBinaryExpr(Expr).left,FollowPrefix+'| ');
+    Result:=Result+sLineBreak+FollowPrefix+'+Right='+WritePasElTree(TBinaryExpr(Expr).right,FollowPrefix+'| ');
+    end
+  else if C=TParamsExpr then
+    begin
+    ParamsExpr:=TParamsExpr(Expr);
+    Result:=Result+sLineBreak+FollowPrefix+'+Value='+WritePasElTree(ParamsExpr.Value,FollowPrefix+'| ');
+    for i:=0 to length(ParamsExpr.Params)-1 do
+      Result:=Result+sLineBreak+FollowPrefix+'+Params['+IntToStr(i)+']='+WritePasElTree(ParamsExpr.Params[i],FollowPrefix+'| ');
+    end
+  else if C=TInlineSpecializeExpr then
+    begin
+    InlineSpecExpr:=TInlineSpecializeExpr(Expr);
+    Result:=Result+sLineBreak+FollowPrefix+'+Name='+WritePasElTree(InlineSpecExpr.NameExpr,FollowPrefix+'| ');
+    if InlineSpecExpr.Params<>nil then
+      for i:=0 to InlineSpecExpr.Params.Count-1 do
+        begin
+        Result:=Result+sLineBreak+FollowPrefix+'+Params['+IntToStr(i)+']=';
+        SubEl:=TPasElement(InlineSpecExpr.Params[i]);
+        if SubEl=nil then
+          Result:=Result+'nil'
+        else if SubEl is TPasExpr then
+          Result:=Result+WritePasElTree(TPasExpr(SubEl),FollowPrefix+'| ')
+        else
+          Result:=Result+SubEl.Name+':'+SubEl.ClassName;
+        end;
+    end
+  else
+    Result:=C.ClassName+' Kind=';
+end;
+
 Function IndentStrings(S : TStrings; indent : Integer) : string;
 Function IndentStrings(S : TStrings; indent : Integer) : string;
 Var
 Var
   I,CurrLen,CurrPos : Integer;
   I,CurrLen,CurrPos : Integer;

+ 15 - 2
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -62,6 +62,10 @@ const
   // non fpc hints
   // non fpc hints
   nPAParameterInOverrideNotUsed = 4501;
   nPAParameterInOverrideNotUsed = 4501;
   sPAParameterInOverrideNotUsed = 'Parameter "%s" not used';
   sPAParameterInOverrideNotUsed = 'Parameter "%s" not used';
+  nPAFieldNotUsed = 4502;
+  sPAFieldNotUsed = 'Field "%s" not used';
+  nPAFieldIsAssignedButNeverUsed = 4503;
+  sPAFieldIsAssignedButNeverUsed = 'Field "%s" is assigned but never used';
   // fpc hints: use same IDs as fpc
   // fpc hints: use same IDs as fpc
   nPAUnitNotUsed = 5023;
   nPAUnitNotUsed = 5023;
   sPAUnitNotUsed = 'Unit "%s" not used in %s';
   sPAUnitNotUsed = 'Unit "%s" not used in %s';
@@ -2827,8 +2831,14 @@ begin
           sPAPrivateFieldIsNeverUsed,[El.FullName],El);
           sPAPrivateFieldIsNeverUsed,[El.FullName],El);
       end
       end
     else if El.ClassType=TPasVariable then
     else if El.ClassType=TPasVariable then
-      EmitMessage(20170311234201,mtHint,nPALocalVariableNotUsed,
-        sPALocalVariableNotUsed,[El.Name],El)
+      begin
+      if El.Parent is TPasMembersType then
+        EmitMessage(20201229033108,mtHint,nPAFieldNotUsed,
+          sPAFieldNotUsed,[El.Name],El)
+      else
+        EmitMessage(20170311234201,mtHint,nPALocalVariableNotUsed,
+          sPALocalVariableNotUsed,[El.Name],El);
+      end
     else
     else
       EmitMessage(20170314221334,mtHint,nPALocalXYNotUsed,
       EmitMessage(20170314221334,mtHint,nPALocalXYNotUsed,
         sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
         sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
@@ -2842,6 +2852,9 @@ begin
     if El.Visibility in [visPrivate,visStrictPrivate] then
     if El.Visibility in [visPrivate,visStrictPrivate] then
       EmitMessage(20170311234159,mtHint,nPAPrivateFieldIsAssignedButNeverUsed,
       EmitMessage(20170311234159,mtHint,nPAPrivateFieldIsAssignedButNeverUsed,
         sPAPrivateFieldIsAssignedButNeverUsed,[El.FullName],El)
         sPAPrivateFieldIsAssignedButNeverUsed,[El.FullName],El)
+    else if El.Parent is TPasMembersType then
+      EmitMessage(20201229033618,mtHint,nPAFieldIsAssignedButNeverUsed,
+        sPAFieldIsAssignedButNeverUsed,[El.Name],El)
     else
     else
       EmitMessage(20170311233825,mtHint,nPALocalVariableIsAssignedButNeverUsed,
       EmitMessage(20170311233825,mtHint,nPALocalVariableIsAssignedButNeverUsed,
         sPALocalVariableIsAssignedButNeverUsed,[El.Name],El);
         sPALocalVariableIsAssignedButNeverUsed,[El.Name],El);

+ 6 - 1
packages/fcl-passrc/src/pparser.pp

@@ -2527,11 +2527,16 @@ begin
         NextToken;
         NextToken;
         if CurToken=tkspecialize then
         if CurToken=tkspecialize then
           begin
           begin
+          // Obj.specialize ...
           if CanSpecialize=aMust then
           if CanSpecialize=aMust then
             CheckToken(tkLessThan);
             CheckToken(tkLessThan);
           CanSpecialize:=aMust;
           CanSpecialize:=aMust;
           NextToken;
           NextToken;
-          end;
+          end
+        else if msDelphi in CurrentModeswitches then
+          CanSpecialize:=aCan
+        else
+          CanSpecialize:=aCannot;
         if CurToken in [tkIdentifier,tktrue,tkfalse,tkself] then // true and false are sub identifiers as well
         if CurToken in [tkIdentifier,tktrue,tkfalse,tkself] then // true and false are sub identifiers as well
           begin
           begin
           aName:=aName+'.'+CurTokenString;
           aName:=aName+'.'+CurTokenString;

+ 3 - 3
packages/fcl-passrc/src/pscanner.pp

@@ -3106,7 +3106,8 @@ end;
 function TPascalScanner.FetchToken: TToken;
 function TPascalScanner.FetchToken: TToken;
 
 
 begin
 begin
-  FPreviousToken:=FCurToken;
+  if Not (FCurToken in [tkWhiteSpace,tkLineEnding]) then
+    FPreviousToken:=FCurToken;
   while true do
   while true do
   begin
   begin
     Result := DoFetchToken;
     Result := DoFetchToken;
@@ -5051,8 +5052,7 @@ begin
       begin
       begin
       if ForceCaret or PPisSkipping or
       if ForceCaret or PPisSkipping or
          (PreviousToken in [tkeof,tkTab,tkLineEnding,tkComment,tkIdentifier,
          (PreviousToken in [tkeof,tkTab,tkLineEnding,tkComment,tkIdentifier,
-                   tkNil,tkOperator,tkBraceClose,tkSquaredBraceClose,tkCaret,
-                   tkWhitespace]) then
+                   tkNil,tkOperator,tkBraceClose,tkSquaredBraceClose,tkCaret]) then
         begin
         begin
         Inc(FTokenPos);
         Inc(FTokenPos);
         Result := tkCaret;
         Result := tkCaret;

+ 28 - 1
packages/fcl-passrc/tests/tcresolvegenerics.pas

@@ -156,7 +156,7 @@ type
     procedure TestGenProc_TypeParamCntOverload;
     procedure TestGenProc_TypeParamCntOverload;
     procedure TestGenProc_TypeParamCntOverloadNoParams;
     procedure TestGenProc_TypeParamCntOverloadNoParams;
     procedure TestGenProc_TypeParamWithDefaultParamDelphiFail;
     procedure TestGenProc_TypeParamWithDefaultParamDelphiFail;
-    procedure TestGenProc_ParamSpecWithT; // ToDo: Func<T>(Bird: TBird<T>)
+    procedure TestGenProc_ParamSpecWithT;
     // ToDo: NestedResultAssign
     // ToDo: NestedResultAssign
 
 
     // generic function infer types
     // generic function infer types
@@ -186,6 +186,7 @@ type
     procedure TestGenMethod_OverloadTypeParamCntDelphi;
     procedure TestGenMethod_OverloadTypeParamCntDelphi;
     procedure TestGenMethod_OverloadArgs;
     procedure TestGenMethod_OverloadArgs;
     procedure TestGenMethod_TypeCastParam;
     procedure TestGenMethod_TypeCastParam;
+    procedure TestGenMethod_TypeCastIdentDot;
   end;
   end;
 
 
 implementation
 implementation
@@ -3010,6 +3011,32 @@ begin
   ParseUnit;
   ParseUnit;
 end;
 end;
 
 
+procedure TTestResolveGenerics.TestGenMethod_TypeCastIdentDot;
+begin
+  StartUnit(false);
+  Add([
+  '{$mode delphi}',
+  'interface',
+  'type',
+  '  TObject = class end;',
+  '  TBird = class end;',
+  '  TEagle = class(TBird)',
+  '    procedure Run<S>(p: S);',
+  '    procedure Fly;',
+  '  end;',
+  'implementation',
+  'procedure TEagle.Run<S>(p: S);',
+  'begin',
+  'end;',
+  'procedure TEagle.Fly;',
+  'var Bird: TBird;',
+  'begin',
+  '  TEagle(Bird).Run<word>(3);',
+  'end;',
+  '']);
+  ParseUnit;
+end;
+
 initialization
 initialization
   RegisterTests([TTestResolveGenerics]);
   RegisterTests([TTestResolveGenerics]);
 
 

+ 3 - 1
packages/fcl-passrc/tests/tcresolver.pas

@@ -3544,7 +3544,8 @@ begin
   '  s[9+1]:=''b'';',
   '  s[9+1]:=''b'';',
   '  s[10]:='''''''';',
   '  s[10]:='''''''';',
   '  s[11]:=^g;',
   '  s[11]:=^g;',
-  '  s[12]:=^H;']);
+  '  s[12]:=^H;',
+  '']);
   ParseProgram;
   ParseProgram;
 end;
 end;
 
 
@@ -3622,6 +3623,7 @@ begin
   '  m=low(char)+high(char);',
   '  m=low(char)+high(char);',
   '  n = string(''A'');',
   '  n = string(''A'');',
   '  o = UnicodeString(''A'');',
   '  o = UnicodeString(''A'');',
+  //'  p = ^C''bird'';',
   'begin']);
   'begin']);
   ParseProgram;
   ParseProgram;
   CheckResolverUnexpectedHints;
   CheckResolverUnexpectedHints;

+ 7 - 0
packages/fcl-passrc/tests/tcscanner.pas

@@ -115,6 +115,7 @@ type
     procedure TestNumber;
     procedure TestNumber;
     procedure TestChar;
     procedure TestChar;
     procedure TestCharString;
     procedure TestCharString;
+    procedure TestCaretString;
     procedure TestBraceOpen;
     procedure TestBraceOpen;
     procedure TestBraceClose;
     procedure TestBraceClose;
     procedure TestMul;
     procedure TestMul;
@@ -831,6 +832,12 @@ begin
   TestToken(pscanner.tkChar,'''A''');
   TestToken(pscanner.tkChar,'''A''');
 end;
 end;
 
 
+procedure TTestScanner.TestCaretString;
+begin
+
+  TestTokens([tkIdentifier,tkWhiteSpace,tkEqual,tkwhiteSpace,pscanner.tkString,tkSemicolon],'a = ^C''abc'';',false);
+end;
+
 procedure TTestScanner.TestNumber;
 procedure TTestScanner.TestNumber;
 
 
 begin
 begin

+ 8 - 8
packages/fcl-passrc/tests/tcuseanalyzer.pas

@@ -945,9 +945,9 @@ begin
   'begin',
   'begin',
   '  DoIt;']);
   '  DoIt;']);
   AnalyzeProgram;
   AnalyzeProgram;
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableNotUsed,'Local variable "b" not used');
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableIsAssignedButNeverUsed,
-    'Local variable "c" is assigned but never used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldNotUsed,'Field "b" not used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldIsAssignedButNeverUsed,
+    'Field "c" is assigned but never used');
   CheckUseAnalyzerUnexpectedHints;
   CheckUseAnalyzerUnexpectedHints;
 end;
 end;
 
 
@@ -2278,9 +2278,9 @@ begin
   Add('begin');
   Add('begin');
   Add('  Point(1);');
   Add('  Point(1);');
   AnalyzeProgram;
   AnalyzeProgram;
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableIsAssignedButNeverUsed,
-    'Local variable "X" is assigned but never used');
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableNotUsed,'Local variable "Y" not used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldIsAssignedButNeverUsed,
+    'Field "X" is assigned but never used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldNotUsed,'Field "Y" not used');
   CheckUseAnalyzerUnexpectedHints;
   CheckUseAnalyzerUnexpectedHints;
 end;
 end;
 
 
@@ -2319,7 +2319,7 @@ begin
   Add('begin');
   Add('begin');
   Add('  Point();');
   Add('  Point();');
   AnalyzeProgram;
   AnalyzeProgram;
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableNotUsed,'Local variable "Y" not used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldNotUsed,'Field "Y" not used');
   CheckUseAnalyzerUnexpectedHints;
   CheckUseAnalyzerUnexpectedHints;
 end;
 end;
 
 
@@ -2385,7 +2385,7 @@ begin
   '  specialize Point<word>();',
   '  specialize Point<word>();',
   '']);
   '']);
   AnalyzeProgram;
   AnalyzeProgram;
-  CheckUseAnalyzerHint(mtHint,nPALocalVariableNotUsed,'Local variable "Y" not used');
+  CheckUseAnalyzerHint(mtHint,nPAFieldNotUsed,'Field "Y" not used');
   CheckUseAnalyzerUnexpectedHints;
   CheckUseAnalyzerUnexpectedHints;
 end;
 end;
 
 

+ 68 - 13
packages/pastojs/src/fppas2js.pp

@@ -2399,6 +2399,7 @@ const
   TempRefSetPathName = 's';
   TempRefSetPathName = 's';
   TempRefParamName = 'a';
   TempRefParamName = 'a';
   IdentChars = ['0'..'9', 'A'..'Z', 'a'..'z','_'];
   IdentChars = ['0'..'9', 'A'..'Z', 'a'..'z','_'];
+  AwaitSignature2 = 'function await(aType,TJSPromise):aType';
 
 
 function CodePointToJSString(u: longword): TJSString;
 function CodePointToJSString(u: longword): TJSString;
 begin
 begin
@@ -5956,12 +5957,10 @@ end;
 
 
 function TPas2JSResolver.BI_AWait_OnGetCallCompatibility(
 function TPas2JSResolver.BI_AWait_OnGetCallCompatibility(
   Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
   Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
-// await(T; p: TJSPromise): T;
+// await(T; p: TJSPromise): T
+// await(T; jsvalue): T
+// await(AsyncFuncWithResultT): T
 // await(AsyncProc);
 // await(AsyncProc);
-// await(Proc);
-// await(const Expr: T): T
-const
-  Signature2 = 'function await(aType,TJSPromise):aType';
 var
 var
   Params: TParamsExpr;
   Params: TParamsExpr;
   Param: TPasExpr;
   Param: TPasExpr;
@@ -5991,6 +5990,48 @@ begin
     // must be the only parameter
     // must be the only parameter
     Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
     Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
     if Result=cIncompatible then exit;
     if Result=cIncompatible then exit;
+
+    TypeEl:=ParamResolved.LoTypeEl;
+    if (ParamResolved.IdentEl is TPasResultElement) then
+      begin
+      // await(AsyncFuncCall)
+      if not TPasFunctionType(ParamResolved.IdentEl.Parent).IsAsync then
+        begin
+        {$IFDEF VerbosePas2JS}
+        writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
+        {$ENDIF}
+        if RaiseOnError then
+          RaiseMsg(20201229232446,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
+        else
+          exit(cIncompatible);
+        end;
+      end
+    else if (ParamResolved.BaseType=btContext)
+        and (TypeEl is TPasProcedureType) then
+      begin
+      // await(AsyncFuncTypeVar)
+      if not TPasProcedureType(TypeEl).IsAsync then
+        begin
+        {$IFDEF VerbosePas2JS}
+        writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
+        {$ENDIF}
+        if RaiseOnError then
+          RaiseMsg(20201229232541,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
+        else
+          exit(cIncompatible);
+        end;
+      end
+    else
+      begin
+      {$IFDEF VerbosePas2JS}
+      writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
+      {$ENDIF}
+      if RaiseOnError then
+        RaiseMsg(20201229224920,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
+      else
+        exit(cIncompatible);
+      end;
+
     end
     end
   else if ParamResolved.BaseType=btProc then
   else if ParamResolved.BaseType=btProc then
     begin
     begin
@@ -6028,7 +6069,7 @@ begin
       begin
       begin
       if RaiseOnError then
       if RaiseOnError then
         RaiseMsg(20200520090749,nWrongNumberOfParametersForCallTo,
         RaiseMsg(20200520090749,nWrongNumberOfParametersForCallTo,
-          sWrongNumberOfParametersForCallTo,[Signature2],Params);
+          sWrongNumberOfParametersForCallTo,[AwaitSignature2],Params);
       exit(cIncompatible);
       exit(cIncompatible);
       end;
       end;
 
 
@@ -6062,14 +6103,21 @@ begin
         exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
         exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
            'instance of TJSPromise',RaiseOnError));
            'instance of TJSPromise',RaiseOnError));
 
 
-      if (Param2Resolved.BaseType<>btContext)
-          or not (Param2Resolved.LoTypeEl is TPasClassType)
-          or not IsExternalClass_Name(TPasClassType(Param2Resolved.LoTypeEl),'Promise') then
-        exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
+      if (Param2Resolved.BaseType=btContext)
+          and (Param2Resolved.LoTypeEl is TPasClassType)
+          and IsExternalClass_Name(TPasClassType(Param2Resolved.LoTypeEl),'Promise') then
+        // await(T,aPromise)
+      else if IsJSBaseType(Param2Resolved,pbtJSValue) then
+        // await(T,jsvalue)
+      else if (Param2Resolved.IdentEl is TPasArgument)
+          and (Param2Resolved.LoTypeEl=nil) then
+        // await(T,UntypedArg)
+      else
+        exit(CheckRaiseTypeArgNo(20200520091708,2,Param,Param2Resolved,
            'TJSPromise',RaiseOnError));
            'TJSPromise',RaiseOnError));
       end;
       end;
 
 
-    Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError,Signature2);
+    Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError,AwaitSignature2);
     end;
     end;
 end;
 end;
 
 
@@ -6084,11 +6132,18 @@ begin
   Param:=Params.Params[0];
   Param:=Params.Params[0];
   if length(Params.Params)=1 then
   if length(Params.Params)=1 then
     begin
     begin
-    // await(expr)
+    // await(AsyncFuncCall)
     if CheckCallAsyncFuncResult(Param,ResolvedEl) then
     if CheckCallAsyncFuncResult(Param,ResolvedEl) then
+      begin
       // await(CallAsynFuncResultT): T
       // await(CallAsynFuncResultT): T
+      if (ResolvedEl.BaseType=btContext)
+          and (ResolvedEl.LoTypeEl is TPasClassType)
+          and IsExternalClass_Name(TPasClassType(ResolvedEl.LoTypeEl),'Promise') then
+        // async function returns a promise, await resolve all promises -> need final type as first param
+        RaiseMsg(20201229235932,nWrongNumberOfParametersForCallTo,
+          sWrongNumberOfParametersForCallTo,[AwaitSignature2],Param);
       exit;
       exit;
-    // await(expr:T):T
+      end;
     end
     end
   else
   else
     begin
     begin

+ 47 - 3
packages/pastojs/tests/tcgenerics.pas

@@ -77,7 +77,8 @@ type
     // ToDo: FuncName:= instead of Result:=
     // ToDo: FuncName:= instead of Result:=
 
 
     // generic methods
     // generic methods
-    procedure TestGenMethod_ObjFPC;
+    procedure TestGenMethod_ImplicitSpec_ObjFPC;
+    procedure TestGenMethod_Delphi;
 
 
     // generic array
     // generic array
     procedure TestGen_Array_OtherUnit;
     procedure TestGen_Array_OtherUnit;
@@ -2135,7 +2136,7 @@ begin
     '']));
     '']));
 end;
 end;
 
 
-procedure TTestGenerics.TestGenMethod_ObjFPC;
+procedure TTestGenerics.TestGenMethod_ImplicitSpec_ObjFPC;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
@@ -2166,7 +2167,7 @@ begin
   '  o.{@C}Run(''foo'',''bar'');',
   '  o.{@C}Run(''foo'',''bar'');',
   '']);
   '']);
   ConvertProgram;
   ConvertProgram;
-  CheckSource('TestGenMethod_ObjFPC',
+  CheckSource('TestGenMethod_ImplicitSpec_ObjFPC',
     LinesToStr([ // statements
     LinesToStr([ // statements
     'rtl.createClass(this, "TObject", null, function () {',
     'rtl.createClass(this, "TObject", null, function () {',
     '  this.$init = function () {',
     '  this.$init = function () {',
@@ -2192,6 +2193,49 @@ begin
     '']));
     '']));
 end;
 end;
 
 
+procedure TTestGenerics.TestGenMethod_Delphi;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode delphi}',
+  'type',
+  '  TObject = class',
+  '    procedure Run<S>;',
+  '  end; ',
+  'procedure TObject.Run<S>;',
+  'begin',
+  'end;',
+  'var o: TObject;',
+  'begin',
+  '  o.Run<word>;',
+  '  o.Run<word>();',
+  '  with o do begin',
+  '    Run<word>;',
+  '    Run<word>();',
+  '  end;',
+  '']);
+  ConvertProgram;
+  CheckSource('TestGenMethod_Delphi',
+    LinesToStr([ // statements
+    'rtl.createClass(this, "TObject", null, function () {',
+    '  this.$init = function () {',
+    '  };',
+    '  this.$final = function () {',
+    '  };',
+    '  this.Run$G1 = function () {',
+    '  };',
+    '});',
+    'this.o = null;',
+    '']),
+    LinesToStr([ // $mod.$main
+    '$mod.o.Run$G1();',
+    '$mod.o.Run$G1();',
+    'var $with = $mod.o;',
+    '$with.Run$G1();',
+    '$with.Run$G1();',
+    '']));
+end;
+
 procedure TTestGenerics.TestGen_Array_OtherUnit;
 procedure TTestGenerics.TestGen_Array_OtherUnit;
 begin
 begin
   WithTypeInfo:=true;
   WithTypeInfo:=true;

+ 114 - 34
packages/pastojs/tests/tcmodules.pas

@@ -883,8 +883,11 @@ type
     Procedure TestAwait_NonPromiseWithTypeFail;
     Procedure TestAwait_NonPromiseWithTypeFail;
     Procedure TestAwait_AsyncCallTypeMismatch;
     Procedure TestAwait_AsyncCallTypeMismatch;
     Procedure TestAWait_OutsideAsyncFail;
     Procedure TestAWait_OutsideAsyncFail;
-    Procedure TestAWait_Result;
+    Procedure TestAWait_IntegerFail;
     Procedure TestAWait_ExternalClassPromise;
     Procedure TestAWait_ExternalClassPromise;
+    Procedure TestAWait_JSValue;
+    Procedure TestAWait_Result;
+    Procedure TestAWait_ResultPromiseMissingTypeFail;
     Procedure TestAsync_AnonymousProc;
     Procedure TestAsync_AnonymousProc;
     Procedure TestAsync_ProcType;
     Procedure TestAsync_ProcType;
     Procedure TestAsync_ProcTypeAsyncModMismatchFail;
     Procedure TestAsync_ProcTypeAsyncModMismatchFail;
@@ -32619,48 +32622,21 @@ begin
   ConvertProgram;
   ConvertProgram;
 end;
 end;
 
 
-procedure TTestModule.TestAWait_Result;
+procedure TTestModule.TestAWait_IntegerFail;
 begin
 begin
   StartProgram(false);
   StartProgram(false);
   Add([
   Add([
-  '{$modeswitch externalclass}',
-  'type',
-  '  TJSPromise = class external name ''Promise''',
-  '  end;',
-  'function Crawl(d: double = 1.3): word; ',
+  'function Run: word;',
   'begin',
   'begin',
   'end;',
   'end;',
-  'function Run(d: double = 1.6): word; async;',
+  'procedure Fly(w: word); async;',
   'begin',
   'begin',
-  '  Result:=await(1);',
-  '  Result:=await(Crawl);',
-  '  Result:=await(Crawl(4.5));',
-  '  Result:=await(Run);',
-  '  Result:=await(Run(6.7));',
+  '  await(Run());',
   'end;',
   'end;',
   'begin',
   'begin',
-  '  Run(1);']);
+  '  Fly(1);']);
+  SetExpectedPasResolverError('async function expected, but Result:Word found',nXExpectedButYFound);
   ConvertProgram;
   ConvertProgram;
-  CheckSource('TestAWait_Result',
-    LinesToStr([ // statements
-    'this.Crawl = function (d) {',
-    '  var Result = 0;',
-    '  return Result;',
-    '};',
-    'this.Run = async function (d) {',
-    '  var Result = 0;',
-    '  Result = await 1;',
-    '  Result = await $mod.Crawl(1.3);',
-    '  Result = await $mod.Crawl(4.5);',
-    '  Result = await $mod.Run(1.6);',
-    '  Result = await $mod.Run(6.7);',
-    '  return Result;',
-    '};',
-    '']),
-    LinesToStr([
-    '$mod.Run(1);'
-    ]));
-  SetExpectedPasResolverError('Await without promise',nAwaitWithoutPromise);
 end;
 end;
 
 
 procedure TTestModule.TestAWait_ExternalClassPromise;
 procedure TTestModule.TestAWait_ExternalClassPromise;
@@ -32723,6 +32699,110 @@ begin
   CheckResolverUnexpectedHints();
   CheckResolverUnexpectedHints();
 end;
 end;
 
 
+procedure TTestModule.TestAWait_JSValue;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch externalclass}',
+  'type',
+  '  TJSPromise = class external name ''Promise''',
+  '  end;',
+  'function Fly(w: word): jsvalue; async;',
+  'begin',
+  'end;',
+  'function Run(d: jsvalue; var e): word; async;',
+  'begin',
+  '  Result:=await(word,d);', // promise needs type
+  '  d:=await(Fly(4));', // async non promise must omit the type
+  '  Result:=await(word,e);', // promise needs type
+  'end;',
+  'begin',
+  '']);
+  ConvertProgram;
+  CheckSource('TestAWait_JSValue',
+    LinesToStr([ // statements
+    'this.Fly = async function (w) {',
+    '  var Result = undefined;',
+    '  return Result;',
+    '};',
+    'this.Run = async function (d, e) {',
+    '  var Result = 0;',
+    '  Result = await d;',
+    '  d = await $mod.Fly(4);',
+    '  Result = await e.get();',
+    '  return Result;',
+    '};',
+    '']),
+    LinesToStr([
+    ]));
+  CheckResolverUnexpectedHints();
+end;
+
+procedure TTestModule.TestAWait_Result;
+begin
+  StartProgram(false);
+  Add([
+  '{$modeswitch externalclass}',
+  'type',
+  '  TJSPromise = class external name ''Promise''',
+  '  end;',
+  'function Crawl(d: double = 1.3): TJSPromise; ',
+  'begin',
+  'end;',
+  'function Run(d: double = 1.6): word; async;',
+  'begin',
+  '  Result:=await(word,Crawl);',
+  '  Result:=await(word,Crawl(4.5));',
+  '  Result:=await(Run);',
+  '  Result:=await(Run(6.7));',
+  'end;',
+  'begin',
+  '  Run(1);']);
+  ConvertProgram;
+  CheckSource('TestAWait_Result',
+    LinesToStr([ // statements
+    'this.Crawl = function (d) {',
+    '  var Result = null;',
+    '  return Result;',
+    '};',
+    'this.Run = async function (d) {',
+    '  var Result = 0;',
+    '  Result = await $mod.Crawl(1.3);',
+    '  Result = await $mod.Crawl(4.5);',
+    '  Result = await $mod.Run(1.6);',
+    '  Result = await $mod.Run(6.7);',
+    '  return Result;',
+    '};',
+    '']),
+    LinesToStr([
+    '$mod.Run(1);'
+    ]));
+  CheckResolverUnexpectedHints();
+end;
+
+procedure TTestModule.TestAWait_ResultPromiseMissingTypeFail;
+begin
+  StartProgram(false);
+  Add([
+  '{$mode objfpc}',
+  '{$modeswitch externalclass}',
+  'type',
+  '  TJSPromise = class external name ''Promise''',
+  '  end;',
+  'function Run: TJSPromise; async;',
+  'begin',
+  'end;',
+  'procedure Fly(w: word); async;',
+  'begin',
+  '  await(Run());',
+  'end;',
+  'begin',
+  '  Fly(1);']);
+  SetExpectedPasResolverError('Wrong number of parameters specified for call to "function await(aType,TJSPromise):aType"',
+    nWrongNumberOfParametersForCallTo);
+  ConvertProgram;
+end;
+
 procedure TTestModule.TestAsync_AnonymousProc;
 procedure TTestModule.TestAsync_AnonymousProc;
 begin
 begin
   StartProgram(false);
   StartProgram(false);

+ 1 - 1
packages/winunits-base/src/activex.pp

@@ -4541,7 +4541,7 @@ type
   procedure CoTaskMemFree(_para1:PVOID);stdcall; external  'ole32.dll' name 'CoTaskMemFree';
   procedure CoTaskMemFree(_para1:PVOID);stdcall; external  'ole32.dll' name 'CoTaskMemFree';
 
 
 {$ifndef wince}
 {$ifndef wince}
-  function CreateDataAdviseHolder(_para1:IDataAdviseHolder):HRESULT;stdcall; external  'ole32.dll' name 'CreateDataAdviseHolder';
+  function CreateDataAdviseHolder(out _para1:IDataAdviseHolder):HRESULT;stdcall; external  'ole32.dll' name 'CreateDataAdviseHolder';
   function CreateDataCache(_para1:IUnknown; const _para2:TCLSID; const _para3:TIID; out _para4):HRESULT;stdcall; external  'ole32.dll' name 'CreateDataCache';
   function CreateDataCache(_para1:IUnknown; const _para2:TCLSID; const _para3:TIID; out _para4):HRESULT;stdcall; external  'ole32.dll' name 'CreateDataCache';
 {$endif wince}
 {$endif wince}
 
 

+ 1 - 5
tests/test/cg/tm128.pp

@@ -1,14 +1,10 @@
 {$ASSERTIONS ON}
 {$ASSERTIONS ON}
-{$packrecords c}
-{$push}
-{$codealign recordmin=16}
 
 
 type
 type
   tm128 = record
   tm128 = record
     case byte of
     case byte of
       1 : (m128_f32 : array[0..3] of single;)
       1 : (m128_f32 : array[0..3] of single;)
-  end;
-{$pop}
+  end align 16;
 
 
 type
 type
   tm128_unaligned = record
   tm128_unaligned = record

+ 39 - 0
tests/webtbs/tw28927.pp

@@ -0,0 +1,39 @@
+type
+  TRecord1 = record
+  end align 16;
+
+  TRecord2 = record
+  end align 8;
+
+  TRecord3 = record
+  end align 4;
+
+  TRecord1Outer = record  
+    b : Byte;
+    Record1 : TRecord1;
+  end;
+
+  TRecord2Outer = record  
+    b : Byte;
+    Record2 : TRecord2;
+  end;
+
+  TRecord3Outer = record  
+    b : Byte;
+    Record3 : TRecord3;
+  end;
+
+var
+  Record1Outer : TRecord1Outer;
+  Record2Outer : TRecord2Outer;
+  Record3Outer : TRecord3Outer;
+
+begin
+  if PtrUInt(@Record1Outer.Record1) mod 16<>0 then
+    halt(1);
+  if PtrUInt(@Record2Outer.Record2) mod 8<>0 then
+    halt(2);
+  if PtrUInt(@Record3Outer.Record3) mod 4<>0 then
+    halt(3);
+  writeln('ok');
+end.

+ 17 - 0
tests/webtbs/tw38259.pp

@@ -0,0 +1,17 @@
+{ %OPT=-O3 -Sew -vw }
+{$mode objfpc}
+{$inline on}
+
+procedure test; inline;
+begin
+  exit;
+end;
+
+function f: longint;
+begin
+  test; // tt.pp(11,3) Warning: Function result variable does not seem to be initialized
+  result:=4;
+end;
+
+begin
+end.

+ 2 - 2
utils/pas2js/docs/translation.html

@@ -3060,9 +3060,9 @@ End.
     Pas2js supports the JS operators async and await to simplify the use of Promise.
     Pas2js supports the JS operators async and await to simplify the use of Promise.
     The await operator corresponds to three intrinsic Pas2js functions:
     The await operator corresponds to three intrinsic Pas2js functions:
     <ul>
     <ul>
-    <li><i>function await(AsyncFunctionWithResultT): T;</i>  // implicit promise</li>
+    <li><i>function await(AsyncFunctionWithResultT()): T;</i>  // implicit promise, the inner () can be omitted</li>
     <li><i>function await(aType; p: TJSPromise): aType;</i>  // explicit promise requires the resolved type</li>
     <li><i>function await(aType; p: TJSPromise): aType;</i>  // explicit promise requires the resolved type</li>
-    <li><i>function await(const Expr: T): T;</i>  // implicit promise</li>
+    <li><i>function await(aType; j: jsvalue): aType;</i>  // explicit promise requires the resolved type</li>
     </ul>
     </ul>
     The await function can only be used inside a procedure with the async modifier.<br>
     The await function can only be used inside a procedure with the async modifier.<br>
     Example for the explicit promise:
     Example for the explicit promise: