diff options
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()); |