https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67333
Bug ID: 67333 Summary: [C++11][constexpr] constexpr functions incorrectly prohibit taking references to volatile types Product: gcc Version: 5.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: myriachan at gmail dot com Target Milestone: --- GCC 4.7.3 (at least) through GCC 6.0 reject the following due to "meow has side-effects": #include <cstddef> #include <type_traits> template <typename T, std::size_t S> constexpr std::size_t lengthof(const volatile T (&)[S]) { return S; } int main() { volatile int meow[4]; static_cast<void>(meow); // shut up warning return static_cast<int>(std::integral_constant<std::size_t, lengthof(meow)>::value); } I believe that this is legal per [expr.const] in the Standard, because the volatile parameter is never used in an lvalue-to-rvalue conversion, which is what [expr.const] disallows in constant-expressions for volatile types. Clang versions that understand this code accept it; Visual C++ 2015 does as well. Someone who replied to my question on the "std-discussion" mailing list suggested that this is also technically legal as well: #include <type_traits> constexpr int Test(int x) { volatile int v = x; return x; } int main() { return std::integral_constant<int, Test(2)>::value; } GCC also rejects this, but Clang accepts this as well. Any attempt to read v will fail, though, so Clang is enforcing the rule. I'm not on my Windows machine as I write this, so I can't check MSVC.