Difference between += and := -- Is this a bug in FPC? lazarus / 64-FPC development ---------------------------------------------------------------------- EganSolo · 2017-10-18 00:33 Before I get ahead of myself and post this as a bug, I thought I would ask here first. Consider line 8 in the code fragment below: The code uses +=, whereas the commented assignment on line nine  uses := When I run the code as is (with +=) and the boolean variable, EmptyStr on line seven is true, the debugger exits the method as if the code on lines eight and ten does not exist. But when I comment that line and uncomment line nine, then the code functions properly. Am I simply misusing +=? I mean CurrentString is a variable passed to method where this code is implemented and MIF_EmtyCharStyleMarker is a constant declared in another unit. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i           Case WordHTMLTag of            wht_Italics : CurrentString += MIF_ItalicMarker;            wht_Bold    : CurrentString += MIF_BoldMarker  ;            wht_span    : If IsOpeningTag                        then begin                            EmptyStr := HtmlClass = '';                            If EmptyStr then                             CurrentString += MIF_EmptyCharStyleMarker                          // CurrentString := CurrentString + MIF_EmptyCharStyleMarker                            else MIF_AddStartCharaTag(HTMLClass)                          end                        else If MIF_HasIllegalMarker(CurrentString)                             then CurrentString += MIF_EmptyCharStyleMarker                             else MIF_AddEndCharaTag;            else Assert(False, 'we should not bere here!');           end; ---------------------------------------------------------------------- Blaazen · 2017-10-18 01:22 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     CurrentString += MIF_EmptyCharStyleMarker    CurrentString := CurrentString + MIF_EmptyCharStyleMarkerThese two lines are identical. There must be something wrong elsewhere out of pasted code. ---------------------------------------------------------------------- munair · 2017-10-18 02:19 You are not misusing += but it is C-style. I never use that style, but from the manual I find that you must use the compiler directive {$COPERATORS ON} to support it. With a similar example, without the directive, I get a compile error "Variable identifier expected". Interestingly, WITH the directive I also get the same compile error. See the screenshot. If I replace += with normal fp syntax, everything compiles just fine. My suggestion: stick to native fp syntax. Even though it may look more verbose, the resulting code is the same. Example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit upcstyle; {$mode objfpc}{$H+}{$COPERATORS ON} interface uses  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls; type   { TForm1 }   TForm1 = class(TForm)    Label1: TLabel;    procedure FormCreate(Sender: TObject);  private    { private declarations }  public    { public declarations }  end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);var  EmptyStr: boolean;  HtmlClass: string;begin  EmptyStr := (HtmlClass = '');  if EmptyStr then    Label1.Caption += 'empty' //doesn't work    //Label1.Caption := Label1.Caption + 'empty' //works  else    Label1.Caption := 'not empty';end; end.  Steps to reproduce: Start a new project. Add a label to the form. Replace the code in unit1 with the example code. EDIT: I just learned that {$mode objfpc} already gives support to C style operators. It explains why the compiler keeps complaining. In the example above {$COPERATORS ON} doesn't make any difference. ---------------------------------------------------------------------- engkin · 2017-10-18 03:15 Quote from: EganSolo on October 18, 2017, 02:33:05 amBefore I get ahead of myself and post this as a bug, I thought I would ask here first. Consider line 8 in the code fragment below: The code uses +=, whereas the commented assignment on line nine  uses := When I run the code as is (with +=) and the boolean variable, EmptyStr on line seven is true, the debugger exits the method as if the code on lines eight and ten does not exist. But when I comment that line and uncomment line nine, then the code functions properly. Am I simply misusing +=? I mean CurrentString is a variable passed to method where this code is implemented and MIF_EmtyCharStyleMarker is a constant declared in another unit. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i           Case WordHTMLTag of            wht_Italics : CurrentString += MIF_ItalicMarker;            wht_Bold    : CurrentString += MIF_BoldMarker  ;            wht_span    : If IsOpeningTag                        then begin                            EmptyStr := HtmlClass = '';                            If EmptyStr then                             CurrentString += MIF_EmptyCharStyleMarker                          // CurrentString := CurrentString + MIF_EmptyCharStyleMarker                            else MIF_AddStartCharaTag(HTMLClass)                          end                        else If MIF_HasIllegalMarker(CurrentString)                             then CurrentString += MIF_EmptyCharStyleMarker                             else MIF_AddEndCharaTag;            else Assert(False, 'we should not bere here!');           end;  Your usage is correct. The generated code is also correct. There is a bug in the debug information, confirmed using -al in the compiler options When += is used here is the generated code: Quote.Ll28: # [46] If EmptyStr then    cmpb   $0,-20(%ebp)    je   .Lj58 .Ll29: # [49] else    pushl   $0    movl   8(%ebp),%eax    movl   (%eax),%edx    movl   8(%ebp),%eax    movl   TC_$P$PROJECT1_$$_MIF_EMPTYCHARSTYLEMARKER,%ecx    call   fpc_ansistr_concat    jmp   .Lj32 While with CurrentString := CurrentString + MIF_EmptyCharStyleMarker Quote.Ll28: # [46] If EmptyStr then    cmpb   $0,-20(%ebp)    je   .Lj58 .Ll29: # [48] CurrentString := CurrentString + MIF_EmptyCharStyleMarker    pushl   $0    movl   8(%ebp),%eax    movl   (%eax),%edx    movl   8(%ebp),%eax    movl   TC_$P$PROJECT1_$$_MIF_EMPTYCHARSTYLEMARKER,%ecx    call   fpc_ansistr_concat    jmp   .Lj32 Notice that the assembly is identical. Just the debug information is wrong. ---------------------------------------------------------------------- munair · 2017-10-18 03:23 Does that mean that the directive {$COPERATORS ON} no longer makes a difference? My example suggests it is not just the debugger. ---------------------------------------------------------------------- EganSolo · 2017-10-18 04:53 Thank you, everyone, for your thoughtful responses. This was extremely helpful and enlightening. I did not think to use the -al option, now I know better. So, should I report this as a bug? ---------------------------------------------------------------------- Thaddy · 2017-10-18 07:22 Quote from: Munair on October 18, 2017, 05:23:33 amDoes that mean that the directive {$COPERATORS ON} no longer makes a difference? My example suggests it is not just the debugger. Depends on mode: in objfpc mode it is on by default. In mode delphi it is off by default. So {$COPERATORS ON} is basically just required if you want to use it in other modes than {$mode objfpc} ---------------------------------------------------------------------- munair · 2017-10-18 07:45 Quote from: Thaddy on October 18, 2017, 09:22:07 amQuote from: Munair on October 18, 2017, 05:23:33 amDoes that mean that the directive {$COPERATORS ON} no longer makes a difference? My example suggests it is not just the debugger. Depends on mode: in objfpc mode it is on by default. In mode delphi it is off by default. So {$COPERATORS ON} is basically just required if you want to use it in other modes than {$mode objfpc} Then my example above should be considered a bug. I never use c-style operators. This is the first issue I run into taking the TS problem. ---------------------------------------------------------------------- Thaddy · 2017-10-18 07:47 I don't see the bug? ---------------------------------------------------------------------- munair · 2017-10-18 07:49 Quote from: Thaddy on October 18, 2017, 09:47:56 amI don't see the bug? See my first comment with screenshot. It doesn't compile here. Clearly the compiler expects something else from line 40 to 41. It doesn't seem to support the += construction followed by the ELSE statement. ---------------------------------------------------------------------- Thaddy · 2017-10-18 08:23 The C style operators need to be fully evaluated first. It is C style, and certainly not complete (e.g. use =+ etc are not implemented) ---------------------------------------------------------------------- munair · 2017-10-18 08:25 Quote from: Thaddy on October 18, 2017, 10:23:52 amThe C style operators need to be fully evaluated first. It is C style, and certainly not complete (e.g. use =+ etc are not implemented) Which is why I suggested to stick to FP syntax. ---------------------------------------------------------------------- Leledumbo · 2017-10-18 09:02 In this case, the two should be identical. Can you make a super simple example that still reproduce this issue so that we can confirm? ---------------------------------------------------------------------- munair · 2017-10-18 09:28 Quote from: Leledumbo on October 18, 2017, 11:02:57 amIn this case, the two should be identical. Can you make a super simple example that still reproduce this issue so that we can confirm? Even if I take out the ELSE condition, the compiler still complains: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if EmptyStr then  Label1.Caption += 'empty'; //complaint The compiler also complains without IF condition: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Label1.Caption += ''; //complaint However, the compiler does not complain when using simple variables: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var a: string;a += ''; //no complaintLabel1.Caption += ''; //complaint It looks like it has to do with the combination of object referencing. ---------------------------------------------------------------------- Blaazen · 2017-10-18 12:16 @ It looks like it has to do with the combination of object referencing. No. It has to do with properties. Operator += needs variable. Setters and getters have no address. It seems that CurrentString from the original post is a property. ---------------------------------------------------------------------- munair · 2017-10-18 14:15 Quote from: Blaazen on October 18, 2017, 02:16:56 pm@ It looks like it has to do with the combination of object referencing. No. It has to do with properties. Operator += needs variable. Setters and getters have no address. It seems that CurrentString from the original post is a property. Object properties are referenced / dereferenced during execution, if I'm not mistaken. So the problem is referencing as opposed to variable address. ---------------------------------------------------------------------- engkin · 2017-10-18 17:54 Quote from: Leledumbo on October 18, 2017, 11:02:57 amIn this case, the two should be identical. Can you make a super simple example that still reproduce this issue so that we can confirm? Consider the following program: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program minimal; {$mode objfpc}{$H+} uses {$IFDEF UNIX} {$IFDEF UseCThreads}  cthreads, {$ENDIF} {$ENDIF}  Classes { you can add units after this }; var  boolVar: boolean = True;  SomeVar: integer = 0;begin  if boolVar then    SomeVar += 1  else    SomeVar := SomeVar - 1;end. When you debug this program it should start at Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if boolVar thenthen: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     SomeVar += 1and finally: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i end.That is the expected behavior. BUT the current behavior is different at the second step. Instead of showing  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     SomeVar += 1it shows: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   else If you replace += with the full syntax  SomeVar := SomeVar + 1 you will see the correct expected behavior. Here is GDB output when using C operator: Quote13        if boolVar then (gdb) n 15        else (gdb) 17      end. (gdb) Here is GDB output *without* C operator: Quote13        if boolVar then (gdb) n 14          SomeVar := SomeVar + 1 (gdb) 17      end. (gdb) ---------------------------------------------------------------------- munair · 2017-10-18 18:15 @engkin, there seem to be two issues here (at least). 1. The debugger does not fully support C-style operators. 2. C-style operators can only be used with simple variables. As demonstrated in an earlier comment, C-style operators won't work with object properties. ---------------------------------------------------------------------- engkin · 2017-10-18 18:38 Quote from: Munair on October 18, 2017, 08:15:11 pm@engkin, there seem to be two issues here (at least). 1. The debugger does not fully support C-style operators. The debugger knows what FPC saved in the debug information. IAW, FPC generates wrong debug information for C operators. Specifically, wrong line number. ---------------------------------------------------------------------- munair · 2017-10-18 19:56 Quote from: engkin on October 18, 2017, 08:38:40 pmQuote from: Munair on October 18, 2017, 08:15:11 pm@engkin, there seem to be two issues here (at least). 1. The debugger does not fully support C-style operators. The debugger knows what FPC saved in the debug information. IAW, FPC generates wrong debug information for C operators. Specifically, wrong line number. Yes, thanks for correcting me there. Suffice it to say, better not use C-style operators. ---------------------------------------------------------------------- engkin · 2017-10-19 02:36 Quote from: Munair on October 18, 2017, 09:56:54 pmQuote from: engkin on October 18, 2017, 08:38:40 pmQuote from: Munair on October 18, 2017, 08:15:11 pm@engkin, there seem to be two issues here (at least). 1. The debugger does not fully support C-style operators. The debugger knows what FPC saved in the debug information. IAW, FPC generates wrong debug information for C operators. Specifically, wrong line number. Yes, thanks for correcting me there. Suffice it to say, better not use C-style operators. What if this bug is not limited to C operators? I believe this bug should be reported. ---------------------------------------------------------------------- EganSolo · 2017-10-19 03:42 Don't use C-style operators. Got it. So... should I report this or will someone else do it? I'm fine either way. I just want to know ---------------------------------------------------------------------- engkin · 2017-10-19 03:57 Yes, please do. Otherwise it will be forgotten. ---------------------------------------------------------------------- schuler · 2017-10-24 22:39 Quick note: Caption is a property (not a variable).