That's not the original issue. The problem is that the compiler silently predefines an undocumented macro. If the compiler silently predefined an undocumented variable, type, or function called "linux" or "unix", that too can be a problem. E.g., if there were a global function linux() on Linux systems only and you tried to define a global variable linux in your code, you'd get an error, too.
The clean solution is to do what clang does and generate informative error messages. In the case of macros, by showing the macro expansion history. For example, the following (using __STDC__ instead of linux for portability):
foo.c:2:7: error: expected identifier or '('
int __STDC__ = 1;
^
<built-in>:159:18: note: expanded from here
#define __STDC__ 1
Note that there can be other reasons to have macros that are syntactically different from functions and variables, but this isn't one of them.
But Patrick isn't responding to the original issue, he was responding to simias' assertion that macros should be syntactically disambiguated.
> If the compiler silently predefined an undocumented
> variable, type, or function called "linux" or "unix",
> that too can be a problem.
While we're on the topic of Rust, the compiler actually used to do this! In the early days, the identifiers "error", "warn", "info", and "debug" were all magical, undocumented constants for controlling logging levels. As you might expect, this caused problems. :P So don't think that Patrick isn't keenly aware of the perils of including non-keyword identifiers by default.
As for clang, their solution is the best they can do given that they don't have the authority to make the call over whether to syntactically disambiguate macros. It's definitely a debate to be had in the case of a language designed from scratch, and the Rust devs decided to err on the side of explicitness (you can contrast e.g. Elixir, which has the same sort of structural macros but chose not to distinguish their invocation syntax).
The clean solution is to do what clang does and generate informative error messages. In the case of macros, by showing the macro expansion history. For example, the following (using __STDC__ instead of linux for portability):
Note that there can be other reasons to have macros that are syntactically different from functions and variables, but this isn't one of them.