From: Manuel Klimek Date: Tue, 26 Apr 2011 21:50:03 +0000 (+0000) Subject: To be able to replay compilations we need to accurately remodel how X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7412494982c8b50c90961302c3a718633b2c3ab7;p=clang To be able to replay compilations we need to accurately remodel how includes get resolved, especially when they are found relatively to another include file. We also try to get it working for framework includes, but that part of the code is untested, as I don't have a code base that uses it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130246 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index 1ee19266f3..1ee6953a12 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -122,17 +122,26 @@ public: /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. - /// 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". + /// + /// \param Filename The file to look up relative to the search paths. + /// + /// \param HS The header search instance to search with. + /// + /// \param SearchPath If not NULL, will be set to the search path relative + /// to which the file was found. + /// + /// \param RelativePath If not NULL, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS, - llvm::SmallVectorImpl *RawPath) const; + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const; private: const FileEntry *DoFrameworkLookup( llvm::StringRef Filename, HeaderSearch &HS, - llvm::SmallVectorImpl *RawPath) const; + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const; }; diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 54c7eb47c8..e333840b6a 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -52,8 +52,7 @@ public: /// 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 *RawPath) const; + const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const; /// getFileName - Return the filename of the headermap. const char *getFileName() const; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 3ba780438f..fec4dad1e7 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -182,18 +182,32 @@ public: } /// LookupFile - Given a "foo" or reference, look up the indicated file, - /// return null on failure. isAngled indicates whether the file reference is - /// a <> reference. If successful, this returns 'UsedDir', the - /// DirectoryLookup member the file was found in, or null if not applicable. - /// If CurDir is non-null, the file was found in the specified directory - /// search location. This is used to implement #include_next. CurFileEnt, if - /// non-null, indicates where the #including file is, in case a relative - /// search is needed. + /// return null on failure. + /// + /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member + /// the file was found in, or null if not applicable. + /// + /// \param isAngled indicates whether the file reference is a <> reference. + /// + /// \param CurDir If non-null, the file was found in the specified directory + /// search location. This is used to implement #include_next. + /// + /// \param CurFileEnt If non-null, indicates where the #including file is, in + /// case a relative search is needed. + /// + /// \param SearchPath If non-null, will be set to the search path relative + /// to which the file was found. If the include path is absolute, SearchPath + /// will be set to an empty string. + /// + /// \param RelativePath If non-null, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt, - llvm::SmallVectorImpl *RawPath); + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// LookupSubframeworkHeader - Look up a subframework for the specified /// #include file. For example, if #include'ing from @@ -203,7 +217,8 @@ public: const FileEntry *LookupSubframeworkHeader( llvm::StringRef Filename, const FileEntry *RelativeFileEnt, - llvm::SmallVectorImpl *RawPath); + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// LookupFrameworkCache - Look up the specified framework name in our /// framework cache, returning the DirectoryEntry it is in if we know, diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 242986dae5..fd07a29f8e 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -76,16 +76,25 @@ public: /// \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". + /// \param SearchPath Contains the search path which was used to find the file + /// in the file system. If the file was found via an absolute include path, + /// SearchPath will be empty. For framework includes, the SearchPath and + /// RelativePath will be split up. For example, if an include of "Some/Some.h" + /// is found via the framework path + /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be + /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be + /// "Some.h". + /// + /// \param RelativePath The path relative to SearchPath, at which the include + /// file was found. This is equal to FileName except for framework includes. virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName, bool IsAngled, const FileEntry *File, SourceLocation EndLoc, - const llvm::SmallVectorImpl &RawPath) { + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { } /// EndOfMainFile - This callback is invoked when the end of the main file is @@ -194,11 +203,12 @@ public: bool IsAngled, const FileEntry *File, SourceLocation EndLoc, - const llvm::SmallVectorImpl &RawPath) { + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, RawPath); + EndLoc, SearchPath, RelativePath); Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc, RawPath); + EndLoc, SearchPath, RelativePath); } virtual void EndOfMainFile() { diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index f5066d4bfd..7be845549d 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -342,7 +342,8 @@ namespace clang { bool IsAngled, const FileEntry *File, SourceLocation EndLoc, - const llvm::SmallVectorImpl &RawPath); + llvm::StringRef SearchPath, + llvm::StringRef RelativePath); }; } // end namespace clang diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 04b3e3224f..af3631de52 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -834,7 +834,8 @@ public: const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, - llvm::SmallVectorImpl *RawPath); + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath); /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp index 90ed184a57..e102a6da60 100644 --- a/lib/Lex/HeaderMap.cpp +++ b/lib/Lex/HeaderMap.cpp @@ -200,8 +200,7 @@ void HeaderMap::dump() const { /// 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, - llvm::SmallVectorImpl *RawPath) const { + llvm::StringRef Filename, FileManager &FM) const { const HMapHeader &Hdr = getHeader(); unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets); @@ -224,8 +223,6 @@ const FileEntry *HeaderMap::LookupFile( llvm::SmallString<1024> DestPath; DestPath += getString(B.Prefix); DestPath += getString(B.Suffix); - if (RawPath != NULL) - *RawPath = DestPath; return FM.getFile(DestPath.str()); } } diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index db91ba4e78..1fe0240f43 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -116,7 +116,9 @@ const char *DirectoryLookup::getName() const { /// if it exists or returning null if not. const FileEntry *DirectoryLookup::LookupFile( llvm::StringRef Filename, - HeaderSearch &HS, llvm::SmallVectorImpl *RawPath) const { + HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const { llvm::SmallString<1024> TmpDir; if (isNormalDir()) { // Concatenate the requested file onto the directory. @@ -124,16 +126,36 @@ const FileEntry *DirectoryLookup::LookupFile( TmpDir += getDir()->getName(); TmpDir.push_back('/'); TmpDir.append(Filename.begin(), Filename.end()); - if (RawPath != NULL) - *RawPath = TmpDir; + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(getDir()->getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } return HS.getFileMgr().getFile(TmpDir.str(), /*openFile=*/true); } if (isFramework()) - return DoFrameworkLookup(Filename, HS, RawPath); + return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath); assert(isHeaderMap() && "Unknown directory lookup"); - return getHeaderMap()->LookupFile(Filename, HS.getFileMgr(), RawPath); + const FileEntry * const Result = getHeaderMap()->LookupFile( + Filename, HS.getFileMgr()); + if (Result) { + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(getDir()->getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } + } + return Result; } @@ -141,7 +163,9 @@ const FileEntry *DirectoryLookup::LookupFile( /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( llvm::StringRef Filename, - HeaderSearch &HS, llvm::SmallVectorImpl *RawPath) const { + HeaderSearch &HS, + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. @@ -187,15 +211,25 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( FrameworkDirCache = getFrameworkDir(); } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); + } + // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; + + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); + } + FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(), /*openFile=*/true)) { - if (RawPath != NULL) - *RawPath = FrameworkName; return FE; } @@ -203,8 +237,10 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); - if (RawPath != NULL) - *RawPath = FrameworkName; + if (SearchPath != NULL) + SearchPath->insert(SearchPath->begin()+OrigSize, Private, + Private+strlen(Private)); + return FileMgr.getFile(FrameworkName.str(), /*openFile=*/true); } @@ -225,7 +261,8 @@ const FileEntry *HeaderSearch::LookupFile( const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, const FileEntry *CurFileEnt, - llvm::SmallVectorImpl *RawPath) { + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { // If 'Filename' is absolute, check to see if it exists and no searching. if (llvm::sys::path::is_absolute(Filename)) { CurDir = 0; @@ -233,8 +270,12 @@ const FileEntry *HeaderSearch::LookupFile( // If this was an #include_next "/absolute/file", fail. if (FromDir) return 0; - if (RawPath != NULL) - llvm::Twine(Filename).toVector(*RawPath); + if (SearchPath != NULL) + SearchPath->clear(); + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } // Otherwise, just return the file. return FileMgr.getFile(Filename, /*openFile=*/true); } @@ -260,8 +301,15 @@ const FileEntry *HeaderSearch::LookupFile( // of evaluation. unsigned DirInfo = getFileInfo(CurFileEnt).DirInfo; getFileInfo(FE).DirInfo = DirInfo; - if (RawPath != NULL) - *RawPath = TmpDir; + if (SearchPath != NULL) { + llvm::StringRef SearchPathRef(CurFileEnt->getDir()->getName()); + SearchPath->clear(); + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); + } + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin(), Filename.end()); + } return FE; } } @@ -299,7 +347,7 @@ const FileEntry *HeaderSearch::LookupFile( // 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, RawPath); + SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath); if (!FE) continue; CurDir = &SearchDirs[i]; @@ -325,7 +373,8 @@ const FileEntry *HeaderSearch::LookupFile( const FileEntry *HeaderSearch:: LookupSubframeworkHeader(llvm::StringRef Filename, const FileEntry *ContextFileEnt, - llvm::SmallVectorImpl *RawPath) { + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { assert(ContextFileEnt && "No context file?"); // Framework names must have a '/' in the filename. Find it. @@ -373,21 +422,36 @@ LookupSubframeworkHeader(llvm::StringRef Filename, const FileEntry *FE = 0; + if (RelativePath != NULL) { + RelativePath->clear(); + RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); + } + // Check ".../Frameworks/HIToolbox.framework/Headers/HIToolbox.h" llvm::SmallString<1024> HeadersFilename(FrameworkName); HeadersFilename += "Headers/"; + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); + } + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; + if (SearchPath != NULL) { + SearchPath->clear(); + // Without trailing '/'. + SearchPath->append(HeadersFilename.begin(), HeadersFilename.end()-1); + } + HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); if (!(FE = FileMgr.getFile(HeadersFilename.str(), /*openFile=*/true))) return 0; } - if (RawPath != NULL) - *RawPath = HeadersFilename; // This file is a system header or C++ unfriendly if the old file is. // diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index ac4f8e0b8f..af3fa6e2ad 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -474,7 +474,8 @@ const FileEntry *Preprocessor::LookupFile( bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, - llvm::SmallVectorImpl *RawPath) { + llvm::SmallVectorImpl *SearchPath, + llvm::SmallVectorImpl *RelativePath) { // 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; @@ -497,7 +498,8 @@ const FileEntry *Preprocessor::LookupFile( // Do a standard file entry lookup. CurDir = CurDirLookup; const FileEntry *FE = HeaderInfo.LookupFile( - Filename, isAngled, FromDir, CurDir, CurFileEnt, RawPath); + Filename, isAngled, FromDir, CurDir, CurFileEnt, + SearchPath, RelativePath); if (FE) return FE; // Otherwise, see if this is a subframework header. If so, this is relative @@ -506,7 +508,7 @@ const FileEntry *Preprocessor::LookupFile( if (IsFileLexer()) { if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, - RawPath))) + SearchPath, RelativePath))) return FE; } @@ -515,8 +517,8 @@ const FileEntry *Preprocessor::LookupFile( if (IsFileLexer(ISEntry)) { if ((CurFileEnt = SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) - if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, - RawPath))) + if ((FE = HeaderInfo.LookupSubframeworkHeader( + Filename, CurFileEnt, SearchPath, RelativePath))) return FE; } } @@ -1171,11 +1173,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Search include directories. const DirectoryLookup *CurDir; - llvm::SmallString<1024> RawPath; + llvm::SmallString<1024> SearchPath; + llvm::SmallString<1024> RelativePath; // 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); + Filename, isAngled, LookupFrom, CurDir, + Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL); if (File == 0) { Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; @@ -1184,7 +1188,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // Notify the callback object that we've seen an inclusion directive. if (Callbacks) Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, - End, RawPath); + End, SearchPath, RelativePath); // 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 diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 0e38e39c26..29f9cd6e32 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -668,7 +668,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // Search include directories. const DirectoryLookup *CurDir; const FileEntry *File = - PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL); + PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL); // Get the result value. Result = true means the file exists. bool Result = File != 0; diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 5d6ad6e716..0c180918dc 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -368,7 +368,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { // Search include directories for this file. const DirectoryLookup *CurDir; - const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL); + const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL); if (File == 0) { Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; return; diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp index b7f6e75c47..9555611dc5 100644 --- a/lib/Lex/PreprocessingRecord.cpp +++ b/lib/Lex/PreprocessingRecord.cpp @@ -153,7 +153,8 @@ void PreprocessingRecord::InclusionDirective( bool IsAngled, const FileEntry *File, clang::SourceLocation EndLoc, - const llvm::SmallVectorImpl &RawPath) { + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {