This is a regression that only affects -std=c++1z, introduced in r273754. The following test case (thanks rsmith!) fails to compile:
template<int N> struct X {}; template<typename T> struct Y { static constexpr int s_v[] = {0}; X<*s_v> x; // Clang incorrectly says: error, *s_v is not a constant expression }; template struct Y<int>;
The problem is that the initializer for s_v (an implicitly inline variable in c++1z) is not instantiated. This patch requires that the initializer for an IncompleteArrayType is instantiated, which is the same rule as an initializer for an auto type.
Fixes PR28385.
Thanks!
I don't see why we would need the initializer right away in the IncompleteArrayType case. It seems instead that we should delay instantiation of the initializer until a complete type is required for the variable (Sema::RequireCompleteExprType handles this case) or it is used in a context that requires a definition (Sema::MarkVariableReferenced handles this case).
You can reproduce a related bug in C++11 mode like so:
or:
It looks like the bug in this case is that VarDecl::isUsableInConstantExpressions (called from DoMarkVarDeclReferenced) is mishandling this case: once it's determined that the variable is of non-volatile const-qualified type, it needs to map back to the template instantiation pattern and check whether the most recent declaration of that is declared constexpr, since there might be a not-yet-instantiated redeclaration that adds the constexpr.
I'm not sure that's the same bug you're hitting here, though, since in this case we should be instantiating the constexpr specifier with the initial declaration, which should be enough to cause isUsableInConstantExpressions to return true. So the mystery is, why is DoMarkVarDeclReferenced not triggering instantiation?