It turns out that we need to have the diagnostic consumers set up
before we've actually opened the input files, which makes sense
because we might want to emit diagnostics about not being able to open
an input file. Switch to using file names instead, and mapping those
over to source ranges only once we actually need to handle a
diagnostic with a valid source location.
If a top-level diagnostic is in a particular source range, the
RangeSpecificDiagnosticConsumer will funnel it and any attached notes
to a particular "sub-consumer" designated for that range (intended to
be used with whole files). If it's not in a range designated for any
sub-consumer, the diagnostic is passed to all registered
sub-consumers.
This is intended to be used for batch mode, so that diagnostics that
are definitely associated with a particular file can be emitted in
that file's .dia output, while diagnostics that may be associated with
other files (such as those that come from Clang) will still get
presented to the user.