• AVR Freaks

Compiler bug. if() statement - missing code

Page: 12 > Showing page 1 of 2
Author
pcmgold
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2017/06/30 01:54:41
  • Location: 0
  • Status: offline
2017/06/30 20:51:14 (permalink)
3 (1)

Compiler bug. if() statement - missing code

Compiler produces no code with if() statement when comparing char variable against a constant.  XC16
I would class this as a serious compiler bug!
There is no warning and the resultant code is missing in the output (program memory). That is the if statement and the entire code between the brackets is missing. If you try to place a breakpoint on it, the debugger also shows/says no such code at this point, and won't set a breakpoint on it.
 
#define TEST_VALUE 0xFF  
    char c;
 
    if(c == TEST_VALUE)     // produces missing code
      {
      ......
      }
 
0xFF should in effect resolve to -1 with char.
in fact any value 0x80 and above fails.
Whats worse about this is that there is NO compiler warning that the compiler had any problem with it and has striped this code from the output.
 
If we set up another variable and assign the constant to it, then the correct code is produced.
Apart from pre-fetching the value from a variable 't' the above should have produced effectively the same code.
 
#define TEST_VALUE 0xFF  
    char c;
    char t = TEST_VALUE;
 
    if(c == t)     // produces correct code
      {
      ......
      }
 
 
The int counterpart of this code does produce code so further proof the above is a compiler bug.
 
#define TEST_VALUE 0xFFFF 
    int c;
 
    if(c == TEST_VALUE)   // the int version works correctly
      {
      ......
      }
 
 
 
#1

30 Replies Related Threads

    du00000001
    Just Some Member
    • Total Posts : 3225
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/01 09:32:42 (permalink)
    +3 (3)
    Compiler bug? Nope.
    Cast TEST_VALUE to chat (either in the #define or when using it) and stop complaining!
    Could it be that you set "char" to be "unsigned char" in the compiler options?
    #2
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3333
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/01 09:45:44 (permalink)
    0
    Not a compiler bug.
     
    "0xFF should in effect resolve to -1 with char."
     
    But a single char takes up 2bytes in 16bit land, so does a bool.
     
    resolved.
    char t = TEST_VALUE;
    #3
    simong123
    Lab Member No. 003
    • Total Posts : 1315
    • Reward points : 0
    • Joined: 2012/02/07 18:21:03
    • Location: Future Gadget Lab (UK Branch)
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/01 09:57:31 (permalink)
    +2 (2)
    Gort2015
    But a single char takes up 2bytes in 16bit land, so does a bool.

    ???? WTF
    Rubbish. As per the standard, char takes up 1 byte in any land you can think of.
    #4
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11420
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/01 10:43:07 (permalink)
    +1 (1)
    #define TEST_VALUE 0xFF  
    char c;
    if(c == TEST_VALUE) 

     
    Don't use plain char as a small integer.  Used signed char or unsigned char.  Whether plain char is signed or not is implementation defined.  This will help reduce misunderstandings in the future.
     
    In this code, the "==" operator promotes 0xFF and c to "int", so you are comparing c with 255, not -1.  If you want to compare c with -1, use -1 in your code, not 0xFF.  You haven't shown what value is in "c" so it's not clear what your expectation was.
     
    #define TEST_VALUE 0xFFFF 
    int c;
    if(c == TEST_VALUE)   // the int version works correctly

     
    0xFFFF is an unsigned int, so comparing it with an "int" is asking for trouble, since C's rules for converting between signed and unsigned can be surprising.  If you had loaded -1 into "c" here, the conversion would have given you the expected result, but again, if you want -1, put -1 in your code.
    #5
    NorthGuy
    Super Member
    • Total Posts : 5799
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/01 11:30:12 (permalink)
    +1 (1)
    You can use a character constant:
     
    #define TEST_VALUE '\xFF'

     
    This will be converted to int using the same rules as the char on the left, so the comparison will come out correct. If char is signed, the value will be 0xffff. If char is unsigned, the value will be 0xff.
     
    Or, better yet, use "int8_t" or "uint8_t" instead of "char". This removes the ambiguity.
     
    #6
    pcmgold
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2017/06/30 01:54:41
    • Location: 0
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 05:54:55 (permalink)
    -3 (5)
    This is a compiler bug! it has been tracked right back to the final output assembly code.

    I know exactly how to get round this bug, (I had already worked that out, thanks)
    The point of the post is make known the bug.

    The bug is that no output code whatsoever is produced and there is no warning that the compiler is unhappy with the code and has in effect commented out the entire code out of existence.

    The value of 'c' is irreverent, the problem is that compiler produces no code, and no comparison is done.

    As far as the == promoting to an 'int' this is not true. by definition it casts to the highest variable size.

    In this case a byte,  which is in-fact the test done at the assembly level is a single byte test,( when output code is produced.)

     As far as a char is concerned unless overridden by compiler settings, a char is required to be treated as a signed byte value by its very definition. But to keep everyone happy I have fully defined it.

     As far as 'int8_t'  it is defined as a "signed char" and uint8_t is defined as "unsigned char".   so the use of this in this case makes absolutely no difference.

     #define TEST_VALUE '\xFF'

     does in-effect cast as a char and when comparing with a char variable works, but if compared with an unsigned char will again fail and produces no code.

    These are the conditions that fail,



    //case 1 - signed char
    signed char c;

    if(c == 0xFF) // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }


    //case 2 - unsigned char
    unsigned char c;

    if(c == '\xFF') // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }

    if(c == -1) // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }




     In all cases the compiler is required! to produce output code ( which is likely to be the same effective output assembly code).
    The warning that some compilers may/do issue is 'comparing signed and unsigned values'

    Every other compiler i have used produces the right result including XC8, except XC16 which fails.
    Q: What is the procedure and where do we report compiler bugs to, to get them fixed?

    NOTE: The way around bug is to cast the constant as appropriate, failure to do so will produce no warnings and you will never know you have a problem.  Your first hint will be when you find you code does not work as expected. To find the problem will likely take a lot of work tracing through your code only to find the output assembly code it is missing.


    post edited by pcmgold - 2017/07/02 06:02:34
    #7
    NorthGuy
    Super Member
    • Total Posts : 5799
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 07:03:23 (permalink)
    +5 (5)
    Before the comparison, C is required to apply "integer promotion" and then it compares the resulting integers.
     
    pcmgold
    //case 1 - signed char
    signed char c;

    if(c == 0xFF) // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }


     
    When converted to int, left side is sign-extended (because you declared it as signed). Possible values will be 0x00 to 0x7f and 0xff80 to 0xffff. None of them is 0xff. So the comparison is always false. The compiler is smart enough to figure that out and it doesn't produce any code.
     
    pcmgold
    //case 2 - unsigned char
    unsigned char c;

    if(c == '\xFF') // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }


     
    This would work if you used "char" instead of "unsigned char". I suggested this as something which works without knowing if "char" is signed or unsigned. If their "char" is signed, then it's 0xffff on the right. The range of possible values on the left is 0x00 to 0xff (because you declared it as unsigned). So, the comparison is never true - the compiler simply removes the redundant code which will never execute.
     
    pcmgold
    unsigned char c;
    if(c == -1) // no output code is produced. and no warnings
      {
      ... // this includes all code between the { } missing
      }


     
    In this case, you probably can figure by yourself that anything unsigned cannot be equal to anything negative.


    #8
    1and0
    Access is Denied
    • Total Posts : 9977
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 07:23:31 (permalink)
    +3 (3)
    Agree with NG's analysis in Post #8.
     
    For information only, the type of a plain char is signed char for XC16 and XC32, while it is unsigned char for XC8.
     
    <edit> To summary it up:
     
    case 1:
    (0x0000 to 0x007F, 0xFF80 to 0xFFFF ) != 0x00FF
     
    case 2:
    (0x0000 to 0x00FF) != 0xFFFF
     
    case 3:
    (0x0000 to 0x00FF) != 0xFFFF
     
    These conditional tests are ALWAYS false, so the compiler removes code that will never execute.
    post edited by 1and0 - 2017/07/02 07:43:56
    #9
    1and0
    Access is Denied
    • Total Posts : 9977
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 08:02:06 (permalink)
    +2 (2)
    Applying the same analysis to the snippets in Post #1,
     
    case1: comparing char c to 0xFF
    (0x0000 to 0x007F, 0xFF80 to 0xFFFF ) <> 0x00FF (always false)
     
    case2: comparing char c to char t
    (0x0000 to 0x007F, 0xFF80 to 0xFFFF ) == 0xFFFF
     
    case3: comparing int c to 0xFFFF
    (0x0000 to 0xFFFF) == 0xFFFF
    post edited by 1and0 - 2017/07/02 08:04:13
    #10
    NKurzman
    A Guy on the Net
    • Total Posts : 18027
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 09:01:39 (permalink)
    +2 (2)
    If the compiler determines that code will never be executed, then it I allowed to not included it. It is how the optimizer works.
    Yes it can be annoying. But you need to learn how the tools behave, this will allow to trouble shoot faster.

    If a char is signed or unsigned is implementation defined. It is not required to be signed.
    The other compiler do this does not mean anything. There are many implementation Defined rules in compilers.
    post edited by NKurzman - 2017/07/02 09:06:29
    #11
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3333
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 10:31:00 (permalink)
    0
    simong123
    Gort2015
    But a single char takes up 2bytes in 16bit land, so does a bool.

    ???? WTF
    Rubbish. As per the standard, char takes up 1 byte in any land you can think of.


    When you manipulate it, it is 2bytes in 16bit land.  (Not the storage)
     
    void mybyte(char X);
    .equ arg_X,w0   ;16bit word
    _mybyte:
    cp0.b w0
    return
     
     
    post edited by Gort2015 - 2017/07/02 10:32:22
    #12
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11420
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 10:34:48 (permalink)
    +2 (4)
    I've quoted from the C99 standard below to clarify some of your misunderstandings:
     
    pcmgoldAs far as the == promoting to an 'int' this is not true. by definition it casts to the highest variable size.

     
    "6.5.9 Equality operators: If both of the operands have arithmetic type, the usual arithmetic conversions are performed.
     
    6.3.1.8 Usual arithmetic conversions: [...] Otherwise, the integer promotions are performed on both operands.
     
    6.3.1 Arithmetic operands

    If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions." 

    As far as a char is concerned unless overridden by compiler settings, a char is required to be treated as a signed byte value by its very definition

     
    "The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char."
     
    In all cases the compiler is required! to produce output code

     
    "In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object)."
     
    #13
    Weydert
    Super Member
    • Total Posts : 483
    • Reward points : 0
    • Joined: 2008/07/02 04:22:40
    • Location: Aachen/Germany
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/02 23:23:02 (permalink)
    0
    hi pcmgold,
     
    NOTE: The way around bug is to cast the constant as appropriate, failure to do so will produce no warnings and you will never know you have a problem. Your first hint will be when you find you code does not work as expected. To find the problem will likely take a lot of work tracing through your code only to find the output assembly code it is missing.

     
    I never thought that a simple 'if (c==0xFF) ' could cause such trouble. So thank you for your hint.
     
    The other thing is: I saw a lot of threads in this forum and yes, someone can vote a post negative. But normally no one does. One of your posts was voted -1 by 3 forum members. I never saw such an aggressive reaction before. It is not normal in this forum.
     
    #14
    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 00:46:11 (permalink)
    +2 (2)
    Disclaimer, I was not one that voted it negative. Most of the time I couldn't be bothered.
    However, I do think a number of people get pretty annoyed when someone starts complaining that particular behaviour  is "a compiler bug", and quoting that "compilers are required to...", when they do not actually know what the C standard says.
    Have a careful read of what jtemples posted in #13.
    I can assure, you, when John quotes from the C standard, he knows what he is talking about.
     
    #15
    pcmgold
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2017/06/30 01:54:41
    • Location: 0
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 07:43:53 (permalink)
    -1 (1)
    The point of the post was only to say that there seems to be a problem...
     
    I have actually got the C standard in front of me WG14-(2007) which is the draft of C11 (2011), which supersedes C99 (1999 )
    never the less this definition of type conversion rank method has never changed.
     
    1) It clearly states that values/variables always promote/conversion up the the highest "rank" (size) of type(s) in use of the arithmetic equation in progress, and where possible the value is to be preserved ie signed extended. 
    2) In the event that the number can not be preserved, both numbers are to be treated as unsigned type.
     
    3) When the values are of the same type no promotion/conversion is to be done.  
    ie 2 values of type char are to be treated as type char size equation.  (as suggested by someone previously the char is promoted to int. - this is not true. With all values being of char the whole arithmetic equation is done at 8 bit level. If you do actually look at the assembly/binary code produced it is in-fact done at this single byte level)
     
    4) It also specifically states that "when dealing with signed char = constant of 0xFF  or '\FF' it is to be treated/interpenetrated as -1, and with unsigned char as 255."  This is given as an example in the 'C standard'
     
    In the event of a comparison ie if(==) first all the operators undergo the normal conversion (ie highest "rank" as described above ) for the arithmetic comparison.   the 'result' from the test is to be of type int either 1 or 0, true or false.  ( it is the result that is to be promoted/demoted to type int not the the operators being compared.)
     
    (what is the size limit on a post as i have had to split it in 2 to post ? )
     
    #16
    1and0
    Access is Denied
    • Total Posts : 9977
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 08:13:08 (permalink)
    +2 (2)
    pcmgold
    3) When the values are of the same type no promotion/conversion is to be done.  
    ie 2 values of type char are to be treated as type char size equation.  (as suggested by someone previously the char is promoted to int. - this is not true. With all values being of char the whole arithmetic equation is done at 8 bit level. If you do actually look at the assembly/binary code produced it is in-fact done at this single byte level)

     
    I'm no C expert, but be assured that John (jtemple) or Jeff (mad_c) can provide more details.
     
    From my understanding, the XC compilers conform to the ANS X3.159-1989 Standard. This is commonly called the C89 Standard. Some features from the C99 Standard are also supported.
     
    That said, integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. That is, integer promotions require the promotion of the type char variables to int size before the comparison is performed.
     
    post edited by 1and0 - 2017/07/03 08:23:00
    #17
    simong123
    Lab Member No. 003
    • Total Posts : 1315
    • Reward points : 0
    • Joined: 2012/02/07 18:21:03
    • Location: Future Gadget Lab (UK Branch)
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 08:24:08 (permalink)
    +1 (1)
    From the document you quote
    EXAMPLE 2 In executing the fragment
    char c1, c2;
    /* ... */
    c1 = c1 + c2;
    the ‘ ‘integer promotions’ ’require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. Provided the addition of two chars can be done without overflow, or with overflow wrapping silently to produce the correct result, the actual execution need only produce the same result, possibly omitting the promotions.

    post edited by simong123 - 2017/07/03 08:26:02
    #18
    Weydert
    Super Member
    • Total Posts : 483
    • Reward points : 0
    • Joined: 2008/07/02 04:22:40
    • Location: Aachen/Germany
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 08:59:53 (permalink)
    0
    char c;
    c=0xFF;
    if (c==0xFF)
    {
       ...catch me if you can
    }

     
    Whether bug or not. Quite funny and against all logic. Even more if the behavior depends on the compiler you use. Quite sure that Microsoft compilers will produce a warning like "compare sigend with unsigned" ( I have no C compiler from Microsoft, only C++ 6.0: in this case 0xFF is treated as a byte and not as an integer)
    #19
    1and0
    Access is Denied
    • Total Posts : 9977
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Compiler bug. if() statement - missing code 2017/07/03 09:16:16 (permalink)
    +1 (1)
    Weydert
    char c;
    c=0xFF;
    if (c==0xFF)
    {
       ...catch me if you can
    }

    Whether bug or not. Quite funny and against all logic. Even more if the behavior depends on the compiler you use. Quite sure that Microsoft compilers will produce a warning like "compare sigend with unsigned" ( I have no C compiler from Microsoft, only C++ 6.0: in this case 0xFF is treated as a byte and not as an integer)

    No bug there. The variable c gets promoted to int size and the constant 0xFF is already int size -- both signed for XC16. That comparison will get optimized out as the test is ALWAYS true.
     
    <edit> I see your point after looking a bit closer.  That comparison is ALWAYS false -- interesting!
    post edited by 1and0 - 2017/07/03 10:28:51
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5