Description
I am wondering if there is an inconsistency in the way NT arrays and NT array pointers are handled. I think there is a off-by-one bug somewhere.
In particular, consider this code:
int main() {
char s0 _Nt_checked[4] = "hello"; // disallowed; initializer too long
char s1 _Nt_checked[5] = "hello"; // allowed, sizeof(s1) = 5
char s2 _Nt_checked[6] = "hello"; // allowed, sizeof(s2) = 6
_Nt_array_ptr<char> p1 : count(5) = s1; // disallowed; bounds too long
_Nt_array_ptr<char> p2 : count(5) = s2; // allowed
}
String s1
is deemed acceptable with an initializer of 6 bytes, when considering the NULL terminator. That tells me I should interpret the declared size 5
to be one less than the real size. This would make sense assuming that the _Nt_checked
annotation is indicating that one unmentioned byte is reserved for the NULL terminator.
But if that's true, then I don't understand why the assignment from s1
to p1
is rejected. We just established that s1
has bounds 5 not counting the null terminator, and that is the interpretation of p1
as well. This is why standard string library functions take _Nt_array_ptr<char>
arguments with no bounds annotation (interpreted as a bounds of count(0)
) -- the NULL terminator is not counted.
So it would seem to me that either the initialization of s1
is treated incorrectly (the size should include the null terminator) or the initialization of p1
is treated incorrectly. I'm not seeing a consistent way to understand them both to be correct.