From: Daniel Dunbar Date: Wed, 11 Nov 2009 05:29:04 +0000 (+0000) Subject: Redo how PCH handles its implicit include. Instead of treating this specially in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7b5a1210d93ca62ecd61800f245c87259b1f8f79;p=clang Redo how PCH handles its implicit include. Instead of treating this specially in the front-end (as far as the preprocessor goes), follow the usual logic of inserting the (original include path) name into the predefines buffer. This pushes the responsibility for handling this to PCH instead of the front-end. In PCH this requires being a little more clever when we diff the predefines buffers. Neither of these solutions are particularly great, I think what we eventually should do is something like gcc where we insert a special marker to indicate the PCH file, but then run the preprocessor as usual. This would be clearer and would allow us to drop the overly clever predefines handling. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86806 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 0c56109f00..85861fab4a 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -88,17 +88,18 @@ public: /// \param PCHPredef The start of the predefines buffer in the PCH /// file. /// - /// \param PCHPredefLen The length of the predefines buffer in the PCH - /// file. - /// /// \param PCHBufferID The FileID for the PCH predefines buffer. /// + /// \param OriginalFileName The original file name for the PCH, which will + /// appear as an entry in the predefines buffer. + /// /// \param SuggestedPredefines If necessary, additional definitions are added /// here. /// /// \returns true to indicate the predefines are invalid or false otherwise. virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines) { return false; } @@ -126,6 +127,7 @@ public: virtual bool ReadTargetTriple(llvm::StringRef Triple); virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines); virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI); virtual void ReadCounter(unsigned Value); @@ -311,10 +313,13 @@ private: /// the PCH file. llvm::SmallVector ObjCCategoryImpls; - /// \brief The original file name that was used to build the PCH - /// file. + /// \brief The original file name that was used to build the PCH file, which + /// may have been modified for relocatable-pch support. std::string OriginalFileName; + /// \brief The actual original file name that was used to build the PCH file. + std::string ActualOriginalFileName; + /// \brief Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index b5e65589e3..82786aaa7f 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -68,6 +68,7 @@ public: virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines) { Predefines = PCHPredef; return false; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 42aa43b81f..936382482c 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -156,17 +156,34 @@ static std::vector splitLines(llvm::StringRef Str, bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines) { - // If the two predefines buffers compare equal, we're done! - if (PP.getPredefines() == PCHPredef) + // We are in the context of an implicit include, so the predefines buffer + // will have a #include entry for the PCH file itself. Find it and skip over + // it in the checking below. + llvm::SmallString<256> PCHInclude; + PCHInclude += "#include \""; + PCHInclude += OriginalFileName; + PCHInclude += "\"\n"; + std::pair Split = + llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); + llvm::StringRef Left = Split.first, Right = Split.second; + assert(Left != PP.getPredefines() && "Missing PCH include entry!"); + + // If the predefines is equal to the joined left and right halves, we're done! + if (Left.size() + Right.size() == PCHPredef.size() && + PCHPredef.startswith(Left) && PCHPredef.endswith(Right)) return false; SourceManager &SourceMgr = PP.getSourceManager(); // The predefines buffers are different. Determine what the differences are, // and whether they require us to reject the PCH file. - std::vector CmdLineLines = splitLines(PP.getPredefines()); std::vector PCHLines = splitLines(PCHPredef); + std::vector CmdLineLines = splitLines(Left); + std::vector CmdLineLinesRight = splitLines(Right); + CmdLineLines.insert(CmdLineLines.end(), + CmdLineLinesRight.begin(), CmdLineLinesRight.end()); // Sort both sets of predefined buffer lines, since we allow some extra // definitions and they may appear at any point in the output. @@ -624,6 +641,7 @@ bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID) { if (Listener) return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID, + ActualOriginalFileName, SuggestedPredefines); return false; } @@ -1333,7 +1351,8 @@ PCHReader::ReadPCHBlock() { break; case pch::ORIGINAL_FILE_NAME: - OriginalFileName.assign(BlobStart, BlobLen); + ActualOriginalFileName.assign(BlobStart, BlobLen); + OriginalFileName = ActualOriginalFileName; MaybeAddSystemRootToFilename(OriginalFileName); break; diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 85305f86fc..a13d1a4da4 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -1110,7 +1110,7 @@ static void InitializePreprocessorOptions(PreprocessorOptions &InitOpts) { InitOpts.addMacroInclude(ImplicitMacroIncludes[i]); if (!ImplicitIncludePTH.empty() || !ImplicitIncludes.empty() || - (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput)) { + !ImplicitIncludePCH.empty()) { // We want to add these paths to the predefines buffer in order, make a // temporary vector to sort by their occurrence. llvm::SmallVector, 8> OrderedPaths; @@ -1118,7 +1118,7 @@ static void InitializePreprocessorOptions(PreprocessorOptions &InitOpts) { if (!ImplicitIncludePTH.empty()) OrderedPaths.push_back(std::make_pair(ImplicitIncludePTH.getPosition(), &ImplicitIncludePTH)); - if (!ImplicitIncludePCH.empty() && ProgAction == PrintPreprocessedInput) + if (!ImplicitIncludePCH.empty()) OrderedPaths.push_back(std::make_pair(ImplicitIncludePCH.getPosition(), &ImplicitIncludePCH)); for (unsigned i = 0, e = ImplicitIncludes.size(); i != e; ++i) @@ -1126,7 +1126,6 @@ static void InitializePreprocessorOptions(PreprocessorOptions &InitOpts) { &ImplicitIncludes[i])); llvm::array_pod_sort(OrderedPaths.begin(), OrderedPaths.end()); - // Now that they are ordered by position, add to the predefines buffer. for (unsigned i = 0, e = OrderedPaths.size(); i != e; ++i) { std::string *Ptr = OrderedPaths[i].second; @@ -1142,10 +1141,10 @@ static void InitializePreprocessorOptions(PreprocessorOptions &InitOpts) { // file that was used to build the precompiled header. assert(Ptr == &ImplicitIncludePCH); std::string OriginalFile = PCHReader::getOriginalSourceFile(*Ptr); - if (!OriginalFile.empty()) { - InitOpts.addInclude(OriginalFile); - InitOpts.setImplicitPCHInclude(""); - } + // FIXME: Don't fail like this. + if (OriginalFile.empty()) + exit(1); + InitOpts.addInclude(OriginalFile); } } }