summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp2323
1 files changed, 1393 insertions, 930 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 3adbc57..deba302 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -30,13 +30,16 @@
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Basic/OnDiskHashTable.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/StringExtras.h"
@@ -62,353 +65,306 @@ using namespace clang::serialization::reader;
ASTReaderListener::~ASTReaderListener() {}
-bool
-PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
- const LangOptions &PPLangOpts = PP.getLangOpts();
-
-#define LANGOPT(Name, Bits, Default, Description) \
- if (PPLangOpts.Name != LangOpts.Name) { \
- Reader.Diag(diag::err_pch_langopt_mismatch) \
- << Description << LangOpts.Name << PPLangOpts.Name; \
+/// \brief Compare the given set of language options against an existing set of
+/// language options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the languagae options mis-match, false otherwise.
+static bool checkLanguageOptions(const LangOptions &LangOpts,
+ const LangOptions &ExistingLangOpts,
+ DiagnosticsEngine *Diags) {
+#define LANGOPT(Name, Bits, Default, Description) \
+ if (ExistingLangOpts.Name != LangOpts.Name) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_mismatch) \
+ << Description << LangOpts.Name << ExistingLangOpts.Name; \
+ return true; \
+ }
+
+#define VALUE_LANGOPT(Name, Bits, Default, Description) \
+ if (ExistingLangOpts.Name != LangOpts.Name) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_value_mismatch) \
+ << Description; \
return true; \
}
-#define VALUE_LANGOPT(Name, Bits, Default, Description) \
- if (PPLangOpts.Name != LangOpts.Name) { \
- Reader.Diag(diag::err_pch_langopt_value_mismatch) \
- << Description; \
- return true; \
-}
-
-#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
- if (PPLangOpts.get##Name() != LangOpts.get##Name()) { \
- Reader.Diag(diag::err_pch_langopt_value_mismatch) \
- << Description; \
- return true; \
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ if (ExistingLangOpts.get##Name() != LangOpts.get##Name()) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_langopt_value_mismatch) \
+ << Description; \
+ return true; \
}
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
- if (PPLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
- Reader.Diag(diag::err_pch_langopt_value_mismatch)
+ if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) {
+ if (Diags)
+ Diags->Report(diag::err_pch_langopt_value_mismatch)
<< "target Objective-C runtime";
return true;
}
-
+
return false;
}
-bool PCHValidator::ReadTargetTriple(StringRef Triple) {
- if (Triple == PP.getTargetInfo().getTriple().str())
- return false;
-
- Reader.Diag(diag::warn_pch_target_triple)
- << Triple << PP.getTargetInfo().getTriple().str();
- return true;
-}
+/// \brief Compare the given set of target options against an existing set of
+/// target options.
+///
+/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+///
+/// \returns true if the target options mis-match, false otherwise.
+static bool checkTargetOptions(const TargetOptions &TargetOpts,
+ const TargetOptions &ExistingTargetOpts,
+ DiagnosticsEngine *Diags) {
+#define CHECK_TARGET_OPT(Field, Name) \
+ if (TargetOpts.Field != ExistingTargetOpts.Field) { \
+ if (Diags) \
+ Diags->Report(diag::err_pch_targetopt_mismatch) \
+ << Name << TargetOpts.Field << ExistingTargetOpts.Field; \
+ return true; \
+ }
+
+ CHECK_TARGET_OPT(Triple, "target");
+ CHECK_TARGET_OPT(CPU, "target CPU");
+ CHECK_TARGET_OPT(ABI, "target ABI");
+ CHECK_TARGET_OPT(CXXABI, "target C++ ABI");
+ CHECK_TARGET_OPT(LinkerVersion, "target linker version");
+#undef CHECK_TARGET_OPT
+
+ // Compare feature sets.
+ SmallVector<StringRef, 4> ExistingFeatures(
+ ExistingTargetOpts.FeaturesAsWritten.begin(),
+ ExistingTargetOpts.FeaturesAsWritten.end());
+ SmallVector<StringRef, 4> ReadFeatures(TargetOpts.FeaturesAsWritten.begin(),
+ TargetOpts.FeaturesAsWritten.end());
+ std::sort(ExistingFeatures.begin(), ExistingFeatures.end());
+ std::sort(ReadFeatures.begin(), ReadFeatures.end());
+
+ unsigned ExistingIdx = 0, ExistingN = ExistingFeatures.size();
+ unsigned ReadIdx = 0, ReadN = ReadFeatures.size();
+ while (ExistingIdx < ExistingN && ReadIdx < ReadN) {
+ if (ExistingFeatures[ExistingIdx] == ReadFeatures[ReadIdx]) {
+ ++ExistingIdx;
+ ++ReadIdx;
+ continue;
+ }
-namespace {
- struct EmptyStringRef {
- bool operator ()(StringRef r) const { return r.empty(); }
- };
- struct EmptyBlock {
- bool operator ()(const PCHPredefinesBlock &r) const {return r.Data.empty();}
- };
-}
+ if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
+ return true;
+ }
-static bool EqualConcatenations(SmallVector<StringRef, 2> 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)
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
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<FileID, StringRef::size_type>
-FindMacro(const PCHPredefinesBlocks &Buffers, StringRef MacroDef) {
- std::pair<FileID, StringRef::size_type> 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;
- }
+ if (ExistingIdx < ExistingN) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << true << ExistingFeatures[ExistingIdx];
+ return true;
}
- return Res;
-}
-
-bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
- StringRef OriginalFileName,
- std::string &SuggestedPredefines,
- FileManager &FileMgr) {
- // 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<StringRef,StringRef> Split =
- StringRef(PP.getPredefines()).split(PCHInclude.str());
- StringRef Left = Split.first, Right = Split.second;
- if (Left == PP.getPredefines()) {
- Error("Missing PCH include entry!");
+
+ if (ReadIdx < ReadN) {
+ if (Diags)
+ Diags->Report(diag::err_pch_targetopt_feature_mismatch)
+ << false << ReadFeatures[ReadIdx];
return true;
}
- // If the concatenation of all the PCH buffers is equal to the adjusted
- // command line, we're done.
- SmallVector<StringRef, 2> CommandLine;
- CommandLine.push_back(Left);
- CommandLine.push_back(Right);
- if (EqualConcatenations(CommandLine, Buffers))
- return false;
+ 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<StringRef, 8> PCHLines;
- for (unsigned I = 0, N = Buffers.size(); I != N; ++I)
- Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-
- SmallVector<StringRef, 8> 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<StringRef, 8> 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<StringRef> 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 ")) {
- Reader.Diag(diag::warn_pch_compiler_options_mismatch);
- return true;
- }
+bool
+PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ const LangOptions &ExistingLangOpts = PP.getLangOpts();
+ return checkLanguageOptions(LangOpts, ExistingLangOpts,
+ Complain? &Reader.Diags : 0);
+}
- // 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<StringRef, 8>::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;
- }
+bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
+ return checkTargetOptions(TargetOpts, ExistingTargetOpts,
+ Complain? &Reader.Diags : 0);
+}
- assert(ConflictPos->size() > MacroDefLen &&
- "Invalid #define in predefines buffer?");
- if ((*ConflictPos)[MacroDefLen] != ' ' &&
- (*ConflictPos)[MacroDefLen] != '(')
- continue; // Longer macro name; keep trying.
+namespace {
+ typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
+ MacroDefinitionsMap;
+}
- // We found a conflicting macro definition.
- break;
- }
+/// \brief Collect the macro definitions provided by the given preprocessor
+/// options.
+static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
+ MacroDefinitionsMap &Macros,
+ SmallVectorImpl<StringRef> *MacroNames = 0){
+ for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
+ StringRef Macro = PPOpts.Macros[I].first;
+ bool IsUndef = PPOpts.Macros[I].second;
- if (ConflictPos != CmdLineLines.end()) {
- Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
- << MacroName;
+ std::pair<StringRef, StringRef> MacroPair = Macro.split('=');
+ StringRef MacroName = MacroPair.first;
+ StringRef MacroBody = MacroPair.second;
- // Show the definition of this macro within the PCH file.
- std::pair<FileID, StringRef::size_type> 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;
+ // For an #undef'd macro, we only care about the name.
+ if (IsUndef) {
+ if (MacroNames && !Macros.count(MacroName))
+ MacroNames->push_back(MacroName);
- ConflictingDefines = true;
+ Macros[MacroName] = std::make_pair("", 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) {
- Reader.Diag(diag::warn_cmdline_missing_macro_defs);
- MissingDefines = true;
+ // For a #define'd macro, figure out the actual definition.
+ if (MacroName.size() == Macro.size())
+ MacroBody = "1";
+ else {
+ // Note: GCC drops anything following an end-of-line character.
+ StringRef::size_type End = MacroBody.find_first_of("\n\r");
+ MacroBody = MacroBody.substr(0, End);
}
- // Show the definition of this macro within the PCH file.
- std::pair<FileID, StringRef::size_type> 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 (MacroNames && !Macros.count(MacroName))
+ MacroNames->push_back(MacroName);
+ Macros[MacroName] = std::make_pair(MacroBody, false);
}
+}
+
+/// \brief Check the preprocessor options deserialized from the control block
+/// against the preprocessor options in an existing preprocessor.
+///
+/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ const PreprocessorOptions &ExistingPPOpts,
+ DiagnosticsEngine *Diags,
+ FileManager &FileMgr,
+ std::string &SuggestedPredefines) {
+ // Check macro definitions.
+ MacroDefinitionsMap ASTFileMacros;
+ collectMacroDefinitions(PPOpts, ASTFileMacros);
+ MacroDefinitionsMap ExistingMacros;
+ SmallVector<StringRef, 4> ExistingMacroNames;
+ collectMacroDefinitions(ExistingPPOpts, ExistingMacros, &ExistingMacroNames);
+
+ for (unsigned I = 0, N = ExistingMacroNames.size(); I != N; ++I) {
+ // Dig out the macro definition in the existing preprocessor options.
+ StringRef MacroName = ExistingMacroNames[I];
+ std::pair<StringRef, bool> Existing = ExistingMacros[MacroName];
+
+ // Check whether we know anything about this macro name or not.
+ llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
+ = ASTFileMacros.find(MacroName);
+ if (Known == ASTFileMacros.end()) {
+ // FIXME: Check whether this identifier was referenced anywhere in the
+ // AST file. If so, we should reject the AST file. Unfortunately, this
+ // information isn't in the control block. What shall we do about it?
+
+ if (Existing.second) {
+ SuggestedPredefines += "#undef ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += '\n';
+ } else {
+ SuggestedPredefines += "#define ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += ' ';
+ SuggestedPredefines += Existing.first.str();
+ SuggestedPredefines += '\n';
+ }
+ continue;
+ }
- 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<StringRef> 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 ")) {
- Reader.Diag(diag::warn_pch_compiler_options_mismatch);
+ // If the macro was defined in one but undef'd in the other, we have a
+ // conflict.
+ if (Existing.second != Known->second.second) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_undef)
+ << MacroName << Known->second.second;
+ }
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)) {
- Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
- return true;
+ // If the macro was #undef'd in both, or if the macro bodies are identical,
+ // it's fine.
+ if (Existing.second || Existing.first == Known->second.first)
+ continue;
+
+ // The macro bodies differ; complain.
+ if (Diags) {
+ Diags->Report(diag::err_pch_macro_def_conflict)
+ << MacroName << Known->second.first << Existing.first;
}
+ return true;
+ }
- // Add this definition to the suggested predefines buffer.
- SuggestedPredefines += Extra;
- SuggestedPredefines += '\n';
+ // Check whether we're using predefines.
+ if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {
+ if (Diags) {
+ Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
+ }
+ return true;
+ }
+
+ // Compute the #include and #include_macros lines we need.
+ for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.Includes[I];
+ if (File == ExistingPPOpts.ImplicitPCHInclude)
+ continue;
+
+ if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
+ != PPOpts.Includes.end())
+ continue;
+
+ SuggestedPredefines += "#include \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n";
+ }
+
+ for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.MacroIncludes[I];
+ if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
+ File)
+ != PPOpts.MacroIncludes.end())
+ continue;
+
+ SuggestedPredefines += "#__include_macros \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n##\n";
}
- // If we get here, it's because the predefines buffer had compatible
- // contents. Accept the PCH file.
return false;
}
+bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
+
+ return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
+ Complain? &Reader.Diags : 0,
+ PP.getFileManager(),
+ SuggestedPredefines);
+}
+
void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI,
unsigned ID) {
PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID);
++NumHeaderInfos;
}
-void PCHValidator::ReadCounter(unsigned Value) {
+void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
PP.setCounterValue(Value);
}
@@ -527,6 +483,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
return II;
}
+ unsigned ObjCOrBuiltinID = ReadUnalignedLE16(d);
unsigned Bits = ReadUnalignedLE16(d);
bool CPlusPlusOperatorKeyword = Bits & 0x01;
Bits >>= 1;
@@ -536,13 +493,11 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
Bits >>= 1;
bool ExtensionToken = Bits & 0x01;
Bits >>= 1;
- bool hasMacroDefinition = Bits & 0x01;
+ bool hadMacroDefinition = Bits & 0x01;
Bits >>= 1;
- unsigned ObjCOrBuiltinID = Bits & 0x7FF;
- Bits >>= 11;
assert(Bits == 0 && "Extra bits in the identifier?");
- DataLen -= 6;
+ DataLen -= 8;
// Build the IdentifierInfo itself and link the identifier ID with
// the new IdentifierInfo.
@@ -570,31 +525,14 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
// If this identifier is a macro, deserialize the macro
// definition.
- if (hasMacroDefinition) {
- // FIXME: Check for conflicts?
- uint32_t Offset = ReadUnalignedLE32(d);
- unsigned LocalSubmoduleID = ReadUnalignedLE32(d);
-
- // Determine whether this macro definition should be visible now, or
- // whether it is in a hidden submodule.
- bool Visible = true;
- if (SubmoduleID GlobalSubmoduleID
- = Reader.getGlobalSubmoduleID(F, LocalSubmoduleID)) {
- if (Module *Owner = Reader.getSubmodule(GlobalSubmoduleID)) {
- if (Owner->NameVisibility == Module::Hidden) {
- // The owning module is not visible, and this macro definition should
- // not be, either.
- Visible = false;
-
- // Note that this macro definition was hidden because its owning
- // module is not yet visible.
- Reader.HiddenNamesMap[Owner].push_back(II);
- }
- }
+ if (hadMacroDefinition) {
+ SmallVector<MacroID, 4> MacroIDs;
+ while (uint32_t LocalID = ReadUnalignedLE32(d)) {
+ MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
+ DataLen -= 4;
}
-
- Reader.setIdentifierIsMacro(II, F, Offset, Visible);
- DataLen -= 8;
+ DataLen -= 4;
+ Reader.setIdentifierIsMacro(II, MacroIDs);
}
Reader.SetIdentifierInfo(ID, II);
@@ -780,16 +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() {
- if (Listener)
- return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
- ActualOriginalFileName,
- SuggestedPredefines,
- FileMgr);
- return false;
-}
-
//===----------------------------------------------------------------------===//
// Source Manager Deserialization
//===----------------------------------------------------------------------===//
@@ -808,7 +736,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
unsigned FilenameLen = Record[Idx++];
std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
Idx += FilenameLen;
- MaybeAddSystemRootToFilename(Filename);
+ MaybeAddSystemRootToFilename(F, Filename);
FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
}
@@ -841,106 +769,8 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
return false;
}
-namespace {
-
-class ASTStatData {
-public:
- const ino_t ino;
- const dev_t dev;
- const mode_t mode;
- const time_t mtime;
- const off_t size;
-
- ASTStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
- : ino(i), dev(d), mode(mo), mtime(m), size(s) {}
-};
-
-class ASTStatLookupTrait {
- public:
- typedef const char *external_key_type;
- typedef const char *internal_key_type;
-
- typedef ASTStatData data_type;
-
- static unsigned ComputeHash(const char *path) {
- return llvm::HashString(path);
- }
-
- static internal_key_type GetInternalKey(const char *path) { return path; }
-
- static bool EqualKey(internal_key_type a, internal_key_type b) {
- return strcmp(a, b) == 0;
- }
-
- static std::pair<unsigned, unsigned>
- ReadKeyDataLength(const unsigned char*& d) {
- unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
- unsigned DataLen = (unsigned) *d++;
- return std::make_pair(KeyLen + 1, DataLen);
- }
-
- static internal_key_type ReadKey(const unsigned char *d, unsigned) {
- return (const char *)d;
- }
-
- static data_type ReadData(const internal_key_type, const unsigned char *d,
- unsigned /*DataLen*/) {
- using namespace clang::io;
-
- ino_t ino = (ino_t) ReadUnalignedLE32(d);
- dev_t dev = (dev_t) ReadUnalignedLE32(d);
- mode_t mode = (mode_t) ReadUnalignedLE16(d);
- time_t mtime = (time_t) ReadUnalignedLE64(d);
- off_t size = (off_t) ReadUnalignedLE64(d);
- return data_type(ino, dev, mode, mtime, size);
- }
-};
-
-/// \brief stat() cache for precompiled headers.
-///
-/// This cache is very similar to the stat cache used by pretokenized
-/// headers.
-class ASTStatCache : public FileSystemStatCache {
- typedef OnDiskChainedHashTable<ASTStatLookupTrait> CacheTy;
- CacheTy *Cache;
-
- unsigned &NumStatHits, &NumStatMisses;
-public:
- ASTStatCache(const unsigned char *Buckets, const unsigned char *Base,
- unsigned &NumStatHits, unsigned &NumStatMisses)
- : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
- Cache = CacheTy::Create(Buckets, Base);
- }
-
- ~ASTStatCache() { delete Cache; }
-
- LookupResult getStat(const char *Path, struct stat &StatBuf,
- int *FileDescriptor) {
- // Do the lookup for the file's data in the AST file.
- CacheTy::iterator I = Cache->find(Path);
-
- // If we don't get a hit in the AST file just forward to 'stat'.
- if (I == Cache->end()) {
- ++NumStatMisses;
- return statChained(Path, StatBuf, FileDescriptor);
- }
-
- ++NumStatHits;
- ASTStatData Data = *I;
-
- StatBuf.st_ino = Data.ino;
- StatBuf.st_dev = Data.dev;
- StatBuf.st_mtime = Data.mtime;
- StatBuf.st_mode = Data.mode;
- StatBuf.st_size = Data.size;
- return CacheExists;
- }
-};
-} // end anonymous namespace
-
-
/// \brief Read a source manager block
-ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
+bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
using namespace SrcMgr;
llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
@@ -954,13 +784,13 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
// The stream itself is going to skip over the source manager block.
if (F.Stream.SkipBlock()) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
// Enter the source manager block.
if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
Error("malformed source manager block record in AST file");
- return Failure;
+ return true;
}
RecordData Record;
@@ -969,9 +799,9 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
if (Code == llvm::bitc::END_BLOCK) {
if (SLocEntryCursor.ReadBlockEnd()) {
Error("error at end of Source Manager block in AST file");
- return Failure;
+ return true;
}
- return Success;
+ return false;
}
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
@@ -979,7 +809,7 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
SLocEntryCursor.ReadSubBlockID();
if (SLocEntryCursor.SkipBlock()) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
continue;
}
@@ -1001,7 +831,7 @@ ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
case SM_SLOC_BUFFER_ENTRY:
case SM_SLOC_EXPANSION_ENTRY:
// Once we hit one of the source location entries, we're done.
- return Success;
+ return false;
}
}
}
@@ -1039,14 +869,13 @@ resolveFileRelativeToOriginalDir(const std::string &Filename,
return currPCHPath.str();
}
-/// \brief Read in the source location entry with the given ID.
-ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
+bool ASTReader::ReadSLocEntry(int ID) {
if (ID == 0)
- return Success;
+ return false;
if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
Error("source location entry ID out-of-range for AST file");
- return Failure;
+ return true;
}
ModuleFile *F = GlobalSLocEntryMap.find(-ID)->second;
@@ -1060,7 +889,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
Code == llvm::bitc::ENTER_SUBBLOCK ||
Code == llvm::bitc::DEFINE_ABBREV) {
Error("incorrectly-formatted source location entry in AST file");
- return Failure;
+ return true;
}
RecordData Record;
@@ -1069,58 +898,18 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
default:
Error("incorrectly-formatted source location entry in AST file");
- return Failure;
+ return true;
case SM_SLOC_FILE_ENTRY: {
- if (Record.size() < 7) {
- Error("source location entry is incorrect");
- return Failure;
- }
-
// We will detect whether a file changed and return 'Failure' for it, but
// we will also try to fail gracefully by setting up the SLocEntry.
- ASTReader::ASTReadResult Result = Success;
-
- bool OverriddenBuffer = Record[6];
-
- std::string OrigFilename(BlobStart, BlobStart + BlobLen);
- std::string Filename = OrigFilename;
- MaybeAddSystemRootToFilename(Filename);
- const FileEntry *File =
- OverriddenBuffer? FileMgr.getVirtualFile(Filename, (off_t)Record[4],
- (time_t)Record[5])
- : FileMgr.getFile(Filename, /*OpenFile=*/false);
- 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]);
- if (File == 0) {
- std::string ErrorStr = "could not find file '";
- ErrorStr += Filename;
- ErrorStr += "' referenced by AST file";
- Error(ErrorStr.c_str());
- return Failure;
- }
+ unsigned InputID = Record[4];
+ InputFile IF = getInputFile(*F, InputID);
+ const FileEntry *File = IF.getPointer();
+ bool OverriddenBuffer = IF.getInt();
- if (!DisableValidation &&
- ((off_t)Record[4] != File->getSize()
-#if !defined(LLVM_ON_WIN32)
- // In our regression testing, the Windows file system seems to
- // have inconsistent modification times that sometimes
- // erroneously trigger this error-handling path.
- || (time_t)Record[5] != File->getModificationTime()
-#endif
- )) {
- Error(diag::err_fe_pch_file_modified, Filename);
- Result = Failure;
- }
+ if (!IF.getPointer())
+ return true;
SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
if (IncludeLoc.isInvalid() && F->Kind != MK_MainFile) {
@@ -1133,12 +922,12 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
ID, BaseOffset + Record[0]);
SrcMgr::FileInfo &FileInfo =
const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile());
- FileInfo.NumCreatedFIDs = Record[7];
+ FileInfo.NumCreatedFIDs = Record[5];
if (Record[3])
FileInfo.setHasLineDirectives();
- const DeclID *FirstDecl = F->FileSortedDecls + Record[8];
- unsigned NumFileDecls = Record[9];
+ const DeclID *FirstDecl = F->FileSortedDecls + Record[6];
+ unsigned NumFileDecls = Record[7];
if (NumFileDecls) {
assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
FileDeclIDs[FID] = FileDeclsInfo(F, llvm::makeArrayRef(FirstDecl,
@@ -1157,23 +946,24 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
if (RecCode != SM_SLOC_BUFFER_BLOB) {
Error("AST record has invalid code");
- return Failure;
+ return true;
}
llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
- Filename);
+ File->getName());
SourceMgr.overrideFileContents(File, Buffer);
}
- if (Result == Failure)
- return Failure;
break;
}
case SM_SLOC_BUFFER_ENTRY: {
const char *Name = BlobStart;
unsigned Offset = Record[0];
+ SrcMgr::CharacteristicKind
+ FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
+ SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
unsigned Code = SLocEntryCursor.ReadCode();
Record.clear();
unsigned RecCode
@@ -1181,23 +971,14 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
if (RecCode != SM_SLOC_BUFFER_BLOB) {
Error("AST record has invalid code");
- return Failure;
+ return true;
}
llvm::MemoryBuffer *Buffer
= llvm::MemoryBuffer::getMemBuffer(StringRef(BlobStart, BlobLen - 1),
Name);
- FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID,
- BaseOffset + Offset);
-
- if (strcmp(Name, "<built-in>") == 0 && F->Kind == MK_PCH) {
- PCHPredefinesBlock Block = {
- BufferID,
- StringRef(BlobStart, BlobLen - 1)
- };
- PCHPredefinesBuffers.push_back(Block);
- }
-
+ SourceMgr.createFileIDForMemBuffer(Buffer, FileCharacter, ID,
+ BaseOffset + Offset, IncludeLoc);
break;
}
@@ -1213,7 +994,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
}
}
- return Success;
+ return false;
}
/// \brief Find the location where the module F is imported.
@@ -1258,7 +1039,8 @@ bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
}
}
-void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
+void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
+ MacroInfo *Hint) {
llvm::BitstreamCursor &Stream = F.MacroCursor;
// Keep track of where we are in the stream, then jump back there
@@ -1270,6 +1052,24 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
SmallVector<IdentifierInfo*, 16> MacroArgs;
MacroInfo *Macro = 0;
+ // RAII object to add the loaded macro information once we're done
+ // adding tokens.
+ struct AddLoadedMacroInfoRAII {
+ Preprocessor &PP;
+ MacroInfo *Hint;
+ MacroInfo *MI;
+ IdentifierInfo *II;
+
+ AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)
+ : PP(PP), Hint(Hint), MI(), II() { }
+ ~AddLoadedMacroInfoRAII( ) {
+ if (MI) {
+ // Finally, install the macro.
+ PP.addLoadedMacroInfo(II, MI, Hint);
+ }
+ }
+ } AddLoadedMacroInfo(PP, Hint);
+
while (true) {
unsigned Code = Stream.ReadCode();
switch (Code) {
@@ -1312,18 +1112,31 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
Error("macro must have a name in AST file");
return;
}
-
- SourceLocation Loc = ReadSourceLocation(F, Record[1]);
- bool isUsed = Record[2];
+ unsigned GlobalID = getGlobalMacroID(F, Record[1]);
+
+ // If this macro has already been loaded, don't do so again.
+ if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
+ return;
+
+ SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
+ unsigned NextIndex = 3;
+ SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
MacroInfo *MI = PP.AllocateMacroInfo(Loc);
- MI->setIsUsed(isUsed);
+
+ // Record this macro.
+ MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS] = MI;
+
+ SourceLocation UndefLoc = ReadSourceLocation(F, Record, NextIndex);
+ if (UndefLoc.isValid())
+ MI->setUndefLoc(UndefLoc);
+
+ MI->setIsUsed(Record[NextIndex++]);
MI->setIsFromAST();
- bool IsPublic = Record[3];
- unsigned NextIndex = 4;
+ bool IsPublic = Record[NextIndex++];
MI->setVisibility(IsPublic, ReadSourceLocation(F, Record, NextIndex));
-
+
if (RecType == PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
bool isC99VarArgs = Record[NextIndex++];
@@ -1341,8 +1154,60 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
PP.getPreprocessorAllocator());
}
- // Finally, install the macro.
- PP.setMacroInfo(II, MI, /*LoadedFromAST=*/true);
+ if (DeserializationListener)
+ DeserializationListener->MacroRead(GlobalID, MI);
+
+ // If an update record marked this as undefined, do so now.
+ // FIXME: Only if the submodule this update came from is visible?
+ MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
+ if (Update != MacroUpdates.end()) {
+ if (MI->getUndefLoc().isInvalid()) {
+ for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
+ bool Hidden = false;
+ if (unsigned SubmoduleID = Update->second[I].first) {
+ if (Module *Owner = getSubmodule(SubmoduleID)) {
+ if (Owner->NameVisibility == Module::Hidden) {
+ // Note that this #undef is hidden.
+ Hidden = true;
+
+ // Record this hiding for later.
+ HiddenNamesMap[Owner].push_back(
+ HiddenName(II, MI, Update->second[I].second.UndefLoc));
+ }
+ }
+ }
+
+ if (!Hidden) {
+ MI->setUndefLoc(Update->second[I].second.UndefLoc);
+ if (PPMutationListener *Listener = PP.getPPMutationListener())
+ Listener->UndefinedMacro(MI);
+ break;
+ }
+ }
+ }
+ MacroUpdates.erase(Update);
+ }
+
+ // Determine whether this macro definition is visible.
+ bool Hidden = !MI->isPublic();
+ if (!Hidden && GlobalSubmoduleID) {
+ if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
+ if (Owner->NameVisibility == Module::Hidden) {
+ // The owning module is not visible, and this macro definition
+ // should not be, either.
+ Hidden = true;
+
+ // Note that this macro definition was hidden because its owning
+ // module is not yet visible.
+ HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
+ }
+ }
+ }
+ MI->setHidden(Hidden);
+
+ // Make sure we install the macro once we're done.
+ AddLoadedMacroInfo.MI = MI;
+ AddLoadedMacroInfo.II = II;
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
@@ -1451,18 +1316,16 @@ HeaderFileInfoTrait::ReadData(const internal_key_type, const unsigned char *d,
return HFI;
}
-void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ModuleFile &F,
- uint64_t LocalOffset, bool Visible) {
- if (Visible) {
- // Note that this identifier has a macro definition.
- II->setHasMacroDefinition(true);
- }
-
- // Adjust the offset to a global offset.
- UnreadMacroRecordOffsets[II] = F.GlobalBitOffset + LocalOffset;
+void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
+ II->setHadMacroDefinition(true);
+ assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
+ PendingMacroIDs[II].append(IDs.begin(), IDs.end());
}
void ASTReader::ReadDefinedMacros() {
+ // Note that we are loading defined macros.
+ Deserializing Macros(this);
+
for (ModuleReverseIterator I = ModuleMgr.rbegin(),
E = ModuleMgr.rend(); I != E; ++I) {
llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
@@ -1514,26 +1377,6 @@ void ASTReader::ReadDefinedMacros() {
}
}
}
-
- // Drain the unread macro-record offsets map.
- while (!UnreadMacroRecordOffsets.empty())
- LoadMacroDefinition(UnreadMacroRecordOffsets.begin());
-}
-
-void ASTReader::LoadMacroDefinition(
- llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos) {
- assert(Pos != UnreadMacroRecordOffsets.end() && "Unknown macro definition");
- uint64_t Offset = Pos->second;
- UnreadMacroRecordOffsets.erase(Pos);
-
- RecordLocation Loc = getLocalBitOffset(Offset);
- ReadMacroRecord(*Loc.F, Loc.Offset);
-}
-
-void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
- llvm::DenseMap<IdentifierInfo *, uint64_t>::iterator Pos
- = UnreadMacroRecordOffsets.find(II);
- LoadMacroDefinition(Pos);
}
namespace {
@@ -1582,6 +1425,9 @@ namespace {
}
void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
unsigned PriorGeneration = 0;
if (getContext().getLangOpts().Modules)
PriorGeneration = IdentifierGeneration[&II];
@@ -1602,14 +1448,132 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
IdentifierGeneration[II] = CurrentGeneration;
}
+llvm::PointerIntPair<const FileEntry *, 1, bool>
+ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
+ // If this ID is bogus, just return an empty input file.
+ if (ID == 0 || ID > F.InputFilesLoaded.size())
+ return InputFile();
+
+ // If we've already loaded this input file, return it.
+ if (F.InputFilesLoaded[ID-1].getPointer())
+ return F.InputFilesLoaded[ID-1];
+
+ // Go find this input file.
+ llvm::BitstreamCursor &Cursor = F.InputFilesCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
+
+ unsigned Code = Cursor.ReadCode();
+ RecordData Record;
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((InputFileRecordTypes)Cursor.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ case INPUT_FILE: {
+ unsigned StoredID = Record[0];
+ assert(ID == StoredID && "Bogus stored ID or offset");
+ (void)StoredID;
+ off_t StoredSize = (off_t)Record[1];
+ time_t StoredTime = (time_t)Record[2];
+ bool Overridden = (bool)Record[3];
+
+ // Get the file entry for this input file.
+ StringRef OrigFilename(BlobStart, BlobLen);
+ std::string Filename = OrigFilename;
+ MaybeAddSystemRootToFilename(F, Filename);
+ const FileEntry *File
+ = Overridden? FileMgr.getVirtualFile(Filename, StoredSize, StoredTime)
+ : FileMgr.getFile(Filename, /*OpenFile=*/false);
+
+ // If we didn't find the file, resolve it relative to the
+ // original directory from which this AST file was created.
+ if (File == 0 && !F.OriginalDir.empty() && !CurrentDir.empty() &&
+ F.OriginalDir != CurrentDir) {
+ std::string Resolved = resolveFileRelativeToOriginalDir(Filename,
+ F.OriginalDir,
+ CurrentDir);
+ if (!Resolved.empty())
+ File = FileMgr.getFile(Resolved);
+ }
+
+ // For an overridden file, create a virtual file with the stored
+ // size/timestamp.
+ if (Overridden && File == 0) {
+ File = FileMgr.getVirtualFile(Filename, StoredSize, StoredTime);
+ }
+
+ if (File == 0) {
+ if (Complain) {
+ std::string ErrorStr = "could not find file '";
+ ErrorStr += Filename;
+ ErrorStr += "' referenced by AST file";
+ Error(ErrorStr.c_str());
+ }
+ return InputFile();
+ }
+
+ // Note that we've loaded this input file.
+ F.InputFilesLoaded[ID-1] = InputFile(File, Overridden);
+
+ // Check if there was a request to override the contents of the file
+ // that was part of the precompiled header. Overridding such a file
+ // can lead to problems when lexing using the source locations from the
+ // PCH.
+ SourceManager &SM = getSourceManager();
+ if (!Overridden && SM.isFileOverridden(File)) {
+ Error(diag::err_fe_pch_file_overridden, Filename);
+ // After emitting the diagnostic, recover by disabling the override so
+ // that the original file will be used.
+ SM.disableFileContentsOverride(File);
+ // The FileEntry is a virtual file entry with the size of the contents
+ // that would override the original contents. Set it to the original's
+ // size/time.
+ FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
+ StoredSize, StoredTime);
+ }
+
+ // For an overridden file, there is nothing to validate.
+ if (Overridden)
+ return InputFile(File, Overridden);
+
+ // The stat info from the FileEntry came from the cached stat
+ // info of the PCH, so we cannot trust it.
+ struct stat StatBuf;
+ if (::stat(File->getName(), &StatBuf) != 0) {
+ StatBuf.st_size = File->getSize();
+ StatBuf.st_mtime = File->getModificationTime();
+ }
+
+ if ((StoredSize != StatBuf.st_size
+#if !defined(LLVM_ON_WIN32)
+ // In our regression testing, the Windows file system seems to
+ // have inconsistent modification times that sometimes
+ // erroneously trigger this error-handling path.
+ || StoredTime != StatBuf.st_mtime
+#endif
+ )) {
+ if (Complain)
+ Error(diag::err_fe_pch_file_modified, Filename);
+
+ return InputFile();
+ }
+
+ return InputFile(File, Overridden);
+ }
+ }
+
+ return InputFile();
+}
+
const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
+ ModuleFile &M = ModuleMgr.getPrimaryModule();
std::string Filename = filenameStrRef;
- MaybeAddSystemRootToFilename(Filename);
+ MaybeAddSystemRootToFilename(M, Filename);
const FileEntry *File = FileMgr.getFile(Filename);
- if (File == 0 && !OriginalDir.empty() && !CurrentDir.empty() &&
- OriginalDir != CurrentDir) {
+ if (File == 0 && !M.OriginalDir.empty() && !CurrentDir.empty() &&
+ M.OriginalDir != CurrentDir) {
std::string resolved = resolveFileRelativeToOriginalDir(Filename,
- OriginalDir,
+ M.OriginalDir,
CurrentDir);
if (!resolved.empty())
File = FileMgr.getFile(resolved);
@@ -1621,9 +1585,10 @@ const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
/// \brief If we are loading a relocatable PCH file, and the filename is
/// not an absolute path, add the system root to the beginning of the file
/// name.
-void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) {
+void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
+ std::string &Filename) {
// If this is not a relocatable PCH file, there's nothing to do.
- if (!RelocatablePCH)
+ if (!M.RelocatablePCH)
return;
if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
@@ -1643,29 +1608,226 @@ void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) {
}
ASTReader::ASTReadResult
-ASTReader::ReadASTBlock(ModuleFile &F) {
+ASTReader::ReadControlBlock(ModuleFile &F,
+ llvm::SmallVectorImpl<ModuleFile *> &Loaded,
+ unsigned ClientLoadCapabilities) {
llvm::BitstreamCursor &Stream = F.Stream;
- if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
Error("malformed block record in AST file");
return Failure;
}
- // Read all of the records and blocks for the ASt file.
+ // Read all of the records and blocks in the control block.
RecordData Record;
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
if (Stream.ReadBlockEnd()) {
- Error("error at end of module block in AST file");
+ Error("error at end of control block in AST file");
return Failure;
}
+ // Validate all of the input files.
+ if (!DisableValidation) {
+ bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
+ for (unsigned I = 0, N = Record[0]; I < N; ++I)
+ if (!getInputFile(F, I+1, Complain).getPointer())
+ return OutOfDate;
+ }
+
return Success;
}
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
switch (Stream.ReadSubBlockID()) {
+ case INPUT_FILES_BLOCK_ID:
+ F.InputFilesCursor = Stream;
+ if (Stream.SkipBlock() || // Skip with the main cursor
+ // Read the abbreviations
+ ReadBlockAbbrevs(F.InputFilesCursor, INPUT_FILES_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ continue;
+
+ default:
+ if (!Stream.SkipBlock())
+ continue;
+ break;
+ }
+
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read and process a record.
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ switch ((ControlRecordTypes)Stream.ReadRecord(Code, Record,
+ &BlobStart, &BlobLen)) {
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return VersionMismatch;
+ }
+
+ bool hasErrors = Record[5];
+ if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
+ Diag(diag::err_pch_with_compiler_errors);
+ return HadErrors;
+ }
+
+ F.RelocatablePCH = Record[4];
+
+ const std::string &CurBranch = getClangFullRepositoryVersion();
+ StringRef ASTBranch(BlobStart, BlobLen);
+ if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+ if ((ClientLoadCapabilities & ARR_VersionMismatch) == 0)
+ Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
+ return VersionMismatch;
+ }
+ break;
+ }
+
+ case IMPORTS: {
+ // Load each of the imported PCH files.
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ // Read information about the AST file.
+ ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
+ unsigned Length = Record[Idx++];
+ SmallString<128> ImportedFile(Record.begin() + Idx,
+ Record.begin() + Idx + Length);
+ Idx += Length;
+
+ // Load the AST file.
+ switch(ReadASTCore(ImportedFile, ImportedKind, &F, Loaded,
+ ClientLoadCapabilities)) {
+ case Failure: return Failure;
+ // If we have to ignore the dependency, we'll have to ignore this too.
+ case OutOfDate: return OutOfDate;
+ case VersionMismatch: return VersionMismatch;
+ case ConfigurationMismatch: return ConfigurationMismatch;
+ case HadErrors: return HadErrors;
+ case Success: break;
+ }
+ }
+ break;
+ }
+
+ case LANGUAGE_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseLanguageOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case TARGET_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseTargetOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case DIAGNOSTIC_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseDiagnosticOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case FILE_SYSTEM_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseFileSystemOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case HEADER_SEARCH_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParseHeaderSearchOptions(Record, Complain, *Listener) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case PREPROCESSOR_OPTIONS: {
+ bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
+ if (Listener && &F == *ModuleMgr.begin() &&
+ ParsePreprocessorOptions(Record, Complain, *Listener,
+ SuggestedPredefines) &&
+ !DisableValidation)
+ return ConfigurationMismatch;
+ break;
+ }
+
+ case ORIGINAL_FILE:
+ F.OriginalSourceFileID = FileID::get(Record[0]);
+ F.ActualOriginalSourceFileName.assign(BlobStart, BlobLen);
+ F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
+ MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
+ break;
+
+ case ORIGINAL_PCH_DIR:
+ F.OriginalDir.assign(BlobStart, BlobLen);
+ break;
+
+ case INPUT_FILE_OFFSETS:
+ F.InputFileOffsets = (const uint32_t *)BlobStart;
+ F.InputFilesLoaded.resize(Record[0]);
+ break;
+ }
+ }
+
+ Error("premature end of bitstream in AST file");
+ return Failure;
+}
+
+bool ASTReader::ReadASTBlock(ModuleFile &F) {
+ llvm::BitstreamCursor &Stream = F.Stream;
+
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Error("malformed block record in AST file");
+ return true;
+ }
+
+ // Read all of the records and blocks for the AST file.
+ RecordData Record;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ Error("error at end of module block in AST file");
+ return true;
+ }
+
+ DeclContext *DC = Context.getTranslationUnitDecl();
+ if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage())
+ DC->setMustBuildLookupTable();
+
+ return false;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ switch (Stream.ReadSubBlockID()) {
case DECLTYPES_BLOCK_ID:
// We lazily load the decls block, but we want to set up the
// DeclsCursor cursor to point into it. Clone our current bitcode
@@ -1676,14 +1838,14 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
// Read the abbrevs.
ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
break;
case DECL_UPDATES_BLOCK_ID:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
break;
@@ -1695,7 +1857,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
@@ -1706,7 +1868,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
ReadBlockAbbrevs(F.PreprocessorDetailCursor,
PREPROCESSOR_DETAIL_BLOCK_ID)) {
Error("malformed preprocessor detail record in AST file");
- return Failure;
+ return true;
}
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
@@ -1718,31 +1880,13 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
break;
case SOURCE_MANAGER_BLOCK_ID:
- switch (ReadSourceManagerBlock(F)) {
- case Success:
- break;
-
- case Failure:
- Error("malformed source manager block in AST file");
- return Failure;
-
- case IgnorePCH:
- return IgnorePCH;
- }
+ if (ReadSourceManagerBlock(F))
+ return true;
break;
case SUBMODULE_BLOCK_ID:
- switch (ReadSubmoduleBlock(F)) {
- case Success:
- break;
-
- case Failure:
- Error("malformed submodule block in AST file");
- return Failure;
-
- case IgnorePCH:
- return IgnorePCH;
- }
+ if (ReadSubmoduleBlock(F))
+ return true;
break;
case COMMENTS_BLOCK_ID: {
@@ -1750,7 +1894,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
Error("malformed comments block in AST file");
- return Failure;
+ return true;
}
CommentsCursors.push_back(std::make_pair(C, &F));
break;
@@ -1760,7 +1904,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
if (!Stream.SkipBlock())
break;
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
continue;
}
@@ -1779,54 +1923,10 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
default: // Default behavior: ignore.
break;
- case METADATA: {
- if (Record[0] != VERSION_MAJOR && !DisableValidation) {
- Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
- : diag::warn_pch_version_too_new);
- return IgnorePCH;
- }
-
- bool hasErrors = Record[5];
- if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
- Diag(diag::err_pch_with_compiler_errors);
- return IgnorePCH;
- }
-
- RelocatablePCH = Record[4];
- if (Listener) {
- std::string TargetTriple(BlobStart, BlobLen);
- if (Listener->ReadTargetTriple(TargetTriple))
- return IgnorePCH;
- }
- break;
- }
-
- case IMPORTS: {
- // Load each of the imported PCH files.
- unsigned Idx = 0, N = Record.size();
- while (Idx < N) {
- // Read information about the AST file.
- ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
- unsigned Length = Record[Idx++];
- SmallString<128> ImportedFile(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- Idx += Length;
-
- // Load the AST file.
- switch(ReadASTCore(ImportedFile, ImportedKind, &F)) {
- case Failure: return Failure;
- // If we have to ignore the dependency, we'll have to ignore this too.
- case IgnorePCH: return IgnorePCH;
- case Success: break;
- }
- }
- break;
- }
-
case TYPE_OFFSET: {
if (F.LocalNumTypes != 0) {
Error("duplicate TYPE_OFFSET record in AST file");
- return Failure;
+ return true;
}
F.TypeOffsets = (const uint32_t *)BlobStart;
F.LocalNumTypes = Record[0];
@@ -1850,7 +1950,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case DECL_OFFSET: {
if (F.LocalNumDecls != 0) {
Error("duplicate DECL_OFFSET record in AST file");
- return Failure;
+ return true;
}
F.DeclOffsets = (const DeclOffset *)BlobStart;
F.LocalNumDecls = Record[0];
@@ -1904,11 +2004,6 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
break;
}
- case LANGUAGE_OPTIONS:
- if (ParseLanguageOptions(Record) && !DisableValidation)
- return IgnorePCH;
- break;
-
case IDENTIFIER_TABLE:
F.IdentifierTableData = BlobStart;
if (Record[0]) {
@@ -1925,7 +2020,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case IDENTIFIER_OFFSET: {
if (F.LocalNumIdentifiers != 0) {
Error("duplicate IDENTIFIER_OFFSET record in AST file");
- return Failure;
+ return true;
}
F.IdentifierOffsets = (const uint32_t *)BlobStart;
F.LocalNumIdentifiers = Record[0];
@@ -1949,7 +2044,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
}
break;
}
-
+
case EXTERNAL_DEFINITIONS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
ExternalDefinitions.push_back(getGlobalDeclID(F, Record[I]));
@@ -1980,7 +2075,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case WEAK_UNDECLARED_IDENTIFIERS:
if (Record.size() % 4 != 0) {
Error("invalid weak identifiers record");
- return Failure;
+ return true;
}
// FIXME: Ignore weak undeclared identifiers from non-original PCH
@@ -2050,11 +2145,12 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case PP_COUNTER_VALUE:
if (!Record.empty() && Listener)
- Listener->ReadCounter(Record[0]);
+ Listener->ReadCounter(F, Record[0]);
break;
case FILE_SORTED_DECLS:
F.FileSortedDecls = (const DeclID *)BlobStart;
+ F.NumFileSortedDecls = Record[0];
break;
case SOURCE_LOCATION_OFFSETS: {
@@ -2098,7 +2194,9 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
ContinuousRangeMap<uint32_t, int, 2>::Builder
IdentifierRemap(F.IdentifierRemap);
- ContinuousRangeMap<uint32_t, int, 2>::Builder
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
+ MacroRemap(F.MacroRemap);
+ ContinuousRangeMap<uint32_t, int, 2>::Builder
PreprocessedEntityRemap(F.PreprocessedEntityRemap);
ContinuousRangeMap<uint32_t, int, 2>::Builder
SubmoduleRemap(F.SubmoduleRemap);
@@ -2114,11 +2212,12 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
ModuleFile *OM = ModuleMgr.lookup(Name);
if (!OM) {
Error("SourceLocation remap refers to unknown module");
- return Failure;
+ return true;
}
uint32_t SLocOffset = io::ReadUnalignedLE32(Data);
uint32_t IdentifierIDOffset = io::ReadUnalignedLE32(Data);
+ uint32_t MacroIDOffset = io::ReadUnalignedLE32(Data);
uint32_t PreprocessedEntityIDOffset = io::ReadUnalignedLE32(Data);
uint32_t SubmoduleIDOffset = io::ReadUnalignedLE32(Data);
uint32_t SelectorIDOffset = io::ReadUnalignedLE32(Data);
@@ -2131,6 +2230,8 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
IdentifierRemap.insert(
std::make_pair(IdentifierIDOffset,
OM->BaseIdentifierID - IdentifierIDOffset));
+ MacroRemap.insert(std::make_pair(MacroIDOffset,
+ OM->BaseMacroID - MacroIDOffset));
PreprocessedEntityRemap.insert(
std::make_pair(PreprocessedEntityIDOffset,
OM->BasePreprocessedEntityID - PreprocessedEntityIDOffset));
@@ -2152,12 +2253,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case SOURCE_MANAGER_LINE_TABLE:
if (ParseLineTable(F, Record))
- return Failure;
- break;
-
- case FILE_SOURCE_LOCATION_OFFSETS:
- F.SLocFileOffsets = (const uint32_t *)BlobStart;
- F.LocalNumSLocFileEntries = Record[0];
+ return true;
break;
case SOURCE_LOCATION_PRELOADS: {
@@ -2165,25 +2261,13 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
// which is based off F.SLocEntryBaseID.
if (!F.PreloadSLocEntries.empty()) {
Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
- return Failure;
+ return true;
}
F.PreloadSLocEntries.swap(Record);
break;
}
- case STAT_CACHE: {
- if (!DisableStatCache) {
- ASTStatCache *MyStatCache =
- new ASTStatCache((const unsigned char *)BlobStart + Record[0],
- (const unsigned char *)BlobStart,
- NumStatHits, NumStatMisses);
- FileMgr.addStatCache(MyStatCache);
- F.StatCache = MyStatCache;
- }
- break;
- }
-
case EXT_VECTOR_DECLS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
ExtVectorDecls.push_back(getGlobalDeclID(F, Record[I]));
@@ -2192,7 +2276,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case VTABLE_USES:
if (Record.size() % 3 != 0) {
Error("Invalid VTABLE_USES record");
- return Failure;
+ return true;
}
// Later tables overwrite earlier ones.
@@ -2215,13 +2299,15 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
+ Error("Invalid existing PendingInstantiations");
+ return true;
+ }
+
+ if (Record.size() % 2 != 0) {
Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
- return Failure;
+ return true;
}
-
- // Later lists of pending instantiations overwrite earlier ones.
- // FIXME: This is most certainly wrong for modules.
- PendingInstantiations.clear();
+
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
PendingInstantiations.push_back(
@@ -2237,34 +2323,6 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
break;
- case ORIGINAL_FILE_NAME:
- // The primary AST will be the last to get here, so it will be the one
- // that's used.
- ActualOriginalFileName.assign(BlobStart, BlobLen);
- OriginalFileName = ActualOriginalFileName;
- MaybeAddSystemRootToFilename(OriginalFileName);
- break;
-
- case ORIGINAL_FILE_ID:
- OriginalFileID = FileID::get(Record[0]);
- 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();
- StringRef ASTBranch(BlobStart, BlobLen);
- if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
- Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
- return IgnorePCH;
- }
- break;
- }
-
case PPD_ENTITIES_OFFSETS: {
F.PreprocessedEntityOffsets = (const PPEntityOffset *)BlobStart;
assert(BlobLen % sizeof(PPEntityOffset) == 0);
@@ -2300,7 +2358,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case DECL_UPDATE_OFFSETS: {
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
- return Failure;
+ return true;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 2)
DeclUpdateOffsets[getGlobalDeclID(F, Record[I])]
@@ -2311,7 +2369,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case DECL_REPLACEMENTS: {
if (Record.size() % 3 != 0) {
Error("invalid DECL_REPLACEMENTS block in AST file");
- return Failure;
+ return true;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 3)
ReplacedDecls[getGlobalDeclID(F, Record[I])]
@@ -2322,7 +2380,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case OBJC_CATEGORIES_MAP: {
if (F.LocalNumObjCCategoriesInMap != 0) {
Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
- return Failure;
+ return true;
}
F.LocalNumObjCCategoriesInMap = Record[0];
@@ -2337,7 +2395,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case CXX_BASE_SPECIFIER_OFFSETS: {
if (F.LocalNumCXXBaseSpecifiers != 0) {
Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
- return Failure;
+ return true;
}
F.LocalNumCXXBaseSpecifiers = Record[0];
@@ -2347,11 +2405,6 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
}
case DIAG_PRAGMA_MAPPINGS:
- if (Record.size() % 2 != 0) {
- Error("invalid DIAG_USER_MAPPINGS block in AST file");
- return Failure;
- }
-
if (F.PragmaDiagMappings.empty())
F.PragmaDiagMappings.swap(Record);
else
@@ -2428,7 +2481,7 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case LOCAL_REDECLARATIONS_MAP: {
if (F.LocalNumRedeclarationsInMap != 0) {
Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
- return Failure;
+ return true;
}
F.LocalNumRedeclarationsInMap = Record[0];
@@ -2445,113 +2498,77 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
}
break;
}
- }
- }
- Error("premature end of bitstream in AST file");
- return Failure;
-}
-
-ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) {
- llvm::BitstreamCursor &SLocEntryCursor = M.SLocEntryCursor;
-
- for (unsigned i = 0, e = M.LocalNumSLocFileEntries; i != e; ++i) {
- SLocEntryCursor.JumpToBit(M.SLocFileOffsets[i]);
- unsigned Code = SLocEntryCursor.ReadCode();
- if (Code == llvm::bitc::END_BLOCK ||
- Code == llvm::bitc::ENTER_SUBBLOCK ||
- Code == llvm::bitc::DEFINE_ABBREV) {
- Error("incorrectly-formatted source location entry in AST file");
- return Failure;
- }
- RecordData Record;
- const char *BlobStart;
- unsigned BlobLen;
- switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
- default:
- Error("incorrectly-formatted source location entry in AST file");
- return Failure;
+ case MACRO_OFFSET: {
+ if (F.LocalNumMacros != 0) {
+ Error("duplicate MACRO_OFFSET record in AST file");
+ return true;
+ }
+ F.MacroOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumMacros = Record[0];
+ unsigned LocalBaseMacroID = Record[1];
+ F.BaseMacroID = getTotalNumMacros();
- case SM_SLOC_FILE_ENTRY: {
- // If the buffer was overridden, the file need not exist.
- if (Record[6])
- break;
-
- StringRef Filename(BlobStart, BlobLen);
- const FileEntry *File = getFileEntry(Filename);
+ if (F.LocalNumMacros > 0) {
+ // Introduce the global -> local mapping for macros within this module.
+ GlobalMacroMap.insert(std::make_pair(getTotalNumMacros() + 1, &F));
- if (File == 0) {
- std::string ErrorStr = "could not find file '";
- ErrorStr += Filename;
- ErrorStr += "' referenced by AST file";
- Error(ErrorStr.c_str());
- return IgnorePCH;
- }
+ // Introduce the local -> global mapping for macros within this module.
+ F.MacroRemap.insertOrReplace(
+ std::make_pair(LocalBaseMacroID,
+ F.BaseMacroID - LocalBaseMacroID));
- if (Record.size() < 7) {
- Error("source location entry is incorrect");
- return Failure;
- }
-
- off_t StoredSize = (off_t)Record[4];
- time_t StoredTime = (time_t)Record[5];
-
- // Check if there was a request to override the contents of the file
- // that was part of the precompiled header. Overridding such a file
- // can lead to problems when lexing using the source locations from the
- // PCH.
- SourceManager &SM = getSourceManager();
- if (SM.isFileOverridden(File)) {
- Error(diag::err_fe_pch_file_overridden, Filename);
- // After emitting the diagnostic, recover by disabling the override so
- // that the original file will be used.
- SM.disableFileContentsOverride(File);
- // The FileEntry is a virtual file entry with the size of the contents
- // that would override the original contents. Set it to the original's
- // size/time.
- FileMgr.modifyFileEntry(const_cast<FileEntry*>(File),
- StoredSize, StoredTime);
+ MacrosLoaded.resize(MacrosLoaded.size() + F.LocalNumMacros);
}
+ break;
+ }
- // The stat info from the FileEntry came from the cached stat
- // info of the PCH, so we cannot trust it.
- struct stat StatBuf;
- if (::stat(File->getName(), &StatBuf) != 0) {
- StatBuf.st_size = File->getSize();
- StatBuf.st_mtime = File->getModificationTime();
- }
+ case MACRO_UPDATES: {
+ for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
+ MacroID ID = getGlobalMacroID(F, Record[I++]);
+ if (I == N)
+ break;
- if ((StoredSize != StatBuf.st_size
-#if !defined(LLVM_ON_WIN32)
- // In our regression testing, the Windows file system seems to
- // have inconsistent modification times that sometimes
- // erroneously trigger this error-handling path.
- || StoredTime != StatBuf.st_mtime
-#endif
- )) {
- Error(diag::err_fe_pch_file_modified, Filename);
- return IgnorePCH;
+ SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
+ SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
+ MacroUpdate Update;
+ Update.UndefLoc = UndefLoc;
+ MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
}
-
break;
}
}
}
-
- return Success;
+ Error("premature end of bitstream in AST file");
+ return true;
}
void ASTReader::makeNamesVisible(const HiddenNames &Names) {
for (unsigned I = 0, N = Names.size(); I != N; ++I) {
- if (Decl *D = Names[I].dyn_cast<Decl *>())
- D->Hidden = false;
- else {
- IdentifierInfo *II = Names[I].get<IdentifierInfo *>();
- if (!II->hasMacroDefinition()) {
- II->setHasMacroDefinition(true);
- if (DeserializationListener)
- DeserializationListener->MacroVisible(II);
+ switch (Names[I].getKind()) {
+ case HiddenName::Declaration:
+ Names[I].getDecl()->Hidden = false;
+ break;
+
+ case HiddenName::MacroVisibility: {
+ std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+ Macro.second->setHidden(!Macro.second->isPublic());
+ if (Macro.second->isDefined()) {
+ PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+ }
+ break;
+ }
+
+ case HiddenName::MacroUndef: {
+ std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+ if (Macro.second->isDefined()) {
+ Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
+ if (PPMutationListener *Listener = PP.getPPMutationListener())
+ Listener->UndefinedMacro(Macro.second);
+ PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
}
+ break;
+ }
}
}
}
@@ -2631,7 +2648,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
Module *Imported = Mod->Imports[I];
- if (Visited.count(Imported))
+ if (!Visited.insert(Imported))
continue;
bool Acceptable = UnrestrictedWildcard;
@@ -2649,32 +2666,62 @@ void ASTReader::makeModuleVisible(Module *Mod,
if (!Acceptable)
continue;
- Visited.insert(Imported);
Stack.push_back(Imported);
}
}
}
ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
- ModuleKind Type) {
+ ModuleKind Type,
+ unsigned ClientLoadCapabilities) {
// Bump the generation number.
unsigned PreviousGeneration = CurrentGeneration++;
-
- switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) {
- case Failure: return Failure;
- case IgnorePCH: return IgnorePCH;
- case Success: break;
+
+ unsigned NumModules = ModuleMgr.size();
+ llvm::SmallVector<ModuleFile *, 4> Loaded;
+ switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type,
+ /*ImportedBy=*/0, Loaded,
+ ClientLoadCapabilities)) {
+ case Failure:
+ case OutOfDate:
+ case VersionMismatch:
+ case ConfigurationMismatch:
+ case HadErrors:
+ ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, ModuleMgr.end());
+ return ReadResult;
+
+ case Success:
+ break;
}
// Here comes stuff that we only do once the entire chain is loaded.
- // Check the predefines buffers.
- 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())
- return IgnorePCH;
+ // Load the AST blocks of all of the modules that we loaded.
+ for (llvm::SmallVectorImpl<ModuleFile *>::iterator M = Loaded.begin(),
+ MEnd = Loaded.end();
+ M != MEnd; ++M) {
+ ModuleFile &F = **M;
+
+ // Read the AST block.
+ if (ReadASTBlock(F))
+ return Failure;
+
+ // Once read, set the ModuleFile bit base offset and update the size in
+ // bits of all files we've seen.
+ F.GlobalBitOffset = TotalModulesSizeInBits;
+ TotalModulesSizeInBits += F.SizeInBits;
+ GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
+
+ // Preload SLocEntries.
+ for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
+ int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
+ // Load it through the SourceManager and don't call ReadSLocEntry()
+ // directly because the entry may have already been loaded in which case
+ // calling ReadSLocEntry() directly would trigger an assertion in
+ // SourceManager.
+ SourceMgr.getLoadedSLocEntryByID(Index);
+ }
+ }
// 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
@@ -2707,17 +2754,19 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
if (DeserializationListener)
DeserializationListener->ReaderInitialized(this);
- if (!OriginalFileID.isInvalid()) {
- OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID
- + OriginalFileID.getOpaqueValue() - 1);
+ ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
+ if (!PrimaryModule.OriginalSourceFileID.isInvalid()) {
+ PrimaryModule.OriginalSourceFileID
+ = FileID::get(PrimaryModule.SLocEntryBaseID
+ + PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
- // If this AST file is a precompiled preamble, then set the preamble file ID
- // of the source manager to the file source file from which the preamble was
- // built.
+ // If this AST file is a precompiled preamble, then set the
+ // preamble file ID of the source manager to the file source file
+ // from which the preamble was built.
if (Type == MK_Preamble) {
- SourceMgr.setPreambleFileID(OriginalFileID);
+ SourceMgr.setPreambleFileID(PrimaryModule.OriginalSourceFileID);
} else if (Type == MK_MainFile) {
- SourceMgr.setMainFileID(OriginalFileID);
+ SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);
}
}
@@ -2732,9 +2781,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
return Success;
}
-ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
- ModuleKind Type,
- ModuleFile *ImportedBy) {
+ASTReader::ASTReadResult
+ASTReader::ReadASTCore(StringRef FileName,
+ ModuleKind Type,
+ ModuleFile *ImportedBy,
+ llvm::SmallVectorImpl<ModuleFile *> &Loaded,
+ unsigned ClientLoadCapabilities) {
ModuleFile *M;
bool NewModule;
std::string ErrorStr;
@@ -2785,7 +2837,7 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
unsigned BlockID = Stream.ReadSubBlockID();
- // We only know the AST subblock ID.
+ // We only know the control subblock ID.
switch (BlockID) {
case llvm::bitc::BLOCKINFO_BLOCK_ID:
if (Stream.ReadBlockInfoBlock()) {
@@ -2793,29 +2845,23 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
return Failure;
}
break;
- case AST_BLOCK_ID:
- switch (ReadASTBlock(F)) {
+ case CONTROL_BLOCK_ID:
+ switch (ReadControlBlock(F, Loaded, ClientLoadCapabilities)) {
case Success:
break;
- case Failure:
- return Failure;
-
- case IgnorePCH:
- // FIXME: We could consider reading through to the end of this
- // AST block, skipping subblocks, to see if there are other
- // AST blocks elsewhere.
-
- // FIXME: We can't clear loaded slocentries anymore.
- //SourceMgr.ClearPreallocatedSLocEntries();
-
- // Remove the stat cache.
- if (F.StatCache)
- FileMgr.removeStatCache((ASTStatCache*)F.StatCache);
-
- return IgnorePCH;
+ case Failure: return Failure;
+ case OutOfDate: return OutOfDate;
+ case VersionMismatch: return VersionMismatch;
+ case ConfigurationMismatch: return ConfigurationMismatch;
+ case HadErrors: return HadErrors;
}
break;
+ case AST_BLOCK_ID:
+ // Record that we've loaded this module.
+ Loaded.push_back(M);
+ return Success;
+
default:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
@@ -2825,32 +2871,6 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
}
}
- // Once read, set the ModuleFile bit base offset and update the size in
- // bits of all files we've seen.
- F.GlobalBitOffset = TotalModulesSizeInBits;
- TotalModulesSizeInBits += F.SizeInBits;
- GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
-
- // Make sure that the files this module was built against are still available.
- if (!DisableValidation) {
- switch(validateFileEntries(*M)) {
- case Failure: return Failure;
- case IgnorePCH: return IgnorePCH;
- case Success: break;
- }
- }
-
- // Preload SLocEntries.
- for (unsigned I = 0, N = M->PreloadSLocEntries.size(); I != N; ++I) {
- int Index = int(M->PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
- // Load it through the SourceManager and don't call ReadSLocEntryRecord()
- // directly because the entry may have already been loaded in which case
- // calling ReadSLocEntryRecord() directly would trigger an assertion in
- // SourceManager.
- SourceMgr.getLoadedSLocEntryByID(Index);
- }
-
-
return Success;
}
@@ -3038,8 +3058,8 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
// We only know the AST subblock ID.
switch (BlockID) {
- case AST_BLOCK_ID:
- if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ case CONTROL_BLOCK_ID:
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
return std::string();
}
@@ -3071,19 +3091,191 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
Record.clear();
const char *BlobStart = 0;
unsigned BlobLen = 0;
- if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
- == ORIGINAL_FILE_NAME)
+ if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == ORIGINAL_FILE)
return std::string(BlobStart, BlobLen);
}
return std::string();
}
-ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
+namespace {
+ class SimplePCHValidator : public ASTReaderListener {
+ const LangOptions &ExistingLangOpts;
+ const TargetOptions &ExistingTargetOpts;
+ const PreprocessorOptions &ExistingPPOpts;
+ FileManager &FileMgr;
+
+ public:
+ SimplePCHValidator(const LangOptions &ExistingLangOpts,
+ const TargetOptions &ExistingTargetOpts,
+ const PreprocessorOptions &ExistingPPOpts,
+ FileManager &FileMgr)
+ : ExistingLangOpts(ExistingLangOpts),
+ ExistingTargetOpts(ExistingTargetOpts),
+ ExistingPPOpts(ExistingPPOpts),
+ FileMgr(FileMgr)
+ {
+ }
+
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) {
+ return checkLanguageOptions(ExistingLangOpts, LangOpts, 0);
+ }
+ virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) {
+ return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
+ }
+ virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
+ SuggestedPredefines);
+ }
+ };
+}
+
+bool ASTReader::readASTFileControlBlock(StringRef Filename,
+ FileManager &FileMgr,
+ ASTReaderListener &Listener) {
+ // Open the AST file.
+ std::string ErrStr;
+ OwningPtr<llvm::MemoryBuffer> Buffer;
+ Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
+ if (!Buffer) {
+ return true;
+ }
+
+ // Initialize the stream
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+ StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
+ (const unsigned char *)Buffer->getBufferEnd());
+ Stream.init(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'P' ||
+ Stream.Read(8) != 'C' ||
+ Stream.Read(8) != 'H') {
+ return true;
+ }
+
+ RecordData Record;
+ bool InControlBlock = false;
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ // We only know the control subblock ID.
+ switch (BlockID) {
+ case CONTROL_BLOCK_ID:
+ if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
+ return true;
+ } else {
+ InControlBlock = true;
+ }
+ break;
+
+ default:
+ if (Stream.SkipBlock())
+ return true;
+ break;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Stream.ReadBlockEnd()) {
+ return true;
+ }
+
+ InControlBlock = false;
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ Record.clear();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ unsigned RecCode = Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen);
+ if (InControlBlock) {
+ switch ((ControlRecordTypes)RecCode) {
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR) {
+ return true;
+ }
+
+ const std::string &CurBranch = getClangFullRepositoryVersion();
+ StringRef ASTBranch(BlobStart, BlobLen);
+ if (StringRef(CurBranch) != ASTBranch)
+ return true;
+
+ break;
+ }
+ case LANGUAGE_OPTIONS:
+ if (ParseLanguageOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case TARGET_OPTIONS:
+ if (ParseTargetOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case DIAGNOSTIC_OPTIONS:
+ if (ParseDiagnosticOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case FILE_SYSTEM_OPTIONS:
+ if (ParseFileSystemOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case HEADER_SEARCH_OPTIONS:
+ if (ParseHeaderSearchOptions(Record, false, Listener))
+ return true;
+ break;
+
+ case PREPROCESSOR_OPTIONS: {
+ std::string IgnoredSuggestedPredefines;
+ if (ParsePreprocessorOptions(Record, false, Listener,
+ IgnoredSuggestedPredefines))
+ return true;
+ break;
+ }
+
+ default:
+ // No other validation to perform.
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+bool ASTReader::isAcceptableASTFile(StringRef Filename,
+ FileManager &FileMgr,
+ const LangOptions &LangOpts,
+ const TargetOptions &TargetOpts,
+ const PreprocessorOptions &PPOpts) {
+ SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
+ return !readASTFileControlBlock(Filename, FileMgr, validator);
+}
+
+bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
// Enter the submodule block.
if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
Error("malformed submodule block record in AST file");
- return Failure;
+ return true;
}
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
@@ -3095,9 +3287,9 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
if (Code == llvm::bitc::END_BLOCK) {
if (F.Stream.ReadBlockEnd()) {
Error("error at end of submodule block in AST file");
- return Failure;
+ return true;
}
- return Success;
+ return false;
}
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
@@ -3105,7 +3297,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
F.Stream.ReadSubBlockID();
if (F.Stream.SkipBlock()) {
Error("malformed block record in AST file");
- return Failure;
+ return true;
}
continue;
}
@@ -3126,12 +3318,12 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_DEFINITION: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (Record.size() < 7) {
Error("malformed module definition");
- return Failure;
+ return true;
}
StringRef Name(BlobStart, BlobLen);
@@ -3157,9 +3349,10 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
if (GlobalIndex >= SubmodulesLoaded.size() ||
SubmodulesLoaded[GlobalIndex]) {
Error("too many submodules");
- return Failure;
+ return true;
}
+ CurrentModule->setASTFile(F.File);
CurrentModule->IsFromModuleFile = true;
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
CurrentModule->InferSubmodules = InferSubmodules;
@@ -3175,7 +3368,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_UMBRELLA_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3187,7 +3380,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
Error("mismatched umbrella headers in submodule");
- return Failure;
+ return true;
}
}
break;
@@ -3196,7 +3389,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3208,15 +3401,51 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
if (std::find(CurrentModule->Headers.begin(),
CurrentModule->Headers.end(),
File) == CurrentModule->Headers.end())
- ModMap.addHeader(CurrentModule, File);
+ ModMap.addHeader(CurrentModule, File, false);
}
break;
}
-
+
+ case SUBMODULE_EXCLUDED_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+ if (std::find(CurrentModule->Headers.begin(),
+ CurrentModule->Headers.end(),
+ File) == CurrentModule->Headers.end())
+ ModMap.addHeader(CurrentModule, File, true);
+ }
+ break;
+ }
+
+ case SUBMODULE_TOPHEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName))
+ CurrentModule->TopHeaders.insert(File);
+ break;
+ }
+
case SUBMODULE_UMBRELLA_DIR: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3229,7 +3458,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
ModMap.setUmbrellaDir(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaDir() != Umbrella) {
Error("mismatched umbrella directories in submodule");
- return Failure;
+ return true;
}
}
break;
@@ -3238,7 +3467,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_METADATA: {
if (!First) {
Error("submodule metadata record not at beginning of block");
- return Failure;
+ return true;
}
First = false;
@@ -3264,7 +3493,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_IMPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3285,7 +3514,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_EXPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3309,7 +3538,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
case SUBMODULE_REQUIRES: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return Failure;
+ return true;
}
if (!CurrentModule)
@@ -3331,27 +3560,144 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
/// them to the AST listener if one is set.
///
/// \returns true if the listener deems the file unacceptable, false otherwise.
-bool ASTReader::ParseLanguageOptions(const RecordData &Record) {
- if (Listener) {
- LangOptions LangOpts;
- unsigned Idx = 0;
+bool ASTReader::ParseLanguageOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ LangOptions LangOpts;
+ unsigned Idx = 0;
#define LANGOPT(Name, Bits, Default, Description) \
LangOpts.Name = Record[Idx++];
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
#include "clang/Basic/LangOptions.def"
- ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
- VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
- LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
-
- unsigned Length = Record[Idx++];
- LangOpts.CurrentModule.assign(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- return Listener->ReadLanguageOptions(LangOpts);
+ ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
+ VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx);
+ LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion);
+
+ unsigned Length = Record[Idx++];
+ LangOpts.CurrentModule.assign(Record.begin() + Idx,
+ Record.begin() + Idx + Length);
+ return Listener.ReadLanguageOptions(LangOpts, Complain);
+}
+
+bool ASTReader::ParseTargetOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ unsigned Idx = 0;
+ TargetOptions TargetOpts;
+ TargetOpts.Triple = ReadString(Record, Idx);
+ TargetOpts.CPU = ReadString(Record, Idx);
+ TargetOpts.ABI = ReadString(Record, Idx);
+ TargetOpts.CXXABI = ReadString(Record, Idx);
+ TargetOpts.LinkerVersion = ReadString(Record, Idx);
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.FeaturesAsWritten.push_back(ReadString(Record, Idx));
+ }
+ for (unsigned N = Record[Idx++]; N; --N) {
+ TargetOpts.Features.push_back(ReadString(Record, Idx));
}
- return false;
+ return Listener.ReadTargetOptions(TargetOpts, Complain);
+}
+
+bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener) {
+ DiagnosticOptions DiagOpts;
+ unsigned Idx = 0;
+#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++];
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+ DiagOpts.set##Name(static_cast<Type>(Record[Idx++]));
+#include "clang/Basic/DiagnosticOptions.def"
+
+ for (unsigned N = Record[Idx++]; N; --N) {
+ DiagOpts.Warnings.push_back(ReadString(Record, Idx));
+ }
+
+ return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
+}
+
+bool ASTReader::ParseFileSystemOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener) {
+ FileSystemOptions FSOpts;
+ unsigned Idx = 0;
+ FSOpts.WorkingDir = ReadString(Record, Idx);
+ return Listener.ReadFileSystemOptions(FSOpts, Complain);
+}
+
+bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener) {
+ HeaderSearchOptions HSOpts;
+ unsigned Idx = 0;
+ HSOpts.Sysroot = ReadString(Record, Idx);
+
+ // Include entries.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Path = ReadString(Record, Idx);
+ frontend::IncludeDirGroup Group
+ = static_cast<frontend::IncludeDirGroup>(Record[Idx++]);
+ bool IsUserSupplied = Record[Idx++];
+ bool IsFramework = Record[Idx++];
+ bool IgnoreSysRoot = Record[Idx++];
+ bool IsInternal = Record[Idx++];
+ bool ImplicitExternC = Record[Idx++];
+ HSOpts.UserEntries.push_back(
+ HeaderSearchOptions::Entry(Path, Group, IsUserSupplied, IsFramework,
+ IgnoreSysRoot, IsInternal, ImplicitExternC));
+ }
+
+ // System header prefixes.
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Prefix = ReadString(Record, Idx);
+ bool IsSystemHeader = Record[Idx++];
+ HSOpts.SystemHeaderPrefixes.push_back(
+ HeaderSearchOptions::SystemHeaderPrefix(Prefix, IsSystemHeader));
+ }
+
+ HSOpts.ResourceDir = ReadString(Record, Idx);
+ HSOpts.ModuleCachePath = ReadString(Record, Idx);
+ HSOpts.DisableModuleHash = Record[Idx++];
+ HSOpts.UseBuiltinIncludes = Record[Idx++];
+ HSOpts.UseStandardSystemIncludes = Record[Idx++];
+ HSOpts.UseStandardCXXIncludes = Record[Idx++];
+ HSOpts.UseLibcxx = Record[Idx++];
+
+ return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
+}
+
+bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
+ bool Complain,
+ ASTReaderListener &Listener,
+ std::string &SuggestedPredefines) {
+ PreprocessorOptions PPOpts;
+ unsigned Idx = 0;
+
+ // Macro definitions/undefs
+ for (unsigned N = Record[Idx++]; N; --N) {
+ std::string Macro = ReadString(Record, Idx);
+ bool IsUndef = Record[Idx++];
+ PPOpts.Macros.push_back(std::make_pair(Macro, IsUndef));
+ }
+
+ // Includes
+ for (unsigned N = Record[Idx++]; N; --N) {
+ PPOpts.Includes.push_back(ReadString(Record, Idx));
+ }
+
+ // Macro Includes
+ for (unsigned N = Record[Idx++]; N; --N) {
+ PPOpts.MacroIncludes.push_back(ReadString(Record, Idx));
+ }
+
+ PPOpts.UsePredefines = Record[Idx++];
+ PPOpts.ImplicitPCHInclude = ReadString(Record, Idx);
+ PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
+ PPOpts.ObjCXXARCStandardLibrary =
+ static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
+ SuggestedPredefines.clear();
+ return Listener.ReadPreprocessorOptions(PPOpts, Complain,
+ SuggestedPredefines);
}
std::pair<ModuleFile *, unsigned>
@@ -3365,6 +3711,23 @@ ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
return std::make_pair(M, LocalIndex);
}
+std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
+ if (PreprocessingRecord *PPRec = PP.getPreprocessingRecord())
+ return PPRec->getIteratorsForLoadedRange(Mod.BasePreprocessedEntityID,
+ Mod.NumPreprocessedEntities);
+
+ return std::make_pair(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
+}
+
+std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
+ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
+ return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
+ ModuleDeclIterator(this, &Mod,
+ Mod.FileSortedDecls + Mod.NumFileSortedDecls));
+}
+
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
PreprocessedEntityID PPID = Index+1;
std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
@@ -3455,7 +3818,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
InclusionDirective *ID
= new (PPRec) InclusionDirective(PPRec, Kind,
StringRef(BlobStart, Record[0]),
- Record[1],
+ Record[1], Record[3],
File,
Range);
return ID;
@@ -3476,7 +3839,7 @@ PreprocessedEntityID ASTReader::findNextPreprocessedEntity(
EndI = GlobalSLocOffsetMap.end(); SLocMapI != EndI; ++SLocMapI) {
ModuleFile &M = *SLocMapI->second;
if (M.NumPreprocessedEntities)
- return getGlobalPreprocessedEntityID(M, M.BasePreprocessedEntityID);
+ return M.BasePreprocessedEntityID;
}
return getTotalNumPreprocessedEntities();
@@ -3559,8 +3922,7 @@ ASTReader::findBeginPreprocessedEntity(SourceLocation BLoc) const {
if (PPI == pp_end)
return findNextPreprocessedEntity(SLocMapI);
- return getGlobalPreprocessedEntityID(M,
- M.BasePreprocessedEntityID + (PPI - pp_begin));
+ return M.BasePreprocessedEntityID + (PPI - pp_begin);
}
/// \brief Returns the first preprocessed entity ID that begins after \arg ELoc.
@@ -3589,8 +3951,7 @@ ASTReader::findEndPreprocessedEntity(SourceLocation ELoc) const {
if (PPI == pp_end)
return findNextPreprocessedEntity(SLocMapI);
- return getGlobalPreprocessedEntityID(M,
- M.BasePreprocessedEntityID + (PPI - pp_begin));
+ return M.BasePreprocessedEntityID + (PPI - pp_begin);
}
/// \brief Returns a pair of [Begin, End) indices of preallocated
@@ -3681,14 +4042,31 @@ HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
}
void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
+ // FIXME: Make it work properly with modules.
+ llvm::SmallVector<DiagnosticsEngine::DiagState *, 32> DiagStates;
for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) {
ModuleFile &F = *(*I);
unsigned Idx = 0;
+ DiagStates.clear();
+ assert(!Diag.DiagStates.empty());
+ DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one.
while (Idx < F.PragmaDiagMappings.size()) {
SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]);
+ unsigned DiagStateID = F.PragmaDiagMappings[Idx++];
+ if (DiagStateID != 0) {
+ Diag.DiagStatePoints.push_back(
+ DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1],
+ FullSourceLoc(Loc, SourceMgr)));
+ continue;
+ }
+
+ assert(DiagStateID == 0);
+ // A new DiagState was created here.
Diag.DiagStates.push_back(*Diag.GetCurDiagState());
+ DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back();
+ DiagStates.push_back(NewState);
Diag.DiagStatePoints.push_back(
- DiagnosticsEngine::DiagStatePoint(&Diag.DiagStates.back(),
+ DiagnosticsEngine::DiagStatePoint(NewState,
FullSourceLoc(Loc, SourceMgr)));
while (1) {
assert(Idx < F.PragmaDiagMappings.size() &&
@@ -4258,6 +4636,8 @@ void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
}
void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setRParenLoc(ReadSourceLocation(Record, Idx));
TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
TL.setArg(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
@@ -4467,6 +4847,10 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_VA_LIST_TAG:
T = Context.getVaListTagType();
break;
+
+ case PREDEF_TYPE_BUILTIN_FN:
+ T = Context.BuiltinFnTy;
+ break;
}
assert(!T.isNull() && "Unknown predefined type");
@@ -4537,7 +4921,9 @@ ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
case TemplateArgument::Pack:
+ // FIXME: Is this right?
return TemplateArgumentLocInfo();
}
llvm_unreachable("unexpected template argument loc");
@@ -4593,7 +4979,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
}
serialization::DeclID
-ASTReader::getGlobalDeclID(ModuleFile &F, unsigned LocalID) const {
+ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
if (LocalID < NUM_PREDEF_DECL_IDS)
return LocalID;
@@ -4930,8 +5316,10 @@ namespace {
continue;
if (ND->getDeclName() != This->Name) {
- assert(!This->Name.getCXXNameType().isNull() &&
- "Name mismatch without a type");
+ // A name might be null because the decl's redeclarable part is
+ // currently read before reading its name. The lookup is triggered by
+ // building that decl (likely indirectly), and so it is later in the
+ // sense of "already existing" and can be ignored here.
continue;
}
@@ -5132,13 +5520,15 @@ void ASTReader::PrintStats() {
= IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
IdentifiersLoaded.end(),
(IdentifierInfo *)0);
+ unsigned NumMacrosLoaded
+ = MacrosLoaded.size() - std::count(MacrosLoaded.begin(),
+ MacrosLoaded.end(),
+ (MacroInfo *)0);
unsigned NumSelectorsLoaded
= SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
SelectorsLoaded.end(),
Selector());
- std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
- std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
if (unsigned TotalNumSLocEntries = getTotalNumSLocs())
std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
NumSLocEntriesRead, TotalNumSLocEntries,
@@ -5155,6 +5545,10 @@ void ASTReader::PrintStats() {
std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
+ if (!MacrosLoaded.empty())
+ std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
+ NumMacrosLoaded, (unsigned)MacrosLoaded.size(),
+ ((float)NumMacrosLoaded/MacrosLoaded.size() * 100));
if (!SelectorsLoaded.empty())
std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
@@ -5213,6 +5607,7 @@ void ASTReader::dump() {
dumpModuleIDMap("Global type map", GlobalTypeMap);
dumpModuleIDMap("Global declaration map", GlobalDeclMap);
dumpModuleIDMap("Global identifier map", GlobalIdentifierMap);
+ dumpModuleIDMap("Global macro map", GlobalMacroMap);
dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);
dumpModuleIDMap("Global selector map", GlobalSelectorMap);
dumpModuleIDMap("Global preprocessed entity map",
@@ -5246,7 +5641,7 @@ void ASTReader::getMemoryBufferSizes(MemoryBufferSizes &sizes) const {
void ASTReader::InitializeSema(Sema &S) {
SemaObj = &S;
- S.ExternalSource = this;
+ S.addExternalSource(this);
// Makes sure any declarations that were deserialized "too early"
// still get added to the identifier's declaration chains.
@@ -5281,6 +5676,9 @@ void ASTReader::InitializeSema(Sema &S) {
}
IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
/*PriorGeneration=*/0);
ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
@@ -5570,6 +5968,7 @@ void ASTReader::ReadPendingInstantiations(
ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
SourceLocation Loc
= SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
+
Pending.push_back(std::make_pair(D, Loc));
}
PendingInstantiations.clear();
@@ -5682,8 +6081,37 @@ IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
return LocalID + I->second;
}
-bool ASTReader::ReadSLocEntry(int ID) {
- return ReadSLocEntryRecord(ID) != Success;
+MacroInfo *ASTReader::getMacro(MacroID ID, MacroInfo *Hint) {
+ if (ID == 0)
+ return 0;
+
+ if (MacrosLoaded.empty()) {
+ Error("no macro table in AST file");
+ return 0;
+ }
+
+ ID -= NUM_PREDEF_MACRO_IDS;
+ if (!MacrosLoaded[ID]) {
+ GlobalMacroMapType::iterator I
+ = GlobalMacroMap.find(ID + NUM_PREDEF_MACRO_IDS);
+ assert(I != GlobalMacroMap.end() && "Corrupted global macro map");
+ ModuleFile *M = I->second;
+ unsigned Index = ID - M->BaseMacroID;
+ ReadMacroRecord(*M, M->MacroOffsets[Index], Hint);
+ }
+
+ return MacrosLoaded[ID];
+}
+
+MacroID ASTReader::getGlobalMacroID(ModuleFile &M, unsigned LocalID) {
+ if (LocalID < NUM_PREDEF_MACRO_IDS)
+ return LocalID;
+
+ ContinuousRangeMap<uint32_t, int, 2>::iterator I
+ = M.MacroRemap.find(LocalID - NUM_PREDEF_MACRO_IDS);
+ assert(I != M.MacroRemap.end() && "Invalid index into macro index remap");
+
+ return LocalID + I->second;
}
serialization::SubmoduleID
@@ -5694,7 +6122,7 @@ ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);
assert(I != M.SubmoduleRemap.end()
- && "Invalid index into identifier index remap");
+ && "Invalid index into submodule index remap");
return LocalID + I->second;
}
@@ -5759,7 +6187,7 @@ ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);
assert(I != M.SelectorRemap.end()
- && "Invalid index into identifier index remap");
+ && "Invalid index into selector index remap");
return LocalID + I->second;
}
@@ -5926,8 +6354,13 @@ ASTReader::ReadTemplateArgument(ModuleFile &F,
return TemplateArgument();
case TemplateArgument::Type:
return TemplateArgument(readType(F, Record, Idx));
- case TemplateArgument::Declaration:
- return TemplateArgument(ReadDecl(F, Record, Idx));
+ case TemplateArgument::Declaration: {
+ ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
+ bool ForReferenceParam = Record[Idx++];
+ return TemplateArgument(D, ForReferenceParam);
+ }
+ case TemplateArgument::NullPtr:
+ return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
case TemplateArgument::Integral: {
llvm::APSInt Value = ReadAPSInt(Record, Idx);
QualType T = readType(F, Record, Idx);
@@ -6340,7 +6773,8 @@ void ASTReader::ReadComments() {
}
void ASTReader::finishPendingActions() {
- while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) {
+ while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+ !PendingMacroIDs.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
while (!PendingIdentifierInfos.empty()) {
@@ -6355,6 +6789,18 @@ void ASTReader::finishPendingActions() {
PendingDeclChainsKnown.erase(PendingDeclChains[I]);
}
PendingDeclChains.clear();
+
+ // Load any pending macro definitions.
+ for (unsigned I = 0; I != PendingMacroIDs.size(); ++I) {
+ // FIXME: std::move here
+ SmallVector<MacroID, 2> GlobalIDs = PendingMacroIDs.begin()[I].second;
+ MacroInfo *Hint = 0;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ ++IDIdx) {
+ Hint = getMacro(GlobalIDs[IDIdx], Hint);
+ }
+ }
+ PendingMacroIDs.clear();
}
// If we deserialized any C++ or Objective-C class definitions, any
@@ -6408,9 +6854,29 @@ void ASTReader::finishPendingActions() {
for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
REnd = RTD->redecls_end();
R != REnd; ++R)
- R->Common = RTD->Common;
+ R->Common = RTD->Common;
}
PendingDefinitions.clear();
+
+ // Load the bodies of any functions or methods we've encountered. We do
+ // this now (delayed) so that we can be sure that the declaration chains
+ // have been fully wired up.
+ for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
+ PBEnd = PendingBodies.end();
+ PB != PBEnd; ++PB) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
+ // FIXME: Check for =delete/=default?
+ // FIXME: Complain about ODR violations here?
+ if (!getContext().getLangOpts().Modules || !FD->hasBody())
+ FD->setLazyBody(PB->second);
+ continue;
+ }
+
+ ObjCMethodDecl *MD = cast<ObjCMethodDecl>(PB->first);
+ if (!getContext().getLangOpts().Modules || !MD->hasBody())
+ MD->setLazyBody(PB->second);
+ }
+ PendingBodies.clear();
}
void ASTReader::FinishedDeserializing() {
@@ -6442,17 +6908,14 @@ void ASTReader::FinishedDeserializing() {
ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
StringRef isysroot, bool DisableValidation,
- bool DisableStatCache, bool AllowASTWithCompilerErrors)
+ bool AllowASTWithCompilerErrors)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(PP), Context(Context),
- Consumer(0), ModuleMgr(FileMgr.getFileSystemOptions()),
- RelocatablePCH(false), isysroot(isysroot),
- DisableValidation(DisableValidation),
- DisableStatCache(DisableStatCache),
+ Consumer(0), ModuleMgr(PP.getFileManager()),
+ isysroot(isysroot), DisableValidation(DisableValidation),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
CurrentGeneration(0), CurrSwitchCaseStmts(&SwitchCaseStmts),
- NumStatHits(0), NumStatMisses(0),
NumSLocEntriesRead(0), TotalNumSLocEntries(0),
NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
OpenPOWER on IntegriCloud