clang 3.3 and constexpr constraints <p>I'm compiling some code with clang 3.3 that seems to compile fine with gcc 4.8:</p> <p>The original code was:</p> <pre><code>template &lt;std::size_t N&gt; struct helper { typedef void type; }; template &lt;&gt; struct helper&lt;64&gt; { typedef int64_t type; }; template &lt;&gt; struct helper&lt;32&gt; { typedef int32_t type; }; template &lt;&gt; struct helper&lt;16&gt; { typedef int16_t type; }; template &lt;&gt; struct helper&lt;8&gt; { typedef int8_t type; }; template &lt;std::size_t I, std::size_t F&gt; struct test { typedef typename helper&lt;I+F&gt;::type value_type; static constexpr std::size_t frac_mask = ~((~value_type(0)) &lt;&lt; F); }; </code></pre> <p>In clang, if I attempt to declare test&lt;16,16> or test&lt;8,0> I get the error:</p> <blockquote> <p>test.cpp:41:34: error: constexpr variable 'frac_mask' must be initialized by a constant expression</p> <pre><code>static constexpr std::size_t frac_mask = ~((~value_type(0)) &lt;&lt; F); </code></pre> </blockquote> <p>Playing around with it, if I convert the code to:</p> <pre><code>template &lt;std::size_t I, std::size_t F&gt; struct test { typedef typename helper&lt;I+F&gt;::type value_type; typedef typename std::make_unsigned&lt;value_type&gt;::type mask_type; static constexpr mask_type frac_mask = ~((~mask_type(0)) &lt;&lt; F); }; </code></pre> <p>It compiles in most cases (values of I, F), but if I declare test&lt;8, 0>, I get the error:</p> <blockquote> <p>test.cpp:23:36: error: constexpr variable 'frac_mask' must be initialized by a constant expression</p> <p>test.cpp:66:15: note: in instantiation of template class 'test&lt;8, 0>' requested here</p> <p>test.cpp:23:66: note: left shift of negative value -1</p> <pre><code> static constexpr mask_type frac_mask = ~((~mask_type(0)) &lt;&lt; F); </code></pre> </blockquote> <p>My question is - is there some rules I'm violating here in terms of the specification of constexpr? Also, for the last error - mask type is unsigned - is this a compiler issue that it thinks I'm shifting a negative value or am I misreading the code?</p>