This is an archive of the discontinued LLVM Phabricator instance.

Support case insensitive header searches for MSVCCompat
Needs ReviewPublic

Authored by abdulras on Mar 5 2014, 12:47 PM.

Details

Reviewers
majnemer
Summary

When the compiler is placed into MSVC compatibility, add a fallback mechanism
for supporting case insensitive header search. This is important when dealing
with case sensitive filesystems and building for Windows. In particular, the
Windows SDK in many places mixes up cases for filenames as well as directories.

In general, this codepath does not affect the compilation as it is a simple
boolean check. If MSVC compatibility is enabled, perform an additional stat.
If the path is inaccessible, do a case insensitive match over the contents of
the directory.

If the underlying filesystem is case-insensitive, then the stat will succeed and
the search will not be required.

Diff Detail

Event Timeline

thakis added a comment.Mar 5 2014, 1:04 PM

Does cl.exe to this if you're on a case-sensitive file system? Why are you
using a case-sensitive file system if you want case-insensitive behavior?

One of the nice things about clang is that it is inherently a cross-compiler :-). Not all file systems are case-insensitive, and unfortunately, as I mentioned in the commit message, the Windows SDK does get the case wrong in many cases. This is an attempt to make the cross-compiler work properly with MS compatibility irrespective of the environment where it is being executed.

thakis added a comment.Mar 5 2014, 1:19 PM

The compiler won't be the only place with issues like this though, no? Say
you have a generated header "header.h" and some file accidentally includes
it as "Header.h", then the build system now won't have a correct dependency
edge. There's probably more examples.

Can't you just create a case-insensitive file system even in cross mode?

majnemer added a subscriber: rsmith.Mar 6 2014, 2:30 PM

Modulo needing some style fixes, this looks fine. However, I'd prefer
for @rsmith look at this at least to make sure it plays nice with modules.

Have you considered using something ilke ciopfs? =)

This patch needs testcases.

I also suspect that some of this belongs in LLVM's Support library, rather than here, but that can wait until we've figured out exactly what we want.

include/clang/Lex/DirectoryLookup.h
66

Typo of "Microsoft"

lib/Frontend/InitHeaderSearch.cpp
679

We don't want to pay the cost of this if the underlying file system is already case-insensitive. On Windows, GetVolumeInformation can be used to determine this. I don't think there's a good way to determine it for Linux, sadly.

(We should also use this in FileManager rather than making an assumption that Windows is case-insensitive and nothing else is there.)

lib/Lex/HeaderSearch.cpp
36–42

Do you need to compare anything other than the last component here?

257–265

Please factor this out. Should you do something better with EC than ignoring it?

abdulras added inline comments.Mar 20 2014, 3:33 PM
include/clang/Lex/DirectoryLookup.h
66

Good eye.

lib/Frontend/InitHeaderSearch.cpp
679

Agreed. What volume would you say that we query that on? We could be compiling on a volume different from the compiler. The headers could come from various volumes as well.

lib/Lex/HeaderSearch.cpp
36–42

for a multi-component file path, a non-terminal component may mismatch. If a multi-component path has a matching terminal-component, that would also get incorrectly included otherwise.

257–265

I dont think I can do much with EC. I suppose I could print out a warning (but that seems like it would clutter the output). But, I will pull out the loop into a function.

rsmith added inline comments.Mar 20 2014, 3:49 PM
lib/Frontend/InitHeaderSearch.cpp
679

We should presumably make the decision on a per-directory basis. I'd expect it can change across junction points, not just across volumes.

lib/Lex/HeaderSearch.cpp
36–42

But directory_iterator only walks a single level at a time, right? If you meant to perform a recursive walk looking for missing directory components, not just the last level, then I think that

  1. you're missing the code to do that (or maybe I've just overlooked how you're achieving that), and
  2. you still only want to compare the last component at each stage in your tree walk (rather than wasting time walking through the files in directories that don't match).
257–265

I'd be inclined to think that a FatalError is the right way to respond to a directory operation that fails, unless we have a reason to continue past one? Hmm, maybe we want to ignore permissions problems?

Does the case-sensitivity behaviour really only apply to headers found in header search? If not, then how about putting this in the virtual file system layer, or at least FileManager?

Right now this doesn't cover the 'header' declarations in module map files (see ModuleMap.cpp, parseHeaderDecl).