[cfe-dev] Question on constexpr

Nuno Lopes nunoplopes at sapo.pt
Mon Jul 23 09:22:05 PDT 2012


Quoting Richard Smith <richard at metafoo.co.uk>:

> On Sun, Jul 22, 2012 at 5:49 PM, Howard Hinnant <hhinnant at apple.com> wrote:
>
>> I'm playing with this code created by Scott Schurr and presented at C++Now:
>>
>> http://cppnow.org/session/cpp11-new-tools-for-class-and-library-authors/
>>
>> #include <cstddef>
>> #include <stdexcept>
>>
>> class str_const
>> {
>>     const char* const p_;
>>     const std::size_t  sz_;
>> public:
>>     template<std::size_t N>
>>         constexpr str_const(const char(&a)[N]) :
>>            p_(a), sz_(N-1) {}
>>
>>     constexpr char operator[](std::size_t n)
>>     {
>>         return n < sz_ ? p_[n] : throw std::out_of_range("");
>>     }
>>
>>     constexpr std::size_t size() { return sz_; }
>> };
>>
>> template <class T = std::size_t>
>> constexpr
>> inline
>> T
>> binary_const(str_const b, std::size_t n = 0, T x = 0)
>> {
>>     return n == b.size() ? x :
>>            b[n] == ',' ? binary_const<T>(b, n+1, x) :
>>            b[n] == ' ' ? binary_const<T>(b, n+1, x) :
>>            b[n] == '0' ? binary_const<T>(b, n+1, x*2) :
>>            b[n] == '1' ? binary_const<T>(b, n+1, x*2+1) :
>>            throw std::domain_error("Only '0', '1', ',', and ' ' may be
>> used");
>> }
>>
>> int main()
>> {
>>     constexpr str_const test("Hi Mom!");
>>     static_assert(test.size() == 7, "");
>>     static_assert(test[6] == '!', "");
>>     constexpr unsigned i = binary_const("1111,0000");
>>     return i;
>> }
>>
>> $ clang++ -std=c++11 -stdlib=libc++ -O3  test.cpp -S
>>
>> Everything compiles and runs great (I know, I'm never happy).  But when I
>> inspect the assembly of main I see:
>>
>>         callq   __Z12binary_constImET_9str_constmS0_
>>         movl    $240, %eax
>>         popq    %rbp
>>         ret
>>
>> Now returning 240 is the right answer.  But why is binary_const being
>> called at run time?  Can't this call be elided because we know it is a
>> constexpr function (without side effects) and that it is going to return
>> the value 240 that we've already computed at compile time?
>>
>
> This is PR12848. Clang's behavior here is conforming, but is obviously not
> ideal. The call certainly can be elided.

FWIW, LLVM's optimizers cannot themselves remove the call to  
__Z12binary_constImET_9str_constmS0_, because that function is  
recursive. Right now the inliner bails out when it sees a recursive  
function.
The test in the PR you mentioned gets the call removed, though, since  
there are no recursive functions.

Nuno



More information about the cfe-dev mailing list