Summary
-------
Add a new compiler lint flag `output-file-clash` that will enable detection of output file clashes. An output file clash is when the compiler writes two different output files, but due to the behavior of the filesystem these files end up being written to the same underlying filesystem file.
Problem
-------
Sometimes the compiler thinks it's writing out two separate files, but due to the way the underlying filesystem maps `Path`'s to actual files, it's really writing the same file twice.
This is usually due to case-insensitive filesystems, but can also be due to how a filesystem "normalizes" file names. For example, on MacOS, compiling this class will generate such a clash:
```
public class Test {
interface Cafe\u0301 {
}
interface Caf\u00e9 {
}
}
```
The reason is that `\u0301` is the Unicode character "Combining Acute Accent" which means "stick an accent over the previous character". So MacOS normalizes the letter `e` followed by a `\u0301` into a Unicode `\u00e9`, that is, `é`. However, the Java language treats these the two names `Cafe\u0301` and `Caf\u00e9` as distinct.
Of course, on any case-insensitive filesystem a class like this would cause an output file clash for the file `Test$Inner.class'`:
```
public class Test {
class Inner {
}
class INNER {
}
}
```
Solution
--------
There's no way to avoid this problem without changing the way the compiler maps output files to filesystem filenames, which would be too disruptive.
So the solution here is to simply provide a way for people experiencing this problem to convert what is currently a runtime error into a compile-time warning (or error with `-Werror`). This is by adding a new lint flag `output-file-clash` that enables output file clash detection. The term "output file" covers class files, source files, and native header files.
If the flag is not used, then the compiler should behave exactly as it currently does. Therefore, there should be no backward compatibility risk.
An alternative, a more aggressive approach would be to always enable this behavior and/or make it an error instead of a warning.
Specification
-------------
New addition to "javac --help-lint":
```
output-file-clash
Warn when an output file is overwritten during compilation. This can occur, for example,
on case-insensitive filesystems. Covers class files, native header files, and source files.
```
An example of the new warning:
```
$ javac -Xlint:output-file-clash Test.java
warning: [output-file-clash] output file written more than once: /Users/archie/test/Test$Café.class
1 warning
```