namespace llvm {
class StringRef;
+ template <typename T> class SmallVectorImpl;
}
namespace clang {
class HeaderMap;
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
- const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const;
+ /// If RawPath is not NULL and the file is found, RawPath will be set to the
+ /// raw path at which the file was found in the file system. For example,
+ /// for a search path ".." and a filename "../file.h" this would be
+ /// "../../file.h".
+ const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS,
+ llvm::SmallVectorImpl<char> *RawPath) const;
private:
- const FileEntry *DoFrameworkLookup(llvm::StringRef Filename,
- HeaderSearch &HS) const;
+ const FileEntry *DoFrameworkLookup(
+ llvm::StringRef Filename, HeaderSearch &HS,
+ llvm::SmallVectorImpl<char> *RawPath) const;
};
namespace llvm {
class MemoryBuffer;
class StringRef;
+ template <typename T> class SmallVectorImpl;
}
namespace clang {
class FileEntry;
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
- const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const;
+ /// If RawPath is not NULL and the file is found, RawPath will be set to the
+ /// raw path at which the file was found in the file system. For example,
+ /// for a search path ".." and a filename "../file.h" this would be
+ /// "../../file.h".
+ const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM,
+ llvm::SmallVectorImpl<char> *RawPath) const;
/// getFileName - Return the filename of the headermap.
const char *getFileName() const;
const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
- const FileEntry *CurFileEnt);
+ const FileEntry *CurFileEnt,
+ llvm::SmallVectorImpl<char> *RawPath);
/// LookupSubframeworkHeader - Look up a subframework for the specified
/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
/// is a subframework within Carbon.framework. If so, return the FileEntry
/// for the designated file, otherwise return null.
- const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename,
- const FileEntry *RelativeFileEnt);
+ const FileEntry *LookupSubframeworkHeader(
+ llvm::StringRef Filename,
+ const FileEntry *RelativeFileEnt,
+ llvm::SmallVectorImpl<char> *RawPath);
/// LookupFrameworkCache - Look up the specified framework name in our
/// framework cache, returning the DirectoryEntry it is in if we know,
///
/// \param EndLoc The location of the last token within the inclusion
/// directive.
+ ///
+ /// \param RawPath Contains the raw path at which the file was found in the
+ /// file system. For example, for a search path ".." and a filename
+ /// "../file.h" this would be "../../file.h".
virtual void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
llvm::StringRef FileName,
bool IsAngled,
const FileEntry *File,
- SourceLocation EndLoc) {
+ SourceLocation EndLoc,
+ const llvm::SmallVectorImpl<char> &RawPath) {
}
/// EndOfMainFile - This callback is invoked when the end of the main file is
llvm::StringRef FileName,
bool IsAngled,
const FileEntry *File,
- SourceLocation EndLoc) {
- First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
- EndLoc);
- Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
- EndLoc);
+ SourceLocation EndLoc,
+ const llvm::SmallVectorImpl<char> &RawPath) {
+ First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc, RawPath);
+ Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File,
+ EndLoc, RawPath);
}
virtual void EndOfMainFile() {
llvm::StringRef FileName,
bool IsAngled,
const FileEntry *File,
- SourceLocation EndLoc);
+ SourceLocation EndLoc,
+ const llvm::SmallVectorImpl<char> &RawPath);
};
} // end namespace clang
/// for system #include's or not (i.e. using <> instead of "").
const FileEntry *LookupFile(llvm::StringRef Filename,
bool isAngled, const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir);
+ const DirectoryLookup *&CurDir,
+ llvm::SmallVectorImpl<char> *RawPath);
/// GetCurLookup - The DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
-const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename,
- FileManager &FM) const {
+const FileEntry *HeaderMap::LookupFile(
+ llvm::StringRef Filename, FileManager &FM,
+ llvm::SmallVectorImpl<char> *RawPath) const {
const HMapHeader &Hdr = getHeader();
unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
llvm::SmallString<1024> DestPath;
DestPath += getString(B.Prefix);
DestPath += getString(B.Suffix);
+ if (RawPath != NULL)
+ *RawPath = DestPath;
return FM.getFile(DestPath.str());
}
}
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
-const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename,
- HeaderSearch &HS) const {
+const FileEntry *DirectoryLookup::LookupFile(
+ llvm::StringRef Filename,
+ HeaderSearch &HS, llvm::SmallVectorImpl<char> *RawPath) const {
llvm::SmallString<1024> TmpDir;
if (isNormalDir()) {
// Concatenate the requested file onto the directory.
TmpDir += getDir()->getName();
TmpDir.push_back('/');
TmpDir.append(Filename.begin(), Filename.end());
+ if (RawPath != NULL)
+ *RawPath = TmpDir;
return HS.getFileMgr().getFile(TmpDir.str());
}
if (isFramework())
- return DoFrameworkLookup(Filename, HS);
+ return DoFrameworkLookup(Filename, HS, RawPath);
assert(isHeaderMap() && "Unknown directory lookup");
- return getHeaderMap()->LookupFile(Filename, HS.getFileMgr());
+ return getHeaderMap()->LookupFile(Filename, HS.getFileMgr(), RawPath);
}
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
-const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
- HeaderSearch &HS) const {
+const FileEntry *DirectoryLookup::DoFrameworkLookup(
+ llvm::StringRef Filename,
+ HeaderSearch &HS, llvm::SmallVectorImpl<char> *RawPath) const {
FileManager &FileMgr = HS.getFileMgr();
// Framework names must have a '/' in the filename.
FrameworkName += "Headers/";
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
- if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str()))
+ if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str())) {
+ if (RawPath != NULL)
+ *RawPath = FrameworkName;
return FE;
+ }
// Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h"
const char *Private = "Private";
FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
Private+strlen(Private));
+ if (RawPath != NULL)
+ *RawPath = FrameworkName;
return FileMgr.getFile(FrameworkName.str());
}
/// for system #include's or not (i.e. using <> instead of ""). CurFileEnt, if
/// non-null, indicates where the #including file is, in case a relative search
/// is needed.
-const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename,
- bool isAngled,
- const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir,
- const FileEntry *CurFileEnt) {
+const FileEntry *HeaderSearch::LookupFile(
+ llvm::StringRef Filename,
+ bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir,
+ const FileEntry *CurFileEnt,
+ llvm::SmallVectorImpl<char> *RawPath) {
// If 'Filename' is absolute, check to see if it exists and no searching.
if (llvm::sys::path::is_absolute(Filename)) {
CurDir = 0;
// If this was an #include_next "/absolute/file", fail.
if (FromDir) return 0;
+ if (RawPath != NULL)
+ llvm::Twine(Filename).toVector(*RawPath);
// Otherwise, just return the file.
return FileMgr.getFile(Filename);
}
// of evaluation.
unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo;
getFileInfo(FE).DirInfo = DirInfo;
+ if (RawPath != NULL)
+ *RawPath = TmpDir;
return FE;
}
}
// Check each directory in sequence to see if it contains this file.
for (; i != SearchDirs.size(); ++i) {
const FileEntry *FE =
- SearchDirs[i].LookupFile(Filename, *this);
+ SearchDirs[i].LookupFile(Filename, *this, RawPath);
if (!FE) continue;
CurDir = &SearchDirs[i];
/// for the designated file, otherwise return null.
const FileEntry *HeaderSearch::
LookupSubframeworkHeader(llvm::StringRef Filename,
- const FileEntry *ContextFileEnt) {
+ const FileEntry *ContextFileEnt,
+ llvm::SmallVectorImpl<char> *RawPath) {
assert(ContextFileEnt && "No context file?");
// Framework names must have a '/' in the filename. Find it.
if (!(FE = FileMgr.getFile(HeadersFilename.str())))
return 0;
}
+ if (RawPath != NULL)
+ *RawPath = HeadersFilename;
// This file is a system header or C++ unfriendly if the old file is.
//
/// 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 "").
-const FileEntry *Preprocessor::LookupFile(llvm::StringRef Filename,
- bool isAngled,
- const DirectoryLookup *FromDir,
- const DirectoryLookup *&CurDir) {
+const FileEntry *Preprocessor::LookupFile(
+ llvm::StringRef Filename,
+ bool isAngled,
+ const DirectoryLookup *FromDir,
+ const DirectoryLookup *&CurDir,
+ llvm::SmallVectorImpl<char> *RawPath) {
// If the header lookup mechanism may be relative to the current file, pass in
// info about where the current file is.
const FileEntry *CurFileEnt = 0;
// Do a standard file entry lookup.
CurDir = CurDirLookup;
- const FileEntry *FE =
- HeaderInfo.LookupFile(Filename, isAngled, FromDir, CurDir, CurFileEnt);
+ const FileEntry *FE = HeaderInfo.LookupFile(
+ Filename, isAngled, FromDir, CurDir, CurFileEnt, RawPath);
if (FE) return FE;
// Otherwise, see if this is a subframework header. If so, this is relative
// headers on the #include stack and pass them to HeaderInfo.
if (IsFileLexer()) {
if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
- if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt)))
+ if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
+ RawPath)))
return FE;
}
if (IsFileLexer(ISEntry)) {
if ((CurFileEnt =
SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID())))
- if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt)))
+ if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
+ RawPath)))
return FE;
}
}
// Search include directories.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
+ llvm::SmallString<1024> RawPath;
+ // We get the raw path only if we have 'Callbacks' to which we later pass
+ // the path.
+ const FileEntry *File = LookupFile(
+ Filename, isAngled, LookupFrom, CurDir, Callbacks ? &RawPath : NULL);
if (File == 0) {
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
// Notify the callback object that we've seen an inclusion directive.
if (Callbacks)
- Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File,
- End);
-
+ Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File,
+ End, RawPath);
+
// The #included file will be considered to be a system header if either it is
// in a system include directory, or if the #includer is a system include
// header.
// Search include directories.
const DirectoryLookup *CurDir;
- const FileEntry *File = PP.LookupFile(Filename, isAngled, LookupFrom, CurDir);
+ const FileEntry *File =
+ PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL);
// Get the result value. Result = true means the file exists.
bool Result = File != 0;
// Search include directories for this file.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
+ const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL);
if (File == 0) {
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
return;
MacroDefinitions.erase(Pos);
}
-void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc,
- const clang::Token &IncludeTok,
- llvm::StringRef FileName,
- bool IsAngled,
- const FileEntry *File,
- clang::SourceLocation EndLoc) {
+void PreprocessingRecord::InclusionDirective(
+ SourceLocation HashLoc,
+ const clang::Token &IncludeTok,
+ llvm::StringRef FileName,
+ bool IsAngled,
+ const FileEntry *File,
+ clang::SourceLocation EndLoc,
+ const llvm::SmallVectorImpl<char> &RawPath) {
InclusionDirective::InclusionKind Kind = InclusionDirective::Include;
switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {