Changes between Version 39 and Version 40 of Guidelines/MaintenanceGuidelines


Ignore:
Timestamp:
Feb 3, 2010, 8:58:47 PM (13 years ago)
Author:
phorgan1
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Guidelines/MaintenanceGuidelines

    v39 v40  
    903903More information needed here!
    904904
    905 == Individual Warnings ==
     905=== Individual Warnings ===
    906906'''comparison between signed and unsigned integer expressions'''
    907907
     
    10361036        }}}
    10371037
    1038     and you had a keyword list to pass it like this:
     1038        and you had a keyword list to pass it that looked like this:
    10391039
    10401040        {{{
     
    10441044        }}}
    10451045
    1046         you would get the warning on the kwlist assignment, but when you change
     1046        you would get the warning on the kwlist assignment, because you're
     1047        assigning a const char * to char *, but when you correctly change
    10471048        it to:
    10481049
     
    10511052        }}}
    10521053
    1053         you'll get:
     1054        to get rid of the waring you'll get a warning on the call to
     1055        PyArg_ParseTupleAndKeywords:
    10541056
    10551057            error: invalid conversion from ‘const char**’ to ‘char**’
    10561058
    1057         unless you change the call to:
     1059        because the library function was declared as taking a char **
     1060        for the fourth argument.  Your only recourse is to cast away
     1061        the constness with a const_cast:
    10581062
    10591063        {{{
     
    10621066        }}}
    10631067
    1064         annoyingly having to incorrectly cast away the constness of kwlist.
    1065         Now the code is arguably correct and it wasn't before.
     1068        Annoying, yet more correct than before.
     1069
     1070'''dereferencing type-punned pointer will break strict-aliasing rules'''
     1071    this warning is only active when strict-aliasing optimization is active
     1072
     1073    '''-Wstrict-aliasing''' - equivalent to -Wstring-aliasing=3 (included in -Wall)[[BR]]
     1074    '''-Wstrict-aliasing=N''' where N is in {1,2,3} - Higher N implies less false positives, at the expense of more work.  Currently there are 3 levels.[[BR]]
     1075        Level 1: Most agressive, quick, very few false negatives, but many false positives.  Might use if higher levels don't warn, but turning on -fstrict-aliasing breaks the code.  Warns about pointer conversions even if pointer not dereferenced.[[BR]]
     1076        Level 2: Agressive, quick, not too precise.  Less false positives than Level 1, but more false negatives.  Only warns if pointer is dereferenced.[[BR]]
     1077        Level 3: Very few false positives and very few false negatives--the default.[[BR]]
     1078    '''-fstrict-aliasing''' - also turned on by -O2, -O3 and -Os.  Tells the compiler that it's ok to do a certain class of optimization based on the type of expressions.  In particular you're promising by using this flag that an object of one type won't reside at the same address as an object of an incompatible type.
     1079    '''-fno-strict-aliasing''' - turns off this optimization.  If this changes the behavior of your code, you have a problem in your code.
     1080
     1081    This is trying to let you know that you are asking the compiler to do undefined behavior and it may not do what you think it will do.  As the optimization level increases, the liklihood that you won't like what it does will increase.  I show a simple example later that surprisingly generates the wrong result when optimization at any level is turned on.  Ignore this warning at your own peril.  You are unlikely to care for the undefined behavior that results.
     1082{{{
     1083From the C++ Standard, section 3.10 Lvalues and rvalues
     1084      15   If a program attempts to access the stored value of an object through an lvalue of other than
     1085          one of the following types the behavior is undefined
     1086        — the dynamic type of the object,
     1087        — a cv-qualified version of the dynamic type of the object,
     1088        — a type similar (as defined in 4.4) to the dynamic type of the object,
     1089        — a type that is the signed or unsigned type corresponding to the dynamic type of the object,
     1090        — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
     1091        — an aggregate or union type that includes one of the aforementioned types among its member
     1092          (including, recursively, a member of a subaggregate or contained union),
     1093        — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
     1094        — a char or unsigned char type.
     1095}}}
     1096The following program generates 6 warnings about breaking strict-aliasing rules, and many would dismiss them.  The correct output of the program is:
     1097
     109800000020
     109900200000
     1100
     1101but when optimization is turned on it's:
     1102
     110300000020
     110400000020
     1105
     1106THAT's what the warning is trying to tell you, that the optimizer is going to do things that you don't like.  In this case seeing that acopy is set to a and never touched again, strict aliasing lets it optimize by just returning the original value of a at the end.
     1107{{{
     1108uint32_t
     1109swaphalves(uint32_t a)
     1110{
     1111    uint32_t acopy=a;
     1112    uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal.
     1113                                    // you should be warned by that.
     1114    uint16_t tmp=ptr[0];
     1115    ptr[0]=ptr[1];
     1116    ptr[1]=tmp;
     1117    return acopy;
     1118}
     1119
     1120int main()
     1121{
     1122    uint32_t a;
     1123    a=32;
     1124    cout << hex << setfill('0') << setw(8) << a << endl;
     1125    a=swaphalves(a);
     1126    cout << setw(8) << a << endl;
     1127}
     1128}}}
     1129Here's the (annotated) x86 assembler generated by gcc 4.4.1 for swaphalves, let's see what went wrong:
     1130{{{
     1131_Z10swaphalvesj:
     1132    pushl   %ebp
     1133    movl    %esp, %ebp
     1134    subl    $16, %esp
     1135    movl    8(%ebp), %eax   # get a in %eax
     1136    movl    %eax, -8(%ebp)  # and store in in acopy
     1137    leal    -8(%ebp), %eax  # now get eax pointing at acopy (ptr=&acopy)
     1138    movl    %eax, -12(%ebp) # save that ptr at -12(%ebp)
     1139    movl    -12(%ebp), %eax # get the ptr back in %eax
     1140    movzwl  (%eax), %eax    # get 16 bits from ptr[0] in eax
     1141    movw    %ax, -2(%ebp)   # store the 16 bits into tmp
     1142    movl    -12(%ebp), %eax # get the ptr back in eax
     1143    addl    $2, %eax        # bump up by two to get to ptr[1]
     1144    movzwl  (%eax), %edx    # get that 16 bits into %edx
     1145    movl    -12(%ebp), %eax # get ptr into eax
     1146    movw    %dx, (%eax)     # store the 16 bits into ptr[1]
     1147    movl    -12(%ebp), %eax # get the ptr again
     1148    leal    2(%eax), %edx   # get the address of ptr[1] into edx
     1149    movzwl  -2(%ebp), %eax  # get tmp into eax
     1150    movw    %ax, (%edx)     # store into ptr[1]
     1151    movl    -8(%ebp), %eax  # forget all that, return original a.
     1152    leave
     1153    ret
     1154}}}
     1155Scary, isn't it?  Of course you could use -fno-strict-aliasing to get the right output, but the generated code won't be as good.  A better way to accomplish the same thing without the warning's or the incorrect output is to define swaphalves like this:
     1156
     1157{{{
     1158uint32_t
     1159swaphalves(uint32_t a)
     1160{
     1161    union swapem{
     1162        uint32_t a;
     1163        uint16_t b[2];
     1164    };
     1165    swapem s={a};
     1166    uint16_t tmp;
     1167    tmp=s.b[0];
     1168    s.b[0]=s.b[1];
     1169    s.b[1]=tmp;
     1170    return s.a;
     1171}
     1172}}}
     1173The C++ compiler knows that members of a union alias, and this helps the compiler generate MUCH better code:
     1174{{{
     1175_Z10swaphalvesj:
     1176    pushl   %ebp                        # save the original value of ebp
     1177    movl    %esp, %ebp          # point ebp at the stack frame
     1178    movl    8(%ebp), %eax       # get a in eax
     1179    popl    %ebp                        # get the original ebp value back
     1180    roll    $16, %eax           # swap the two halves of a and return it
     1181    ret
     1182}}}
     1183
     1184   
     1185
     1186
     1187
     1188
    10661189
    10671190 |? || class does not have a  virtual destructor||Suppress or provide a virtual destructor.||??||