Both the C99 Standard (6.7.5.3) and the C11 Standard (6.7.6.3) state:
An identifier list declares only the identifiers of the parameters
of the function. An empty list in a function declarator that is part
of a definition of that function specifies that the function has no
parameters. The empty list in a function declarator that is not part
of a definition of that function specifies that no information about
the number or types of the parameters is supplied.
Since the declaration of foo is part of a definition, the declaration
specifies that foo takes 0 arguments, so the call foo(str) is at
least morally wrong. But as described below, there are different
degrees of "wrong" in C, and compilers may differ in how they deal
with certain kinds of "wrong".
To take a slightly simpler example, consider the following program:
int f() { return 9; }
int main() {
return f(1);
}
If I compile the above using Clang:
tmp$ cc tmp3.c
tmp3.c:4:13: warning: too many arguments in call to 'f'
return f(1);
~ ^
1 warning generated.
If I compile with gcc 4.8 I don't get any errors or warnings, even with -Wall. A previous answer suggested using -Wstrict-prototypes, which correctly reports that the definition of f is not in prototype form, but this is really not the point. The C Standard(s) allow a function definition in a non-prototype form such as the one above and the Standards clearly state that this definition specifies that the function takes 0 arguments.
Now there is a constraint (C11 Sec. 6.5.2.2):
If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters.
However, this constraint does not apply in this case, since the type of the function does not include a prototype. But here is a subsequent statement in the semantics section (not a "constraint"), that does apply:
If the expression that denotes the called function has a type that does not include a prototype
... If the number of arguments does not equal the number of parameters, the behavior is undefined.
Hence the function call does result in undefined behavior (i.e., the program is not "strictly conforming"). However, the Standard only requires an implementation to report a diagnostic message when an actual constraint is violated, and in this case, there is no violation of a constraint. Hence gcc is not required to report an error or warning in order to be a "conforming implementation".
So I think the answer to the question, why does gcc allow it?, is that gcc is not required to report anything, since this is not a constraint violation. Moreover gcc does not claim to report every kind of undefined behavior, even with -Wall or -Wpedantic. It is undefined behavior, which means the implementation can choose how to deal with it, and gcc has chosen to compile it without warnings (and apparently it just ignores the argument).