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:
Chris Lattner 2007-12-17 07:52:39 +00:00
parent dd00e625d2
commit f62f75895f
3 changed files with 104 additions and 57 deletions

View File

@ -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.

View File

@ -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) {

View File

@ -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