diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-15 17:54:22 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-02-15 17:54:22 +0000 |
commit | 8e3df4d0864f0a966c20088ca1a29c3398b7639d (patch) | |
tree | 1c380a3a70b49f586732f44947003562d0a40e08 /lib | |
parent | 5ac96d5f54a94d57f485de8103eb05a0f19e1c39 (diff) |
Allow resolving headers from a PCH even after headers+PCH were moved to another path.
Store in PCH the directory that the PCH was originally created in.
If a header file is not found at the path that we expect it to be and the PCH file
was moved from its original location, try to resolve the file by assuming that
header+PCH were moved together and the header is in the same place relative to the PCH.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125576 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 7 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 52 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 30 | ||||
-rw-r--r-- | lib/Serialization/GeneratePCH.cpp | 5 |
5 files changed, 90 insertions, 12 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 00902e810c..0370c2e125 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -653,7 +653,7 @@ public: PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP, bool Chaining, const char *isysroot, llvm::raw_ostream *Out) - : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { } + : PCHGenerator(PP, "", Chaining, isysroot, Out), Unit(Unit) { } virtual void HandleTopLevelDecl(DeclGroupRef D) { for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) { @@ -700,9 +700,11 @@ public: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { std::string Sysroot; + std::string OutputFile; llvm::raw_ostream *OS = 0; bool Chaining; - if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, + if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, + OutputFile, OS, Chaining)) return 0; @@ -2008,7 +2010,7 @@ bool ASTUnit::Save(llvm::StringRef File) { std::vector<unsigned char> Buffer; llvm::BitstreamWriter Stream(Buffer); ASTWriter Writer(Stream); - Writer.WriteAST(getSema(), 0, 0); + Writer.WriteAST(getSema(), 0, std::string(), 0); // Write the generated bitstream to "Out". if (!Buffer.empty()) diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 0ffea201cd..e454321c0c 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -83,19 +83,21 @@ ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { std::string Sysroot; + std::string OutputFile; llvm::raw_ostream *OS = 0; bool Chaining; - if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining)) + if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining)) return 0; const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? Sysroot.c_str() : 0; - return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS); + return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS); } bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, llvm::StringRef InFile, std::string &Sysroot, + std::string &OutputFile, llvm::raw_ostream *&OS, bool &Chaining) { Sysroot = CI.getHeaderSearchOpts().Sysroot; @@ -111,6 +113,7 @@ bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, if (!OS) return true; + OutputFile = CI.getFrontendOpts().OutputFile; Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); return false; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 5e3fa132e6..3dcc62ebc1 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1181,6 +1181,39 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(PerFileData &F) { } } +/// \brief If a header file is not found at the path that we expect it to be +/// and the PCH file was moved from its original location, try to resolve the +/// file by assuming that header+PCH were moved together and the header is in +/// the same place relative to the PCH. +static std::string +resolveFileRelativeToOriginalDir(const std::string &Filename, + const std::string &OriginalDir, + const std::string &CurrDir) { + assert(OriginalDir != CurrDir && + "No point trying to resolve the file if the PCH dir didn't change"); + using namespace llvm::sys; + llvm::SmallString<128> filePath(Filename); + fs::make_absolute(filePath); + assert(path::is_absolute(OriginalDir)); + llvm::SmallString<128> currPCHPath(CurrDir); + + path::const_iterator fileDirI = path::begin(path::parent_path(filePath)), + fileDirE = path::end(path::parent_path(filePath)); + path::const_iterator origDirI = path::begin(OriginalDir), + origDirE = path::end(OriginalDir); + // Skip the common path components from filePath and OriginalDir. + while (fileDirI != fileDirE && origDirI != origDirE && + *fileDirI == *origDirI) { + ++fileDirI; + ++origDirI; + } + for (; origDirI != origDirE; ++origDirI) + path::append(currPCHPath, ".."); + path::append(currPCHPath, fileDirI, fileDirE); + path::append(currPCHPath, path::filename(Filename)); + return currPCHPath.str(); +} + /// \brief Get a cursor that's correctly positioned for reading the source /// location entry with the given ID. ASTReader::PerFileData *ASTReader::SLocCursorForID(unsigned ID) { @@ -1235,6 +1268,14 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) { std::string Filename(BlobStart, BlobStart + BlobLen); MaybeAddSystemRootToFilename(Filename); const FileEntry *File = FileMgr.getFile(Filename); + if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() && + OriginalDir != CurrentDir) { + std::string resolved = resolveFileRelativeToOriginalDir(Filename, + OriginalDir, + CurrentDir); + if (!resolved.empty()) + File = FileMgr.getFile(resolved); + } if (File == 0) File = FileMgr.getVirtualFile(Filename, (off_t)Record[4], (time_t)Record[5]); @@ -2179,6 +2220,12 @@ ASTReader::ReadASTBlock(PerFileData &F) { MaybeAddSystemRootToFilename(OriginalFileName); break; + case ORIGINAL_PCH_DIR: + // The primary AST will be the last to get here, so it will be the one + // that's used. + OriginalDir.assign(BlobStart, BlobLen); + break; + case VERSION_CONTROL_BRANCH_REVISION: { const std::string &CurBranch = getClangFullRepositoryVersion(); llvm::StringRef ASTBranch(BlobStart, BlobLen); @@ -2393,6 +2440,11 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName, // Set the AST file name. F.FileName = FileName; + if (FileName != "-") { + CurrentDir = llvm::sys::path::parent_path(FileName); + if (CurrentDir.empty()) CurrentDir = "."; + } + // Open the AST file. // // FIXME: This shouldn't be here, we should just take a raw_ostream. diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index f1af8354a2..cb29973105 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -899,7 +899,8 @@ adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { } /// \brief Write the AST metadata (e.g., i686-apple-darwin9). -void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { +void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot, + const std::string &OutputFile) { using namespace llvm; // Metadata @@ -947,6 +948,23 @@ void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); } + // Original PCH directory + if (!OutputFile.empty() && OutputFile != "-") { + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name + unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev); + + llvm::SmallString<128> OutputPath(OutputFile); + + llvm::sys::fs::make_absolute(OutputPath); + StringRef origDir = llvm::sys::path::parent_path(OutputPath); + + RecordData Record; + Record.push_back(ORIGINAL_PCH_DIR); + Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); + } + // Repository branch/version information. BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev(); RepoAbbrev->Add(BitCodeAbbrevOp(VERSION_CONTROL_BRANCH_REVISION)); @@ -2568,6 +2586,7 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) } void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const std::string &OutputFile, const char *isysroot) { // Emit the file header. Stream.Emit((unsigned)'C', 8); @@ -2580,11 +2599,12 @@ void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, if (Chain) WriteASTChain(SemaRef, StatCalls, isysroot); else - WriteASTCore(SemaRef, StatCalls, isysroot); + WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile); } void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char *isysroot) { + const char *isysroot, + const std::string &OutputFile) { using namespace llvm; ASTContext &Context = SemaRef.Context; @@ -2692,7 +2712,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // Write the remaining AST contents. RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); + WriteMetadata(Context, isysroot, OutputFile); WriteLanguageOptions(Context.getLangOptions()); if (StatCalls && !isysroot) WriteStatCache(*StatCalls); @@ -2827,7 +2847,7 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, RecordData Record; Stream.EnterSubblock(AST_BLOCK_ID, 5); - WriteMetadata(Context, isysroot); + WriteMetadata(Context, isysroot, ""); if (StatCalls && !isysroot) WriteStatCache(*StatCalls); // FIXME: Source manager block should only write new stuff, which could be diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp index 3b4f869c00..b8833ceacc 100644 --- a/lib/Serialization/GeneratePCH.cpp +++ b/lib/Serialization/GeneratePCH.cpp @@ -27,10 +27,11 @@ using namespace clang; PCHGenerator::PCHGenerator(const Preprocessor &PP, + const std::string &OutputFile, bool Chaining, const char *isysroot, llvm::raw_ostream *OS) - : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), + : PP(PP), OutputFile(OutputFile), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0), Stream(Buffer), Writer(Stream), Chaining(Chaining) { // Install a stat() listener to keep track of all of the stat() // calls. @@ -50,7 +51,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WriteAST(*SemaPtr, StatCalls, isysroot); + Writer.WriteAST(*SemaPtr, StatCalls, OutputFile, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); |