From: Douglas Gregor Date: Thu, 25 Oct 2012 00:30:23 +0000 (+0000) Subject: Remove the old predefines-buffer diffing code completely. It's been X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ca6e27138e2fe12e03284d4d820182702141a7d;p=clang Remove the old predefines-buffer diffing code completely. It's been replaced by the more efficient, cleaner preprocessor-option version that occurs earlier in PCH validation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166654 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 978a35d1d9..e9df09d114 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -64,22 +64,6 @@ def err_pch_undef : Error< "'-undef' but %select{precompiled header was not built with it|" "it is not present on the command line}0">; -def warn_cmdline_conflicting_macro_def : Error< - "definition of the macro '%0' conflicts with the definition used to " - "build the precompiled header">; -def note_pch_macro_defined_as : Note< - "definition of macro '%0' in the precompiled header">; -def warn_cmdline_missing_macro_defs : Warning< - "macro definitions used to build the precompiled header are missing">; -def note_using_macro_def_from_pch : Note< - "using this macro definition from precompiled header">; -def warn_macro_name_used_in_pch : Error< - "definition of macro %0 conflicts with an identifier used in the " - "precompiled header">; -def warn_pch_compiler_options_mismatch : Error< - "compiler options used when building the precompiled header differ from " - "the options used when using the precompiled header">; - def err_not_a_pch_file : Error< "'%0' does not appear to be a precompiled header file">, DefaultFatal; } diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index fd4f05fc4a..36eae76728 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -86,15 +86,6 @@ struct HeaderFileInfo; class VersionTuple; class TargetOptions; -struct PCHPredefinesBlock { - /// \brief The file ID for this predefines buffer in a PCH file. - FileID BufferID; - - /// \brief This predefines buffer in a PCH file. - StringRef Data; -}; -typedef SmallVector PCHPredefinesBlocks; - /// \brief Abstract interface for callback invocations by the ASTReader. /// /// While reading an AST file, the ASTReader will call the methods of the @@ -163,27 +154,6 @@ public: return false; } - /// \brief Receives the contents of the predefines buffer. - /// - /// \param Buffers Information about the predefines buffers. - /// - /// \param OriginalFileName The original file name for the AST file, which - /// will appear as an entry in the predefines buffer. - /// - /// \param SuggestedPredefines If necessary, additional definitions are added - /// here. - /// - /// \param Complain Whether to complain about non-matching predefines buffers. - /// - /// \returns true to indicate the predefines are invalid or false otherwise. - virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - StringRef OriginalFileName, - std::string &SuggestedPredefines, - FileManager &FileMgr, - bool Complain) { - return false; - } - /// \brief Receives a HeaderFileInfo entry. virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {} @@ -211,11 +181,6 @@ public: virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, std::string &SuggestedPredefines); - virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - StringRef OriginalFileName, - std::string &SuggestedPredefines, - FileManager &FileMgr, - bool Complain); virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID); virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value); @@ -912,10 +877,6 @@ private: ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } }; - /// \brief All predefines buffers in the chain, to be treated as if - /// concatenated. - PCHPredefinesBlocks PCHPredefinesBuffers; - /// \brief Suggested contents of the predefines buffer, after this /// PCH file has been processed. /// @@ -949,7 +910,6 @@ private: llvm::SmallVectorImpl &Loaded, unsigned ClientLoadCapabilities); bool ReadASTBlock(ModuleFile &F); - bool CheckPredefinesBuffers(bool Complain); bool ParseLineTable(ModuleFile &F, SmallVectorImpl &Record); bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index d246569a4c..4ba0534fb5 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -358,313 +358,6 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, SuggestedPredefines); } -namespace { - struct EmptyStringRef { - bool operator ()(StringRef r) const { return r.empty(); } - }; - struct EmptyBlock { - bool operator ()(const PCHPredefinesBlock &r) const {return r.Data.empty();} - }; -} - -static bool EqualConcatenations(SmallVector L, - PCHPredefinesBlocks R) { - // First, sum up the lengths. - unsigned LL = 0, RL = 0; - for (unsigned I = 0, N = L.size(); I != N; ++I) { - LL += L[I].size(); - } - for (unsigned I = 0, N = R.size(); I != N; ++I) { - RL += R[I].Data.size(); - } - if (LL != RL) - return false; - if (LL == 0 && RL == 0) - return true; - - // Kick out empty parts, they confuse the algorithm below. - L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end()); - R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end()); - - // Do it the hard way. At this point, both vectors must be non-empty. - StringRef LR = L[0], RR = R[0].Data; - unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size(); - (void) RN; - for (;;) { - // Compare the current pieces. - if (LR.size() == RR.size()) { - // If they're the same length, it's pretty easy. - if (LR != RR) - return false; - // Both pieces are done, advance. - ++LI; - ++RI; - // If either string is done, they're both done, since they're the same - // length. - if (LI == LN) { - assert(RI == RN && "Strings not the same length after all?"); - return true; - } - LR = L[LI]; - RR = R[RI].Data; - } else if (LR.size() < RR.size()) { - // Right piece is longer. - if (!RR.startswith(LR)) - return false; - ++LI; - assert(LI != LN && "Strings not the same length after all?"); - RR = RR.substr(LR.size()); - LR = L[LI]; - } else { - // Left piece is longer. - if (!LR.startswith(RR)) - return false; - ++RI; - assert(RI != RN && "Strings not the same length after all?"); - LR = LR.substr(RR.size()); - RR = R[RI].Data; - } - } -} - -static std::pair -FindMacro(const PCHPredefinesBlocks &Buffers, StringRef MacroDef) { - std::pair Res; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) { - Res.second = Buffers[I].Data.find(MacroDef); - if (Res.second != StringRef::npos) { - Res.first = Buffers[I].BufferID; - break; - } - } - return Res; -} - -bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - StringRef OriginalFileName, - std::string &SuggestedPredefines, - FileManager &FileMgr, - bool Complain) { - // We are in the context of an implicit include, so the predefines buffer will - // have a #include entry for the PCH file itself (as normalized by the - // preprocessor initialization). Find it and skip over it in the checking - // below. - SmallString<256> PCHInclude; - PCHInclude += "#include \""; - PCHInclude += HeaderSearch::NormalizeDashIncludePath(OriginalFileName, - FileMgr); - PCHInclude += "\"\n"; - std::pair Split = - StringRef(PP.getPredefines()).split(PCHInclude.str()); - StringRef Left = Split.first, Right = Split.second; - if (Left == PP.getPredefines()) { - if (Complain) - Error("Missing PCH include entry!"); - return true; - } - - // If the concatenation of all the PCH buffers is equal to the adjusted - // command line, we're done. - SmallVector CommandLine; - CommandLine.push_back(Left); - CommandLine.push_back(Right); - if (EqualConcatenations(CommandLine, Buffers)) - 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. - SmallVector PCHLines; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) - Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - SmallVector CmdLineLines; - Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - // Pick out implicit #includes after the PCH and don't consider them for - // validation; we will insert them into SuggestedPredefines so that the - // preprocessor includes them. - std::string IncludesAfterPCH; - SmallVector AfterPCHLines; - Right.split(AfterPCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - for (unsigned i = 0, e = AfterPCHLines.size(); i != e; ++i) { - if (AfterPCHLines[i].startswith("#include ")) { - IncludesAfterPCH += AfterPCHLines[i]; - IncludesAfterPCH += '\n'; - } else { - CmdLineLines.push_back(AfterPCHLines[i]); - } - } - - // Make sure we add the includes last into SuggestedPredefines before we - // exit this function. - struct AddIncludesRAII { - std::string &SuggestedPredefines; - std::string &IncludesAfterPCH; - - AddIncludesRAII(std::string &SuggestedPredefines, - std::string &IncludesAfterPCH) - : SuggestedPredefines(SuggestedPredefines), - IncludesAfterPCH(IncludesAfterPCH) { } - ~AddIncludesRAII() { - SuggestedPredefines += IncludesAfterPCH; - } - } AddIncludes(SuggestedPredefines, IncludesAfterPCH); - - // Sort both sets of predefined buffer lines, since we allow some extra - // definitions and they may appear at any point in the output. - std::sort(CmdLineLines.begin(), CmdLineLines.end()); - std::sort(PCHLines.begin(), PCHLines.end()); - - // Determine which predefines that were used to build the PCH file are missing - // from the command line. - std::vector MissingPredefines; - std::set_difference(PCHLines.begin(), PCHLines.end(), - CmdLineLines.begin(), CmdLineLines.end(), - std::back_inserter(MissingPredefines)); - - bool MissingDefines = false; - bool ConflictingDefines = false; - for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) { - StringRef Missing = MissingPredefines[I]; - if (Missing.startswith("#include ")) { - // An -include was specified when generating the PCH; it is included in - // the PCH, just ignore it. - continue; - } - if (!Missing.startswith("#define ")) { - if (Complain) - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is a macro definition. Determine the name of the macro we're - // defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Missing.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName); - - // Determine whether this macro was given a different definition on the - // command line. - std::string MacroDefStart = "#define " + MacroName.str(); - std::string::size_type MacroDefLen = MacroDefStart.size(); - SmallVector::iterator ConflictPos - = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(), - MacroDefStart); - for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) { - if (!ConflictPos->startswith(MacroDefStart)) { - // Different macro; we're done. - ConflictPos = CmdLineLines.end(); - break; - } - - assert(ConflictPos->size() > MacroDefLen && - "Invalid #define in predefines buffer?"); - if ((*ConflictPos)[MacroDefLen] != ' ' && - (*ConflictPos)[MacroDefLen] != '(') - continue; // Longer macro name; keep trying. - - // We found a conflicting macro definition. - break; - } - - if (ConflictPos != CmdLineLines.end()) { - if (!Complain) - return true; - - Reader.Diag(diag::warn_cmdline_conflicting_macro_def) - << MacroName; - - // Show the definition of this macro within the PCH file. - std::pair MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName; - - ConflictingDefines = true; - continue; - } - - // If the macro doesn't conflict, then we'll just pick up the macro - // definition from the PCH file. Warn the user that they made a mistake. - if (ConflictingDefines) - continue; // Don't complain if there are already conflicting defs - - if (!MissingDefines) { - if (!Complain) - return true; - - Reader.Diag(diag::warn_cmdline_missing_macro_defs); - MissingDefines = true; - } - - if (!Complain) - return true; - - // Show the definition of this macro within the PCH file. - std::pair MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch); - } - - if (ConflictingDefines) - return true; - - // Determine what predefines were introduced based on command-line - // parameters that were not present when building the PCH - // file. Extra #defines are okay, so long as the identifiers being - // defined were not used within the precompiled header. - std::vector ExtraPredefines; - std::set_difference(CmdLineLines.begin(), CmdLineLines.end(), - PCHLines.begin(), PCHLines.end(), - std::back_inserter(ExtraPredefines)); - for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) { - StringRef &Extra = ExtraPredefines[I]; - if (!Extra.startswith("#define ")) { - if (Complain) - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is an extra macro definition. Determine the name of the - // macro we're defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Extra.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName); - - // Check whether this name was used somewhere in the PCH file. If - // so, defining it as a macro could change behavior, so we reject - // the PCH file. - if (IdentifierInfo *II = Reader.get(MacroName)) { - if (Complain) - Reader.Diag(diag::warn_macro_name_used_in_pch) << II; - return true; - } - - // Add this definition to the suggested predefines buffer. - SuggestedPredefines += Extra; - SuggestedPredefines += '\n'; - } - - // If we get here, it's because the predefines buffer had compatible - // contents. Accept the PCH file. - return false; -} - void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) { PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID); @@ -1025,11 +718,6 @@ void ASTReader::Error(unsigned DiagID, Diag(DiagID) << Arg1 << Arg2; } -/// \brief Tell the AST listener about the predefines buffers in the chain. -bool ASTReader::CheckPredefinesBuffers(bool Complain) { - return false; -} - //===----------------------------------------------------------------------===// // Source Manager Deserialization //===----------------------------------------------------------------------===// @@ -1384,17 +1072,7 @@ bool ASTReader::ReadSLocEntry(int ID) { llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1), Name); - FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, - BaseOffset + Offset); - - if (strcmp(Name, "") == 0 && F->Kind == MK_PCH) { - PCHPredefinesBlock Block = { - BufferID, - StringRef(BlobStart, BlobLen - 1) - }; - PCHPredefinesBuffers.push_back(Block); - } - + SourceMgr.createFileIDForMemBuffer(Buffer, ID, BaseOffset + Offset); break; } @@ -3152,15 +2830,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, } } - // Check the predefines buffers. - bool ConfigComplain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; - if (!DisableValidation && Type == MK_PCH && - // FIXME: CheckPredefinesBuffers also sets the SuggestedPredefines; - // if DisableValidation is true, defines that were set on command-line - // but not in the PCH file will not be added to SuggestedPredefines. - CheckPredefinesBuffers(ConfigComplain)) - return ConfigurationMismatch; - // Mark all of the identifiers in the identifier table as being out of date, // so that various accessors know to check the loaded modules when the // identifier is used.