Hi majnemer,

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.


http://llvm-reviews.chandlerc.com/D2972

Files:
  include/clang/Lex/DirectoryLookup.h
  include/clang/Lex/HeaderSearch.h
  lib/Frontend/InitHeaderSearch.cpp
  lib/Lex/HeaderSearch.cpp
  lib/Lex/PPDirectives.cpp
  unittests/Lex/PPCallbacksTest.cpp
Index: include/clang/Lex/DirectoryLookup.h
===================================================================
--- include/clang/Lex/DirectoryLookup.h
+++ include/clang/Lex/DirectoryLookup.h
@@ -61,24 +61,31 @@
   /// \brief Whether we've performed an exhaustive search for module maps
   /// within the subdirectories of this directory.
   unsigned SearchedAllModuleMaps : 1;
+
+  /// \brief Whether the lookup should be case insensitive.  This is required
+  /// for compatibility with case-sensitive file systems and Mcirosoft mode
+  /// which does not include headers with the correct case.
+  unsigned CaseInsensitive : 1;
   
 public:
   /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
   /// 'dir'.
   DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT,
-                  bool isFramework)
+                  bool isFramework, bool isCaseInsensitive)
     : DirCharacteristic(DT),
       LookupType(isFramework ? LT_Framework : LT_NormalDir),
-      IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {
+      IsIndexHeaderMap(false), SearchedAllModuleMaps(false),
+      CaseInsensitive(isCaseInsensitive) {
     u.Dir = dir;
   }
 
   /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
   /// 'map'.
   DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT,
-                  bool isIndexHeaderMap)
+                  bool isIndexHeaderMap, bool isCaseInsensitive)
     : DirCharacteristic(DT), LookupType(LT_HeaderMap),
-      IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {
+      IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false),
+      CaseInsensitive(isCaseInsensitive) {
     u.Map = map;
   }
 
Index: include/clang/Lex/HeaderSearch.h
===================================================================
--- include/clang/Lex/HeaderSearch.h
+++ include/clang/Lex/HeaderSearch.h
@@ -235,6 +235,9 @@
 
   bool EnabledModules;
 
+  /// \brief Whether we are performing case insensitive header searches
+  bool CaseInsensitive;
+
   // HeaderSearch doesn't support default or copy construction.
   HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION;
   void operator=(const HeaderSearch&) LLVM_DELETED_FUNCTION;
Index: lib/Frontend/InitHeaderSearch.cpp
===================================================================
--- lib/Frontend/InitHeaderSearch.cpp
+++ lib/Frontend/InitHeaderSearch.cpp
@@ -45,12 +45,15 @@
   bool Verbose;
   std::string IncludeSysroot;
   bool HasSysroot;
+  bool CaseInsensitive;
 
 public:
 
-  InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
+  InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot,
+                   bool caseInsensitive)
     : Headers(HS), Verbose(verbose), IncludeSysroot(sysroot),
-      HasSysroot(!(sysroot.empty() || sysroot == "/")) {
+      HasSysroot(!(sysroot.empty() || sysroot == "/")),
+      CaseInsensitive(caseInsensitive) {
   }
 
   /// AddPath - Add the specified path to the specified group list, prefixing
@@ -153,8 +156,9 @@
 
   // If the directory exists, add it.
   if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) {
-    IncludePath.push_back(
-      std::make_pair(Group, DirectoryLookup(DE, Type, isFramework)));
+    IncludePath.push_back(std::make_pair(Group,
+                                         DirectoryLookup(DE, Type, isFramework,
+                                                         CaseInsensitive)));
     return;
   }
 
@@ -164,9 +168,10 @@
     if (const FileEntry *FE = FM.getFile(MappedPathStr)) {
       if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
         // It is a headermap, add it to the search path.
-        IncludePath.push_back(
-          std::make_pair(Group,
-                         DirectoryLookup(HM, Type, Group == IndexHeaderMap)));
+        IncludePath.push_back(std::make_pair(Group,
+                                             DirectoryLookup(HM, Type,
+                                                        Group == IndexHeaderMap,
+                                                             CaseInsensitive)));
         return;
       }
     }
@@ -671,7 +676,7 @@
                                      const HeaderSearchOptions &HSOpts,
                                      const LangOptions &Lang,
                                      const llvm::Triple &Triple) {
-  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+  InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot, Lang.MSVCCompat);
 
   // Add the user defined entries.
   for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp
+++ lib/Lex/HeaderSearch.cpp
@@ -29,6 +29,21 @@
 #endif
 using namespace clang;
 
+static bool IsEquivalent(StringRef Path, StringRef LowerFilename) {
+  llvm::sys::path::reverse_iterator PI, PE, FI, FE;
+  const std::string LowerPath = Path.lower();
+
+  for (PI = llvm::sys::path::rbegin(LowerPath),
+       PE = llvm::sys::path::rend(LowerPath),
+       FI = llvm::sys::path::rbegin(LowerFilename),
+       FE = llvm::sys::path::rend(LowerFilename);
+       FI != FE && PI != PE; ++PI, ++FI)
+    if (FI->str() != PI->str())
+      return false;
+
+  return FI == FE;
+}
+
 const IdentifierInfo *
 HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
   if (ControllingMacro)
@@ -47,8 +62,9 @@
                            SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                            const LangOptions &LangOpts,
                            const TargetInfo *Target)
-    : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
-      FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this) {
+  : HSOpts(HSOpts), Diags(Diags), FileMgr(SourceMgr.getFileManager()),
+    FrameworkMap(64), ModMap(SourceMgr, Diags, LangOpts, Target, *this),
+    CaseInsensitive(LangOpts.MSVCCompat) {
   AngledDirIdx = 0;
   SystemDirIdx = 0;
   NoCurDirSearch = false;
@@ -237,6 +253,17 @@
     // Concatenate the requested file onto the directory.
     TmpDir = getDir()->getName();
     llvm::sys::path::append(TmpDir, Filename);
+    if (CaseInsensitive && !llvm::sys::fs::exists(TmpDir.str())) {
+      llvm::error_code EC;
+      std::string LowerFilename = Filename.lower();
+      for (llvm::sys::fs::directory_iterator DI(getDir()->getName(), EC), DE;
+           !EC && DI != DE; DI = DI.increment(EC)) {
+        if (IsEquivalent(DI->path(), LowerFilename)) {
+          TmpDir = DI->path();
+          break;
+        }
+      }
+    }
     if (SearchPath != NULL) {
       StringRef SearchPathRef(getDir()->getName());
       SearchPath->clear();
@@ -567,6 +594,15 @@
       RelativePath->clear();
       RelativePath->append(Filename.begin(), Filename.end());
     }
+    if (CaseInsensitive && !llvm::sys::fs::exists(Filename)) {
+      llvm::error_code EC;
+      std::string LowerFilename = Filename.lower();
+      for (llvm::sys::fs::directory_iterator
+                             DI(llvm::sys::path::parent_path(Filename), EC), DE;
+           !EC && DI != DE; DI = DI.increment(EC))
+        if (IsEquivalent(DI->path(), LowerFilename))
+          return FileMgr.getFile(DI->path(), /*openFile=*/true);
+    }
     // Otherwise, just return the file.
     return FileMgr.getFile(Filename, /*openFile=*/true);
   }
@@ -590,6 +626,18 @@
       TmpDir = Includer->getDir()->getName();
       TmpDir.push_back('/');
       TmpDir.append(Filename.begin(), Filename.end());
+      if (CaseInsensitive && !llvm::sys::fs::exists(TmpDir.str())) {
+        llvm::error_code EC;
+        std::string LowerFilename = Filename.lower();
+        for (llvm::sys::fs::directory_iterator
+                                      DI(Includer->getDir()->getName(), EC), DE;
+             !EC && DI != DE; DI = DI.increment(EC)) {
+          if (IsEquivalent(DI->path(), LowerFilename)) {
+            TmpDir = DI->path();
+            break;
+          }
+        }
+      }
       if (const FileEntry *FE =
               FileMgr.getFile(TmpDir.str(), /*openFile=*/true)) {
         // Leave CurDir unset.
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -1461,7 +1461,7 @@
       if (Callbacks->FileNotFound(Filename, RecoveryPath)) {
         if (const DirectoryEntry *DE = FileMgr.getDirectory(RecoveryPath)) {
           // Add the recovery path to the list of search paths.
-          DirectoryLookup DL(DE, SrcMgr::C_User, false);
+          DirectoryLookup DL(DE, SrcMgr::C_User, false, false);
           HeaderInfo.AddSearchPath(DL, isAngled);
           
           // Try the lookup again, skipping the cache.
Index: unittests/Lex/PPCallbacksTest.cpp
===================================================================
--- unittests/Lex/PPCallbacksTest.cpp
+++ unittests/Lex/PPCallbacksTest.cpp
@@ -140,7 +140,7 @@
       // Add header's parent path to search path.
       StringRef SearchPath = path::parent_path(HeaderPath);
       const DirectoryEntry *DE = FileMgr.getDirectory(SearchPath);
-      DirectoryLookup DL(DE, SrcMgr::C_User, false);
+      DirectoryLookup DL(DE, SrcMgr::C_User, false, false);
       HeaderInfo.AddSearchPath(DL, IsSystemHeader);
   }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to