I'm trying to understand the use of the "static" keyword as an array index in a function declaration in C.
After reading this article, I tried to declare such a function, and purposefully passing it an array that is too short:
#include <stdio.h>
#include <stdlib.h>
void print_string10(char string10[static 10]) {
// Should trigger a warning if the argument is NULL or an array of less than 10 elements
printf("%s\n",string10);
}
int main(void) {
char short_string[] = "test";
print_string10(short_string); // should trigger a warning as the string is 5 long
return EXIT_SUCCESS;
}
Compiling with clang
as in the article triggers the warning, but gcc -Wall -Werror
does not, it compiles and run fine.
I couldn't find an explanation, is that a normal behaviour for GCC to omit this warning?
Why it does not need to trigger a warning is because of the section of the standard where it occurs - 6.7.6.3p7:
Semantics
[...]
- A declaration of a parameter as ''array of type'' shall be adjusted to ''qualified pointer to type'', where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
It appears in the semantics section. A conforming implementation is only required to diagnose those that appear in the constraints. Even when it does not diagnose the violation here, it can use the knowledge of the static
keyword to infer that the argument is not null, and that loop unrolling and other optimizations could expect an array that would have at least that many elements.
Do also note, that the example 5 there says that
void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);
void f(double a[restrict static 3][5]);
are all compatible, i.e. you can mix and match them in function pointer assignments without casts even though one has the static
dimension!
It seems that clang (perhaps rightly so) loses its ability to diagnose anything if the call is realized through a function pointer:
void (*f)(double a[restrict static 3]);
int main(void) {
double a[1] = {0};
f(a);
}
(no diagnostics in Clang 7.0 - remove the *
and you will get them).
It looks like this is a bug in GCC. It seems there were some disagreements regarding whether or not this should be reported at compile time. Nonetheless, it was accepted as a bug but there doesn't seem to be a priority on fixing it.
This is detailed in bug report 50584. Comment 9 in particular states:
(In reply to Malcolm Inglis from comment #4)
Could someone change the status of this bug?
Notwithstanding whether the feature is pretty or ugly, GCC does accept this code and warnings for undefined behavior, when possible, are desired. Thus, confirmed.
This does not mean anyone is going to work on fixing this. Please, if you are using this feature and would like to see this warning in GCC, please consider contributing it: https://gcc.gnu.org/wiki/GettingStarted#Basics:_Contributing_to_GCC_in_10_easy_steps
If you start working on this, it would be good to say so here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With