forked from OSchip/llvm-project
as it turns out, frameworks and headermaps are orthogonal. Make this so in
the internal representation. This also fixes a bug where -I foo -F foo would not search foo as both a normal and framework include dir. llvm-svn: 45092
This commit is contained in:
parent
dd00e625d2
commit
f62f75895f
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue