Is this failing test that adds zero to a null pointer undefined behaviour, a compiler bug, or something else?

The name of the pictureThe name of the pictureThe name of the pictureClash 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 of end() etc.

Workaround:



If I change my end method to the following, the failing static_asserts 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. :-/










share|improve this question



























    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 of end() etc.

    Workaround:



    If I change my end method to the following, the failing static_asserts 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. :-/










    share|improve this question

























      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 of end() etc.

      Workaround:



      If I change my end method to the following, the failing static_asserts 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. :-/










      share|improve this question















      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 of end() etc.

      Workaround:



      If I change my end method to the following, the failing static_asserts 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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 41 mins ago

























      asked 1 hour ago









      Charles L Wilcox

      540214




      540214






















          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).






          share|improve this answer




















            Your Answer





            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            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






























            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).






            share|improve this answer
























              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).






              share|improve this answer






















                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).






                share|improve this answer












                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).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 1 hour ago









                Brian

                61.3k791175




                61.3k791175



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    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













































































                    Popular posts from this blog

                    How to check contact read email or not when send email to Individual?

                    Christian Cage

                    How to properly install USB display driver for Fresco Logic FL2000DX on Ubuntu?