From 7a739401983eb9bc25c9b4b25177e116f5e5ba92 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 26 Sep 2008 17:46:45 +0000 Subject: [PATCH] emulate a bit of GCC path lookup weirdness: if a system directory is shadowed by a user directory in the lookup path, ignore the user directory not the system one. Not doing this can affect file lookup and the "is a system header" bit on locations. For example: clang -v -I/usr/include inc.c -E | & grep /usr/inc now prints: # 1 "/usr/include/i386/_types.h" 1 3 4 # 37 "/usr/include/i386/_types.h" 3 4 # 70 "/usr/include/i386/_types.h" 3 4 instead of: # 1 "/usr/include/i386/_types.h" 1 # 37 "/usr/include/i386/_types.h" # 70 "/usr/include/i386/_types.h" This is part of rdar://6243860. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56669 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/InitHeaderSearch.cpp | 43 ++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/Driver/InitHeaderSearch.cpp b/lib/Driver/InitHeaderSearch.cpp index be8a860421..5c23808b3b 100644 --- a/lib/Driver/InitHeaderSearch.cpp +++ b/lib/Driver/InitHeaderSearch.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/InitHeaderSearch.h" - #include "clang/Lex/HeaderSearch.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" @@ -20,7 +19,6 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/System/Path.h" #include "llvm/Config/config.h" - #include using namespace clang; @@ -92,7 +90,7 @@ void InitHeaderSearch::AddEnvVarPaths(const char *Name) { AddPath(".", Angled, false, true, false); else AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false, - true, false); + true, false); at = delim + 1; delim = strchr(at, llvm::sys::PathSeparator); } @@ -255,14 +253,46 @@ static void RemoveDuplicates(std::vector &SearchList, llvm::SmallPtrSet SeenFrameworkDirs; llvm::SmallPtrSet SeenHeaderMaps; for (unsigned i = 0; i != SearchList.size(); ++i) { + unsigned DirToRemove = i; + if (SearchList[i].isNormalDir()) { // If this isn't the first time we've seen this dir, remove it. if (SeenDirs.insert(SearchList[i].getDir())) continue; - if (Verbose) + // If we have a normal #include dir that is shadowed later in the chain + // by a system include dir, we actually want to ignore the user's request + // and drop the user dir... keeping the system dir. This is weird, but + // required to emulate GCC's search path correctly. + // + // Since dupes of system dirs are rare, just rescan to find the original + // that we're nuking instead of using a DenseMap. + if (SearchList[i].getDirCharacteristic() == + DirectoryLookup::SystemHeaderDir || + SearchList[i].getDirCharacteristic() == + DirectoryLookup::ExternCSystemHeaderDir) { + // Find the dir that this is the same of. + unsigned FirstDir; + for (FirstDir = 0; ; ++FirstDir) { + assert(FirstDir != i && "Didn't find dupe?"); + if (SearchList[FirstDir].getDir() == SearchList[i].getDir()) + break; + } + + // If the first dir in the search path is a non-system dir, zap it + // instead of the system one. + if (SearchList[FirstDir].getDirCharacteristic() == + DirectoryLookup::NormalHeaderDir) + DirToRemove = FirstDir; + } + + if (Verbose) { fprintf(stderr, "ignoring duplicate directory \"%s\"\n", SearchList[i].getDir()->getName()); + if (DirToRemove != i) + fprintf(stderr, " as it is a non-system directory that duplicates" + " a system directory\n"); + } } else if (SearchList[i].isFramework()) { // If this isn't the first time we've seen this framework dir, remove it. if (SeenFrameworkDirs.insert(SearchList[i].getFrameworkDir())) @@ -283,8 +313,9 @@ static void RemoveDuplicates(std::vector &SearchList, SearchList[i].getDir()->getName()); } - // This is reached if the current entry is a duplicate. - SearchList.erase(SearchList.begin()+i); + // This is reached if the current entry is a duplicate. Remove the + // DirToRemove (usually the current dir). + SearchList.erase(SearchList.begin()+DirToRemove); --i; } } -- 2.40.0