[cfe-dev] clang-cl issue with MSVC's safeint.h and cast-to-self prvalue-ness
Stephan Bergmann via cfe-dev
cfe-dev at lists.llvm.org
Fri Apr 7 00:42:55 PDT 2017
I came across the following problem with clang-cl (in the context of
compiling LibreOffice) when using the MSVC-provided safeint.h (resp. its
safeinit_internal.h helper; on my machine located at C:\Program Files
(x86)\Windows Kits\10\Include\10.0.10240.0\ucrt\safeint_internal.h):
There is a specialization of some LargeIntRegMultiply::RegMultiply
> template < typename E > class LargeIntRegMultiply< signed __int64, signed __int64, E >
> {
> public:
> static SafeIntError RegMultiply( const signed __int64& a, const signed __int64& b, signed __int64& ret )
> {
> bool aNegative = false;
> bool bNegative = false;
>
> unsigned __int64 tmp;
> __int64 a1 = a;
> __int64 b1 = b;
...
>
> if( LargeIntRegMultiply< unsigned __int64, unsigned __int64, E >::
> RegMultiply( (unsigned __int64)a1, (unsigned __int64)b1, (unsigned __int64)tmp ) == SafeIntNoError )
> {
...
that calls another such specialization (namely
> template< typename E > class LargeIntRegMultiply< unsigned __int64, unsigned __int64, E >
> {
> public:
> static SafeIntError RegMultiply( const unsigned __int64& a, const unsigned __int64& b, unsigned __int64& ret )
...
for unsigned) which takes its third argument by non-const
lvalue-reference. But what gets passed at the call site above,
> (unsigned __int64)tmp
is the result of needlessly casting tmp (which is already of type
unsigned __int64), which shall produce a prvalue, which in turn cannot
bind to a non-const lvalue-reference. So compiling that with clang-cl
fails.
But with MSVC (at least 2013--2017) it succeeds. That compiler
apparently has a bug or mis-feature so that the result of casting an
lvalue to its own type produces an lvalue instead of a prvalue. (As
verified, at least for C-style cast and static_cast, and at least if the
type is some integral type).
Do we have some contact into the MSVC compiler group, so we can clarify
whether that behavior is considered a mis-feature (so we would want to
mimic it in some way in clang-cl, at least when compiling the
MSVC-provided safeint.h) or a bug (so MSVC would want to fix their
safeint.h, and we probably wouldn't want to duplicate that misbehavior
in clang-cl)?
(I would assume it is a genuine bug, which that sloppy
safeint_internal.h just happens to rely on by accident, as it makes the
below program behave in an IMO non-conforming way by printing 1 instead
of 0:
> #include <iostream>
> namespace {
> int n = 0;
> void f() { n = 1; }
> int g(int const & n) { f(); return n; }
> }
> int main() {
> std::cout << g(static_cast<int>(n)) << '\n';
> }
But who knows.)
More information about the cfe-dev
mailing list