forked from OSchip/llvm-project
If the headermap maps the filename to a framework include ("Foo.h" -> "Foo/Foo.h"),
continue header lookup using the framework include as filename. This allows us to conveniently treat #import "Foo.h" as an implicit module import if we can resolve "Foo/Foo.h" as such. rdar://16042979 llvm-svn: 201419
This commit is contained in:
parent
96430645eb
commit
75fa9eddae
|
@ -161,11 +161,16 @@ public:
|
|||
/// \param [out] InUserSpecifiedSystemFramework If the file is found,
|
||||
/// set to true if the file is located in a framework that has been
|
||||
/// user-specified to be treated as a system framework.
|
||||
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
|
||||
///
|
||||
/// \param [out] MappedName if this is a headermap which maps the filename to
|
||||
/// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this
|
||||
/// vector and point Filename to it.
|
||||
const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
ModuleMap::KnownHeader *SuggestedModule,
|
||||
bool &InUserSpecifiedSystemFramework) const;
|
||||
bool &InUserSpecifiedSystemFramework,
|
||||
SmallVectorImpl<char> &MappedName) const;
|
||||
|
||||
private:
|
||||
const FileEntry *DoFrameworkLookup(
|
||||
|
|
|
@ -55,6 +55,11 @@ public:
|
|||
/// "../../file.h".
|
||||
const FileEntry *LookupFile(StringRef Filename, FileManager &FM) const;
|
||||
|
||||
/// If the specified relative filename is located in this HeaderMap return
|
||||
/// the filename it is mapped to, otherwise return an empty StringRef.
|
||||
StringRef lookupFilename(StringRef Filename,
|
||||
SmallVectorImpl<char> &DestPath) const;
|
||||
|
||||
/// getFileName - Return the filename of the headermap.
|
||||
const char *getFileName() const;
|
||||
|
||||
|
|
|
@ -201,18 +201,29 @@ void HeaderMap::dump() const {
|
|||
/// this HeaderMap. If so, open it and return its FileEntry.
|
||||
const FileEntry *HeaderMap::LookupFile(
|
||||
StringRef Filename, FileManager &FM) const {
|
||||
|
||||
SmallString<1024> Path;
|
||||
StringRef Dest = lookupFilename(Filename, Path);
|
||||
if (Dest.empty())
|
||||
return 0;
|
||||
|
||||
return FM.getFile(Dest);
|
||||
}
|
||||
|
||||
StringRef HeaderMap::lookupFilename(StringRef Filename,
|
||||
SmallVectorImpl<char> &DestPath) const {
|
||||
const HMapHeader &Hdr = getHeader();
|
||||
unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
|
||||
|
||||
// If the number of buckets is not a power of two, the headermap is corrupt.
|
||||
// Don't probe infinitely.
|
||||
if (NumBuckets & (NumBuckets-1))
|
||||
return 0;
|
||||
return StringRef();
|
||||
|
||||
// Linearly probe the hash table.
|
||||
for (unsigned Bucket = HashHMapKey(Filename);; ++Bucket) {
|
||||
HMapBucket B = getBucket(Bucket & (NumBuckets-1));
|
||||
if (B.Key == HMAP_EmptyBucketKey) return 0; // Hash miss.
|
||||
if (B.Key == HMAP_EmptyBucketKey) return StringRef(); // Hash miss.
|
||||
|
||||
// See if the key matches. If not, probe on.
|
||||
if (!Filename.equals_lower(getString(B.Key)))
|
||||
|
@ -220,9 +231,11 @@ const FileEntry *HeaderMap::LookupFile(
|
|||
|
||||
// If so, we have a match in the hash table. Construct the destination
|
||||
// path.
|
||||
SmallString<1024> DestPath;
|
||||
DestPath += getString(B.Prefix);
|
||||
DestPath += getString(B.Suffix);
|
||||
return FM.getFile(DestPath.str());
|
||||
StringRef Prefix = getString(B.Prefix);
|
||||
StringRef Suffix = getString(B.Suffix);
|
||||
DestPath.clear();
|
||||
DestPath.append(Prefix.begin(), Prefix.end());
|
||||
DestPath.append(Suffix.begin(), Suffix.end());
|
||||
return StringRef(DestPath.begin(), DestPath.size());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,12 +223,13 @@ const char *DirectoryLookup::getName() const {
|
|||
/// LookupFile - Lookup the specified file in this search path, returning it
|
||||
/// if it exists or returning null if not.
|
||||
const FileEntry *DirectoryLookup::LookupFile(
|
||||
StringRef Filename,
|
||||
StringRef &Filename,
|
||||
HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
ModuleMap::KnownHeader *SuggestedModule,
|
||||
bool &InUserSpecifiedSystemFramework) const {
|
||||
bool &InUserSpecifiedSystemFramework,
|
||||
SmallVectorImpl<char> &MappedName) const {
|
||||
InUserSpecifiedSystemFramework = false;
|
||||
|
||||
SmallString<1024> TmpDir;
|
||||
|
@ -271,8 +272,27 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||
SuggestedModule, InUserSpecifiedSystemFramework);
|
||||
|
||||
assert(isHeaderMap() && "Unknown directory lookup");
|
||||
const FileEntry * const Result = getHeaderMap()->LookupFile(
|
||||
Filename, HS.getFileMgr());
|
||||
const HeaderMap *HM = getHeaderMap();
|
||||
SmallString<1024> Path;
|
||||
StringRef Dest = HM->lookupFilename(Filename, Path);
|
||||
if (Dest.empty())
|
||||
return 0;
|
||||
|
||||
const FileEntry *Result;
|
||||
|
||||
// Check if the headermap maps the filename to a framework include
|
||||
// ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the
|
||||
// framework include.
|
||||
if (llvm::sys::path::is_relative(Dest)) {
|
||||
MappedName.clear();
|
||||
MappedName.append(Dest.begin(), Dest.end());
|
||||
Filename = StringRef(MappedName.begin(), MappedName.size());
|
||||
Result = HM->LookupFile(Filename, HS.getFileMgr());
|
||||
|
||||
} else {
|
||||
Result = HS.getFileMgr().getFile(Dest);
|
||||
}
|
||||
|
||||
if (Result) {
|
||||
if (SearchPath != NULL) {
|
||||
StringRef SearchPathRef(getName());
|
||||
|
@ -620,12 +640,15 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||
CacheLookup.first = i+1;
|
||||
}
|
||||
|
||||
SmallString<64> MappedName;
|
||||
|
||||
// Check each directory in sequence to see if it contains this file.
|
||||
for (; i != SearchDirs.size(); ++i) {
|
||||
bool InUserSpecifiedSystemFramework = false;
|
||||
const FileEntry *FE =
|
||||
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
|
||||
SuggestedModule, InUserSpecifiedSystemFramework);
|
||||
SuggestedModule, InUserSpecifiedSystemFramework,
|
||||
MappedName);
|
||||
if (!FE) continue;
|
||||
|
||||
CurDir = &SearchDirs[i];
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
Foo.h is parsed
|
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
|
||||
// This uses a headermap with this entry:
|
||||
// Foo.h -> Foo/Foo.h
|
||||
|
||||
// RUN: %clang_cc1 -E %s -o %t.i -I %S/foo.hmap -F %S
|
||||
// RUN: FileCheck %s -input-file %t.i
|
||||
|
||||
// CHECK: Foo.h is parsed
|
||||
|
||||
#include "Foo.h"
|
Loading…
Reference in New Issue