Skip to content

Commit

Permalink
MVTGeometryWriter: encode point difference in a C/C++ compliant way
Browse files Browse the repository at this point in the history
cppcheck warns that vx >> 31 is undefined behaviour when vx is signed.

More generally, bitwise operations on signed integers are implementation
defined behaviour.
See https://wiki.sei.cmu.edu/confluence/display/c/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands

So use the ( quint32 )( -( qint32 )( ( quint32 )vx >> 31 ) ) ) trick instead.

Demo:
- if vx is negative, (quint32)vx >> 31 leads to 1, which then becomes -1,
  which then becomes 0xFFFFFFFF when cast to unsigned.
- if vx is >= 0, this leads to 0.

gcc compiles both non-compliant and compliant versions identically. Given
test.cpp with
```
unsigned foo(int x)
{
    return x >> 31;
}

unsigned bar(int x)
{
    return (unsigned)(-(int)((unsigned)x >> 31));
}
```

g++ -O2 test.cpp -c && objdump -d test.o :

```
0000000000000000 <_Z3fooi>:
   0:	89 f8                	mov    %edi,%eax
   2:	c1 f8 1f             	sar    $0x1f,%eax
   5:	c3                   	retq
   6:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
   d:	00 00 00

0000000000000010 <_Z3bari>:
  10:	89 f8                	mov    %edi,%eax
  12:	c1 f8 1f             	sar    $0x1f,%eax
  15:	c3                   	retq
```
  • Loading branch information
rouault committed May 29, 2020
1 parent bae8226 commit 5dd4af7
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/core/vectortile/qgsvectortilemvtencoder.cpp
Expand Up @@ -67,8 +67,10 @@ struct MVTGeometryWriter
qint32 vx = pt.x() - cursor.x();
qint32 vy = pt.y() - cursor.y();

feature->add_geometry( ( vx << 1 ) ^ ( vx >> 31 ) );
feature->add_geometry( ( vy << 1 ) ^ ( vy >> 31 ) );
// (quint32)(-(qint32)((quint32)vx >> 31)) is a C/C++ compliant way
// of doing vx >> 31, which is undefined behaviour since vx is signed
feature->add_geometry( ( ( quint32 )vx << 1 ) ^ ( ( quint32 )( -( qint32 )( ( quint32 )vx >> 31 ) ) ) );
feature->add_geometry( ( ( quint32 )vy << 1 ) ^ ( ( quint32 )( -( qint32 )( ( quint32 )vy >> 31 ) ) ) );

cursor = pt;
}
Expand Down

0 comments on commit 5dd4af7

Please sign in to comment.