Is this failing test that adds zero to a null pointer undefined behaviour, a compiler bug, or something else?
Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
I wrote a lightweight 'string_view' wrapper for a C++14 project, and with MSVC 2017 it is triggering a static_assert
at compile-time, yet the same code at run-time is passes the regular assert
. My question is, is this a compiler bug, manifest undefined behaviour, or something else entirely?
Here's the distilled code:
#include <cassert> // assert
#include <cstddef> // size_t
class String_View
char const* m_data;
std::size_t m_size;
public:
constexpr String_View()
: m_data( nullptr ),
m_size( 0u )
constexpr char const* begin() const noexcept
return m_data;
constexpr char const* end() const noexcept
return m_data + m_size;
;
void static_foo()
constexpr String_View sv;
// static_assert( sv.begin() == sv.end() ); // this errors
static_assert( sv.begin() == nullptr );
// static_assert( sv.end() == nullptr ); // this errors
void dynamic_foo()
String_View const sv;
assert( sv.begin() == sv.end() ); // this compiles & is optimized away
assert( sv.begin() == nullptr );
assert( sv.end() == nullptr ); // this compiles & is optimized away
Here's a Compiler Explorer link that I used to replicate the problem: https://godbolt.org/z/TpnE8o
From what I can tell, adding or subtracting 0
from any pointer value is always valid:
c++ - Is the behavior of subtracting two NULL pointers defined? - Stack Overflow, last blockquote
Additive operators - cppreference.com, last bullet of the last bullet-list
libstdc++: string_view Source File, implementation ofend()
etc.
Workaround:
If I change my end
method to the following, the failing static_assert
s will pass.
constexpr char const* end() const noexcept
return ( m_data == nullptr
? m_data
: m_data + m_size );
Tinkering:
I thought maybe the expression m_data + m_size
itself is UB, before the fact that m_size == 0
is evaluated. Yet, if I replace the implementation of end
with the nonsensical return m_data + 0;
, this still generates the two static_assert
errors. :-/
c++ c++14 undefined-behavior compiler-bug
add a comment |Â
up vote
7
down vote
favorite
I wrote a lightweight 'string_view' wrapper for a C++14 project, and with MSVC 2017 it is triggering a static_assert
at compile-time, yet the same code at run-time is passes the regular assert
. My question is, is this a compiler bug, manifest undefined behaviour, or something else entirely?
Here's the distilled code:
#include <cassert> // assert
#include <cstddef> // size_t
class String_View
char const* m_data;
std::size_t m_size;
public:
constexpr String_View()
: m_data( nullptr ),
m_size( 0u )
constexpr char const* begin() const noexcept
return m_data;
constexpr char const* end() const noexcept
return m_data + m_size;
;
void static_foo()
constexpr String_View sv;
// static_assert( sv.begin() == sv.end() ); // this errors
static_assert( sv.begin() == nullptr );
// static_assert( sv.end() == nullptr ); // this errors
void dynamic_foo()
String_View const sv;
assert( sv.begin() == sv.end() ); // this compiles & is optimized away
assert( sv.begin() == nullptr );
assert( sv.end() == nullptr ); // this compiles & is optimized away
Here's a Compiler Explorer link that I used to replicate the problem: https://godbolt.org/z/TpnE8o
From what I can tell, adding or subtracting 0
from any pointer value is always valid:
c++ - Is the behavior of subtracting two NULL pointers defined? - Stack Overflow, last blockquote
Additive operators - cppreference.com, last bullet of the last bullet-list
libstdc++: string_view Source File, implementation ofend()
etc.
Workaround:
If I change my end
method to the following, the failing static_assert
s will pass.
constexpr char const* end() const noexcept
return ( m_data == nullptr
? m_data
: m_data + m_size );
Tinkering:
I thought maybe the expression m_data + m_size
itself is UB, before the fact that m_size == 0
is evaluated. Yet, if I replace the implementation of end
with the nonsensical return m_data + 0;
, this still generates the two static_assert
errors. :-/
c++ c++14 undefined-behavior compiler-bug
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I wrote a lightweight 'string_view' wrapper for a C++14 project, and with MSVC 2017 it is triggering a static_assert
at compile-time, yet the same code at run-time is passes the regular assert
. My question is, is this a compiler bug, manifest undefined behaviour, or something else entirely?
Here's the distilled code:
#include <cassert> // assert
#include <cstddef> // size_t
class String_View
char const* m_data;
std::size_t m_size;
public:
constexpr String_View()
: m_data( nullptr ),
m_size( 0u )
constexpr char const* begin() const noexcept
return m_data;
constexpr char const* end() const noexcept
return m_data + m_size;
;
void static_foo()
constexpr String_View sv;
// static_assert( sv.begin() == sv.end() ); // this errors
static_assert( sv.begin() == nullptr );
// static_assert( sv.end() == nullptr ); // this errors
void dynamic_foo()
String_View const sv;
assert( sv.begin() == sv.end() ); // this compiles & is optimized away
assert( sv.begin() == nullptr );
assert( sv.end() == nullptr ); // this compiles & is optimized away
Here's a Compiler Explorer link that I used to replicate the problem: https://godbolt.org/z/TpnE8o
From what I can tell, adding or subtracting 0
from any pointer value is always valid:
c++ - Is the behavior of subtracting two NULL pointers defined? - Stack Overflow, last blockquote
Additive operators - cppreference.com, last bullet of the last bullet-list
libstdc++: string_view Source File, implementation ofend()
etc.
Workaround:
If I change my end
method to the following, the failing static_assert
s will pass.
constexpr char const* end() const noexcept
return ( m_data == nullptr
? m_data
: m_data + m_size );
Tinkering:
I thought maybe the expression m_data + m_size
itself is UB, before the fact that m_size == 0
is evaluated. Yet, if I replace the implementation of end
with the nonsensical return m_data + 0;
, this still generates the two static_assert
errors. :-/
c++ c++14 undefined-behavior compiler-bug
I wrote a lightweight 'string_view' wrapper for a C++14 project, and with MSVC 2017 it is triggering a static_assert
at compile-time, yet the same code at run-time is passes the regular assert
. My question is, is this a compiler bug, manifest undefined behaviour, or something else entirely?
Here's the distilled code:
#include <cassert> // assert
#include <cstddef> // size_t
class String_View
char const* m_data;
std::size_t m_size;
public:
constexpr String_View()
: m_data( nullptr ),
m_size( 0u )
constexpr char const* begin() const noexcept
return m_data;
constexpr char const* end() const noexcept
return m_data + m_size;
;
void static_foo()
constexpr String_View sv;
// static_assert( sv.begin() == sv.end() ); // this errors
static_assert( sv.begin() == nullptr );
// static_assert( sv.end() == nullptr ); // this errors
void dynamic_foo()
String_View const sv;
assert( sv.begin() == sv.end() ); // this compiles & is optimized away
assert( sv.begin() == nullptr );
assert( sv.end() == nullptr ); // this compiles & is optimized away
Here's a Compiler Explorer link that I used to replicate the problem: https://godbolt.org/z/TpnE8o
From what I can tell, adding or subtracting 0
from any pointer value is always valid:
c++ - Is the behavior of subtracting two NULL pointers defined? - Stack Overflow, last blockquote
Additive operators - cppreference.com, last bullet of the last bullet-list
libstdc++: string_view Source File, implementation ofend()
etc.
Workaround:
If I change my end
method to the following, the failing static_assert
s will pass.
constexpr char const* end() const noexcept
return ( m_data == nullptr
? m_data
: m_data + m_size );
Tinkering:
I thought maybe the expression m_data + m_size
itself is UB, before the fact that m_size == 0
is evaluated. Yet, if I replace the implementation of end
with the nonsensical return m_data + 0;
, this still generates the two static_assert
errors. :-/
c++ c++14 undefined-behavior compiler-bug
c++ c++14 undefined-behavior compiler-bug
edited 43 mins ago
asked 1 hour ago
Charles L Wilcox
540214
540214
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
5
down vote
I think that this is definitely a bug in the way MSVC evaluates constant expressions, since GCC and Clang have no issues with the code, and the standard is clear that adding 0 to a null pointer yields a null pointer ([expr.add]/7).
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
I think that this is definitely a bug in the way MSVC evaluates constant expressions, since GCC and Clang have no issues with the code, and the standard is clear that adding 0 to a null pointer yields a null pointer ([expr.add]/7).
add a comment |Â
up vote
5
down vote
I think that this is definitely a bug in the way MSVC evaluates constant expressions, since GCC and Clang have no issues with the code, and the standard is clear that adding 0 to a null pointer yields a null pointer ([expr.add]/7).
add a comment |Â
up vote
5
down vote
up vote
5
down vote
I think that this is definitely a bug in the way MSVC evaluates constant expressions, since GCC and Clang have no issues with the code, and the standard is clear that adding 0 to a null pointer yields a null pointer ([expr.add]/7).
I think that this is definitely a bug in the way MSVC evaluates constant expressions, since GCC and Clang have no issues with the code, and the standard is clear that adding 0 to a null pointer yields a null pointer ([expr.add]/7).
answered 1 hour ago
Brian
61.3k791175
61.3k791175
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52808357%2fis-this-failing-test-that-adds-zero-to-a-null-pointer-undefined-behaviour-a-com%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password