diff options
-rw-r--r-- | Driver/clang.cpp | 44 | ||||
-rw-r--r-- | Lex/HeaderSearch.cpp | 48 | ||||
-rw-r--r-- | include/clang/Lex/DirectoryLookup.h | 69 |
3 files changed, 104 insertions, 57 deletions
diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 28659dd84a..08299b16ae 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -651,22 +651,24 @@ static void AddPath(const std::string &Path, IncludeDirGroup Group, return; } - // Check to see if this is an apple-style headermap. - if (const FileEntry *FE = FM.getFile(&MappedPath[0], - &MappedPath[0]+MappedPath.size())) { - std::string ErrorInfo; - const HeaderMap *HM = HS.CreateHeaderMap(FE, ErrorInfo); - if (HM) { - IncludeGroup[Group].push_back(DirectoryLookup(HM, Type, isUserSupplied, - isFramework)); - return; - } - - // If this looked like a headermap but was corrupted, emit that error, - // otherwise treat it as a missing directory. - if (!ErrorInfo.empty()) { - fprintf(stderr, "%s\n", ErrorInfo.c_str()); - return; + // Check to see if this is an apple-style headermap (which are not allowed to + // be frameworks). + if (!isFramework) { + if (const FileEntry *FE = FM.getFile(&MappedPath[0], + &MappedPath[0]+MappedPath.size())) { + std::string ErrorInfo; + const HeaderMap *HM = HS.CreateHeaderMap(FE, ErrorInfo); + if (HM) { + IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); + return; + } + + // If this looked like a headermap but was corrupted, emit that error, + // otherwise treat it as a missing directory. + if (!ErrorInfo.empty()) { + fprintf(stderr, "%s\n", ErrorInfo.c_str()); + return; + } } } @@ -678,6 +680,7 @@ static void AddPath(const std::string &Path, IncludeDirGroup Group, /// search list, remove the later (dead) ones. static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList) { llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs; + llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs; llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps; for (unsigned i = 0; i != SearchList.size(); ++i) { if (SearchList[i].isNormalDir()) { @@ -688,6 +691,15 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList) { if (Verbose) fprintf(stderr, "ignoring duplicate directory \"%s\"\n", SearchList[i].getDir()->getName()); + } 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())) + continue; + + if (Verbose) + fprintf(stderr, "ignoring duplicate framework \"%s\"\n", + SearchList[i].getFrameworkDir()->getName()); + } else { assert(SearchList[i].isHeaderMap() && "Not a headermap or normal dir?"); // If this isn't the first time we've seen this headermap, remove it. diff --git a/Lex/HeaderSearch.cpp b/Lex/HeaderSearch.cpp index c91c4f9ba4..769b1682de 100644 --- a/Lex/HeaderSearch.cpp +++ b/Lex/HeaderSearch.cpp @@ -61,9 +61,11 @@ void HeaderSearch::PrintStats() { const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE, std::string &ErrorInfo) { // We expect the number of headermaps to be small, and almost always empty. - // If it ever grows, use of a linear search should be reevaluated. + // If it ever grows, use of a linear search should be re-evaluated. if (!HeaderMaps.empty()) { for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i) + // Pointer equality comparison of FileEntries works because they are + // already uniqued by inode. if (HeaderMaps[i].first == FE) return HeaderMaps[i].second; } @@ -76,6 +78,26 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE, return 0; } +//===----------------------------------------------------------------------===// +// File lookup within a DirectoryLookup scope +//===----------------------------------------------------------------------===// + +/// LookupFile - Lookup the specified file in this search path, returning it +/// if it exists or returning null if not. +const FileEntry *DirectoryLookup::LookupFile(const char *FilenameStart, + const char *FilenameEnd, + FileManager &FileMgr) const { + llvm::SmallString<1024> TmpDir; + + // Concatenate the requested file onto the directory. + // FIXME: Portability. Filename concatenation should be in sys::Path. + TmpDir += getDir()->getName(); + TmpDir.push_back('/'); + TmpDir.append(FilenameStart, FilenameEnd); + return FileMgr.getFile(TmpDir.begin(), TmpDir.end()); +} + + //===----------------------------------------------------------------------===// // Header File Location. @@ -137,6 +159,7 @@ const FileEntry *HeaderSearch::DoFrameworkLookup(const DirectoryEntry *Dir, return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end()); } + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if @@ -161,11 +184,13 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, return FileMgr.getFile(FilenameStart, FilenameEnd); } - llvm::SmallString<1024> TmpDir; - // Step #0, unless disabled, check to see if the file is in the #includer's - // directory. This search is not done for <> headers. + // directory. This has to be based on CurFileEnt, not CurDir, because + // CurFileEnt could be a #include of a subdirectory (#include "foo/bar.h") and + // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h". + // This search is not done for <> headers. if (CurFileEnt && !isAngled && !NoCurDirSearch) { + llvm::SmallString<1024> TmpDir; // Concatenate the requested file onto the directory. // FIXME: Portability. Filename concatenation should be in sys::Path. TmpDir += CurFileEnt->getDir()->getName(); @@ -173,12 +198,10 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, TmpDir.append(FilenameStart, FilenameEnd); if (const FileEntry *FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end())) { // Leave CurDir unset. - // This file is a system header or C++ unfriendly if the old file is. getFileInfo(FE).DirInfo = getFileInfo(CurFileEnt).DirInfo; return FE; } - TmpDir.clear(); } CurDir = 0; @@ -210,20 +233,15 @@ const FileEntry *HeaderSearch::LookupFile(const char *FilenameStart, // start point value. CacheLookup.first = i+1; } - + // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { const FileEntry *FE = 0; if (!SearchDirs[i].isFramework()) { - // FIXME: Portability. Adding file to dir should be in sys::Path. - // Concatenate the requested file onto the directory. - TmpDir.clear(); - TmpDir += SearchDirs[i].getDir()->getName(); - TmpDir.push_back('/'); - TmpDir.append(FilenameStart, FilenameEnd); - FE = FileMgr.getFile(TmpDir.begin(), TmpDir.end()); + FE = SearchDirs[i].LookupFile(FilenameStart, FilenameEnd, FileMgr); } else { - FE = DoFrameworkLookup(SearchDirs[i].getDir(), FilenameStart,FilenameEnd); + FE = DoFrameworkLookup(SearchDirs[i].getFrameworkDir(), + FilenameStart, FilenameEnd); } if (FE) { diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index b57ebf013e..3ae1d72996 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -15,14 +15,15 @@ #define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H namespace clang { -class DirectoryEntry; class HeaderMap; +class DirectoryEntry; +class FileEntry; +class FileManager; /// DirectoryLookup - This class represents one entry in the search list that /// specifies the search order for directories in #include directives. It -/// represents either a directory or a 'headermap'. A headermap is just like a -/// directory, but it remaps its contents through an indirection table instead -/// of indexing a directory. +/// represents either a directory, a framework, or a headermap. +/// class DirectoryLookup { public: enum DirType { @@ -30,14 +31,20 @@ public: SystemHeaderDir, ExternCSystemHeaderDir }; + + enum LookupType_t { + LT_NormalDir, + LT_Framework, + LT_HeaderMap + }; private: union { // This union is discriminated by isHeaderMap. - /// Dir - This is the actual directory that we're referring to. - /// + /// Dir - This is the actual directory that we're referring to for a normal + /// directory or a framework. const DirectoryEntry *Dir; - /// Map - This is the HeaderMap corresponding if the isHeaderMap field is - /// true. + /// Map - This is the HeaderMap if this is a headermap lookup. + /// const HeaderMap *Map; } u; @@ -49,44 +56,57 @@ private: /// bool UserSupplied : 1; - /// Framework - True if this is a framework directory search-path. - /// - bool Framework : 1; - - /// IsHeaderMap - True if the HeaderMap field is valid, false if the Dir field - /// is valid. - bool IsHeaderMap : 1; + /// LookupType - This indicates whether this DirectoryLookup object is a + /// normal directory, a framework, or a headermap. + unsigned LookupType : 2; public: /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'dir'. DirectoryLookup(const DirectoryEntry *dir, DirType DT, bool isUser, bool isFramework) : DirCharacteristic(DT), UserSupplied(isUser), - Framework(isFramework), IsHeaderMap(false) { + LookupType(isFramework ? LT_Framework : LT_NormalDir) { u.Dir = dir; } /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of /// 'map'. - DirectoryLookup(const HeaderMap *map, DirType DT, bool isUser, bool isFWork) - : DirCharacteristic(DT), UserSupplied(isUser), Framework(isFWork), - IsHeaderMap(true) { + DirectoryLookup(const HeaderMap *map, DirType DT, bool isUser) + : DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) { u.Map = map; } + /// LookupFile - Lookup the specified file in this search path, returning it + /// if it exists or returning null if not. + const FileEntry *LookupFile(const char *FilenameStart, + const char *FilenameEnd, + FileManager &FileMgr) const; + /// getDir - Return the directory that this entry refers to. /// - const DirectoryEntry *getDir() const { return !IsHeaderMap ? u.Dir : 0; } + const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; } + + /// getFrameworkDir - Return the directory that this framework refers to. + /// + const DirectoryEntry *getFrameworkDir() const { + return isFramework() ? u.Dir : 0; + } /// getHeaderMap - Return the directory that this entry refers to. /// - const HeaderMap *getHeaderMap() const { return IsHeaderMap ? u.Map : 0; } + const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; } + LookupType_t getLookupType() const { return (LookupType_t)LookupType; } + /// isNormalDir - Return true if this is a normal directory, not a header map. - bool isNormalDir() const { return !IsHeaderMap; } + bool isNormalDir() const { return getLookupType() == LT_NormalDir; } + + /// isFramework - True if this is a framework directory. + /// + bool isFramework() const { return getLookupType() == LT_Framework; } /// isHeaderMap - Return true if this is a header map, not a normal directory. - bool isHeaderMap() const { return IsHeaderMap; } + bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } /// DirCharacteristic - The type of directory this is, one of the DirType enum /// values. @@ -96,9 +116,6 @@ public: /// bool isUserSupplied() const { return UserSupplied; } - /// isFramework - True if this is a framework directory. - /// - bool isFramework() const { return Framework; } }; } // end namespace clang |