aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ASTReader.cpp')
-rw-r--r--lib/Serialization/ASTReader.cpp1273
1 files changed, 571 insertions, 702 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 416164ebb7d2..5e3a82795049 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===--- ASTReader.cpp - AST File Reader ----------------------------------===//
+//===-- ASTReader.cpp - AST File Reader ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -89,11 +89,13 @@ ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
Second->ReadLanguageOptions(LangOpts, Complain,
AllowCompatibleDifferences);
}
-bool
-ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) {
- return First->ReadTargetOptions(TargetOpts, Complain) ||
- Second->ReadTargetOptions(TargetOpts, Complain);
+bool ChainedASTReaderListener::ReadTargetOptions(
+ const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) {
+ return First->ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences) ||
+ Second->ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ChainedASTReaderListener::ReadDiagnosticOptions(
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
@@ -108,9 +110,12 @@ ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
}
bool ChainedASTReaderListener::ReadHeaderSearchOptions(
- const HeaderSearchOptions &HSOpts, bool Complain) {
- return First->ReadHeaderSearchOptions(HSOpts, Complain) ||
- Second->ReadHeaderSearchOptions(HSOpts, Complain);
+ const HeaderSearchOptions &HSOpts, StringRef SpecificModuleCachePath,
+ bool Complain) {
+ return First->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain) ||
+ Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain);
}
bool ChainedASTReaderListener::ReadPreprocessorOptions(
const PreprocessorOptions &PPOpts, bool Complain,
@@ -229,7 +234,8 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
/// \returns true if the target options mis-match, false otherwise.
static bool checkTargetOptions(const TargetOptions &TargetOpts,
const TargetOptions &ExistingTargetOpts,
- DiagnosticsEngine *Diags) {
+ DiagnosticsEngine *Diags,
+ bool AllowCompatibleDifferences = true) {
#define CHECK_TARGET_OPT(Field, Name) \
if (TargetOpts.Field != ExistingTargetOpts.Field) { \
if (Diags) \
@@ -238,9 +244,16 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
return true; \
}
+ // The triple and ABI must match exactly.
CHECK_TARGET_OPT(Triple, "target");
- CHECK_TARGET_OPT(CPU, "target CPU");
CHECK_TARGET_OPT(ABI, "target ABI");
+
+ // We can tolerate different CPUs in many cases, notably when one CPU
+ // supports a strict superset of another. When allowing compatible
+ // differences skip this check.
+ if (!AllowCompatibleDifferences)
+ CHECK_TARGET_OPT(CPU, "target CPU");
+
#undef CHECK_TARGET_OPT
// Compare feature sets.
@@ -252,43 +265,31 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
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;
- }
-
- if (ReadFeatures[ReadIdx] < ExistingFeatures[ExistingIdx]) {
- if (Diags)
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << false << ReadFeatures[ReadIdx];
- return true;
- }
-
- if (Diags)
- Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << true << ExistingFeatures[ExistingIdx];
- return true;
- }
+ // We compute the set difference in both directions explicitly so that we can
+ // diagnose the differences differently.
+ SmallVector<StringRef, 4> UnmatchedExistingFeatures, UnmatchedReadFeatures;
+ std::set_difference(
+ ExistingFeatures.begin(), ExistingFeatures.end(), ReadFeatures.begin(),
+ ReadFeatures.end(), std::back_inserter(UnmatchedExistingFeatures));
+ std::set_difference(ReadFeatures.begin(), ReadFeatures.end(),
+ ExistingFeatures.begin(), ExistingFeatures.end(),
+ std::back_inserter(UnmatchedReadFeatures));
+
+ // If we are allowing compatible differences and the read feature set is
+ // a strict subset of the existing feature set, there is nothing to diagnose.
+ if (AllowCompatibleDifferences && UnmatchedReadFeatures.empty())
+ return false;
- if (ExistingIdx < ExistingN) {
- if (Diags)
+ if (Diags) {
+ for (StringRef Feature : UnmatchedReadFeatures)
Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << true << ExistingFeatures[ExistingIdx];
- return true;
- }
-
- if (ReadIdx < ReadN) {
- if (Diags)
+ << /* is-existing-feature */ false << Feature;
+ for (StringRef Feature : UnmatchedExistingFeatures)
Diags->Report(diag::err_pch_targetopt_feature_mismatch)
- << false << ReadFeatures[ReadIdx];
- return true;
+ << /* is-existing-feature */ true << Feature;
}
- return false;
+ return !UnmatchedReadFeatures.empty() || !UnmatchedExistingFeatures.empty();
}
bool
@@ -302,10 +303,12 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
}
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) {
+ bool Complain,
+ bool AllowCompatibleDifferences) {
const TargetOptions &ExistingTargetOpts = PP.getTargetInfo().getTargetOpts();
return checkTargetOptions(TargetOpts, ExistingTargetOpts,
- Complain? &Reader.Diags : nullptr);
+ Complain ? &Reader.Diags : nullptr,
+ AllowCompatibleDifferences);
}
namespace {
@@ -464,7 +467,7 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
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.
///
@@ -591,6 +594,36 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
PP.getLangOpts());
}
+/// Check the header search options deserialized from the control block
+/// against the header search options in an existing preprocessor.
+///
+/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+static bool checkHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ StringRef ExistingModuleCachePath,
+ DiagnosticsEngine *Diags,
+ const LangOptions &LangOpts) {
+ if (LangOpts.Modules) {
+ if (SpecificModuleCachePath != ExistingModuleCachePath) {
+ if (Diags)
+ Diags->Report(diag::err_pch_modulecache_mismatch)
+ << SpecificModuleCachePath << ExistingModuleCachePath;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) {
+ return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ PP.getHeaderSearchInfo().getModuleCachePath(),
+ Complain ? &Reader.Diags : nullptr,
+ PP.getLangOpts());
+}
+
void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
PP.setCounterValue(Value);
}
@@ -744,8 +777,6 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
Bits >>= 1;
bool ExtensionToken = Bits & 0x01;
Bits >>= 1;
- bool hasSubmoduleMacros = Bits & 0x01;
- Bits >>= 1;
bool hadMacroDefinition = Bits & 0x01;
Bits >>= 1;
@@ -787,49 +818,8 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
uint32_t MacroDirectivesOffset =
endian::readNext<uint32_t, little, unaligned>(d);
DataLen -= 4;
- SmallVector<uint32_t, 8> LocalMacroIDs;
- if (hasSubmoduleMacros) {
- while (true) {
- uint32_t LocalMacroID =
- endian::readNext<uint32_t, little, unaligned>(d);
- DataLen -= 4;
- if (LocalMacroID == 0xdeadbeef) break;
- LocalMacroIDs.push_back(LocalMacroID);
- }
- }
-
- if (F.Kind == MK_ImplicitModule || F.Kind == MK_ExplicitModule) {
- // Macro definitions are stored from newest to oldest, so reverse them
- // before registering them.
- llvm::SmallVector<unsigned, 8> MacroSizes;
- for (SmallVectorImpl<uint32_t>::iterator
- I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) {
- unsigned Size = 1;
-
- static const uint32_t HasOverridesFlag = 0x80000000U;
- if (I + 1 != E && (I[1] & HasOverridesFlag))
- Size += 1 + (I[1] & ~HasOverridesFlag);
- MacroSizes.push_back(Size);
- I += Size;
- }
-
- SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end();
- for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(),
- SE = MacroSizes.rend();
- SI != SE; ++SI) {
- I -= *SI;
-
- uint32_t LocalMacroID = *I;
- ArrayRef<uint32_t> Overrides;
- if (*SI != 1)
- Overrides = llvm::makeArrayRef(&I[2], *SI - 2);
- Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides);
- }
- assert(I == LocalMacroIDs.begin());
- } else {
- Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset);
- }
+ Reader.addPendingMacro(II, &F, MacroDirectivesOffset);
}
Reader.SetIdentifierInfo(ID, II);
@@ -1393,6 +1383,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
PreprocessorRecordTypes RecType =
(PreprocessorRecordTypes)Stream.readRecord(Entry.ID, Record);
switch (RecType) {
+ case PP_MODULE_MACRO:
case PP_MACRO_DIRECTIVE_HISTORY:
return Macro;
@@ -1441,10 +1432,10 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
PreprocessedEntityID
GlobalID = getGlobalPreprocessedEntityID(F, Record[NextIndex]);
PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
- PreprocessingRecord::PPEntityID
- PPID = PPRec.getPPEntityID(GlobalID-1, /*isLoaded=*/true);
- MacroDefinition *PPDef =
- cast_or_null<MacroDefinition>(PPRec.getPreprocessedEntity(PPID));
+ PreprocessingRecord::PPEntityID PPID =
+ PPRec.getPPEntityID(GlobalID - 1, /*isLoaded=*/true);
+ MacroDefinitionRecord *PPDef = cast_or_null<MacroDefinitionRecord>(
+ PPRec.getPreprocessedEntity(PPID));
if (PPDef)
PPRec.RegisterMacroDefinition(Macro, PPDef);
}
@@ -1586,24 +1577,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
return HFI;
}
-void
-ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M,
- GlobalMacroID GMacID,
- ArrayRef<SubmoduleID> Overrides) {
- assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
- SubmoduleID *OverrideData = nullptr;
- if (!Overrides.empty()) {
- OverrideData = new (Context) SubmoduleID[Overrides.size() + 1];
- OverrideData[0] = Overrides.size();
- for (unsigned I = 0; I != Overrides.size(); ++I)
- OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]);
- }
- PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData));
-}
-
-void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II,
- ModuleFile *M,
- uint64_t MacroDirectivesOffset) {
+void ASTReader::addPendingMacro(IdentifierInfo *II,
+ ModuleFile *M,
+ uint64_t MacroDirectivesOffset) {
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
PendingMacroIDs[II].push_back(PendingMacroInfo(M, MacroDirectivesOffset));
}
@@ -1747,110 +1723,81 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
IdentifierGeneration[II] = getGeneration();
}
-struct ASTReader::ModuleMacroInfo {
- SubmoduleID SubModID;
- MacroInfo *MI;
- SubmoduleID *Overrides;
- // FIXME: Remove this.
- ModuleFile *F;
-
- bool isDefine() const { return MI; }
-
- SubmoduleID getSubmoduleID() const { return SubModID; }
-
- ArrayRef<SubmoduleID> getOverriddenSubmodules() const {
- if (!Overrides)
- return None;
- return llvm::makeArrayRef(Overrides + 1, *Overrides);
- }
-
- MacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
- if (!MI)
- return PP.AllocateUndefMacroDirective(ImportLoc, SubModID,
- getOverriddenSubmodules());
- return PP.AllocateDefMacroDirective(MI, ImportLoc, SubModID,
- getOverriddenSubmodules());
- }
-};
-
-ASTReader::ModuleMacroInfo *
-ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) {
- ModuleMacroInfo Info;
-
- uint32_t ID = PMInfo.ModuleMacroData.MacID;
- if (ID & 1) {
- // Macro undefinition.
- Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1);
- Info.MI = nullptr;
- } else {
- // Macro definition.
- GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1);
- assert(GMacID);
-
- // If this macro has already been loaded, don't do so again.
- // FIXME: This is highly dubious. Multiple macro definitions can have the
- // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc.
- if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
- return nullptr;
+void ASTReader::resolvePendingMacro(IdentifierInfo *II,
+ const PendingMacroInfo &PMInfo) {
+ ModuleFile &M = *PMInfo.M;
- Info.MI = getMacro(GMacID);
- Info.SubModID = Info.MI->getOwningModuleID();
- }
- Info.Overrides = PMInfo.ModuleMacroData.Overrides;
- Info.F = PMInfo.M;
+ BitstreamCursor &Cursor = M.MacroCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(PMInfo.MacroDirectivesOffset);
- return new (Context) ModuleMacroInfo(Info);
-}
+ struct ModuleMacroRecord {
+ SubmoduleID SubModID;
+ MacroInfo *MI;
+ SmallVector<SubmoduleID, 8> Overrides;
+ };
+ llvm::SmallVector<ModuleMacroRecord, 8> ModuleMacros;
-void ASTReader::resolvePendingMacro(IdentifierInfo *II,
- const PendingMacroInfo &PMInfo) {
- assert(II);
+ // We expect to see a sequence of PP_MODULE_MACRO records listing exported
+ // macros, followed by a PP_MACRO_DIRECTIVE_HISTORY record with the complete
+ // macro histroy.
+ RecordData Record;
+ while (true) {
+ llvm::BitstreamEntry Entry =
+ Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (Entry.Kind != llvm::BitstreamEntry::Record) {
+ Error("malformed block record in AST file");
+ return;
+ }
- if (PMInfo.M->Kind != MK_ImplicitModule &&
- PMInfo.M->Kind != MK_ExplicitModule) {
- installPCHMacroDirectives(II, *PMInfo.M,
- PMInfo.PCHMacroData.MacroDirectivesOffset);
- return;
- }
+ Record.clear();
+ switch ((PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record)) {
+ case PP_MACRO_DIRECTIVE_HISTORY:
+ break;
- // Module Macro.
+ case PP_MODULE_MACRO: {
+ ModuleMacros.push_back(ModuleMacroRecord());
+ auto &Info = ModuleMacros.back();
+ Info.SubModID = getGlobalSubmoduleID(M, Record[0]);
+ Info.MI = getMacro(getGlobalMacroID(M, Record[1]));
+ for (int I = 2, N = Record.size(); I != N; ++I)
+ Info.Overrides.push_back(getGlobalSubmoduleID(M, Record[I]));
+ continue;
+ }
- ModuleMacroInfo *MMI = getModuleMacro(PMInfo);
- if (!MMI)
- return;
+ default:
+ Error("malformed block record in AST file");
+ return;
+ }
- Module *Owner = getSubmodule(MMI->getSubmoduleID());
- if (Owner && Owner->NameVisibility == Module::Hidden) {
- // Macros in the owning module are hidden. Just remember this macro to
- // install if we make this module visible.
- HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI));
- } else {
- installImportedMacro(II, MMI, Owner);
+ // We found the macro directive history; that's the last record
+ // for this macro.
+ break;
}
-}
-
-void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
- ModuleFile &M, uint64_t Offset) {
- assert(M.Kind != MK_ImplicitModule && M.Kind != MK_ExplicitModule);
- BitstreamCursor &Cursor = M.MacroCursor;
- SavedStreamPosition SavedPosition(Cursor);
- Cursor.JumpToBit(Offset);
+ // Module macros are listed in reverse dependency order.
+ {
+ std::reverse(ModuleMacros.begin(), ModuleMacros.end());
+ llvm::SmallVector<ModuleMacro*, 8> Overrides;
+ for (auto &MMR : ModuleMacros) {
+ Overrides.clear();
+ for (unsigned ModID : MMR.Overrides) {
+ Module *Mod = getSubmodule(ModID);
+ auto *Macro = PP.getModuleMacro(Mod, II);
+ assert(Macro && "missing definition for overridden macro");
+ Overrides.push_back(Macro);
+ }
- llvm::BitstreamEntry Entry =
- Cursor.advance(BitstreamCursor::AF_DontPopBlockAtEnd);
- if (Entry.Kind != llvm::BitstreamEntry::Record) {
- Error("malformed block record in AST file");
- return;
+ bool Inserted = false;
+ Module *Owner = getSubmodule(MMR.SubModID);
+ PP.addModuleMacro(Owner, II, MMR.MI, Overrides, Inserted);
+ }
}
- RecordData Record;
- PreprocessorRecordTypes RecType =
- (PreprocessorRecordTypes)Cursor.readRecord(Entry.ID, Record);
- if (RecType != PP_MACRO_DIRECTIVE_HISTORY) {
- Error("malformed block record in AST file");
+ // Don't read the directive history for a module; we don't have anywhere
+ // to put it.
+ if (M.Kind == MK_ImplicitModule || M.Kind == MK_ExplicitModule)
return;
- }
// Deserialize the macro directives history in reverse source-order.
MacroDirective *Latest = nullptr, *Earliest = nullptr;
@@ -1861,31 +1808,12 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++];
switch (K) {
case MacroDirective::MD_Define: {
- GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
- MacroInfo *MI = getMacro(GMacID);
- SubmoduleID ImportedFrom = Record[Idx++];
- bool IsAmbiguous = Record[Idx++];
- llvm::SmallVector<unsigned, 4> Overrides;
- if (ImportedFrom) {
- Overrides.insert(Overrides.end(),
- &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]);
- Idx += Overrides.size() + 1;
- }
- DefMacroDirective *DefMD =
- PP.AllocateDefMacroDirective(MI, Loc, ImportedFrom, Overrides);
- DefMD->setAmbiguous(IsAmbiguous);
- MD = DefMD;
+ MacroInfo *MI = getMacro(getGlobalMacroID(M, Record[Idx++]));
+ MD = PP.AllocateDefMacroDirective(MI, Loc);
break;
}
case MacroDirective::MD_Undefine: {
- SubmoduleID ImportedFrom = Record[Idx++];
- llvm::SmallVector<unsigned, 4> Overrides;
- if (ImportedFrom) {
- Overrides.insert(Overrides.end(),
- &Record[Idx] + 1, &Record[Idx] + 1 + Record[Idx]);
- Idx += Overrides.size() + 1;
- }
- MD = PP.AllocateUndefMacroDirective(Loc, ImportedFrom, Overrides);
+ MD = PP.AllocateUndefMacroDirective(Loc);
break;
}
case MacroDirective::MD_Visibility:
@@ -1901,177 +1829,8 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
Earliest = MD;
}
- PP.setLoadedMacroDirective(II, Latest);
-}
-
-/// \brief For the given macro definitions, check if they are both in system
-/// modules.
-static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI,
- Module *NewOwner, ASTReader &Reader) {
- assert(PrevMI && NewMI);
- Module *PrevOwner = nullptr;
- if (SubmoduleID PrevModID = PrevMI->getOwningModuleID())
- PrevOwner = Reader.getSubmodule(PrevModID);
- SourceManager &SrcMgr = Reader.getSourceManager();
- bool PrevInSystem
- = PrevOwner? PrevOwner->IsSystem
- : SrcMgr.isInSystemHeader(PrevMI->getDefinitionLoc());
- bool NewInSystem
- = NewOwner? NewOwner->IsSystem
- : SrcMgr.isInSystemHeader(NewMI->getDefinitionLoc());
- if (PrevOwner && PrevOwner == NewOwner)
- return false;
- return PrevInSystem && NewInSystem;
-}
-
-void ASTReader::removeOverriddenMacros(IdentifierInfo *II,
- SourceLocation ImportLoc,
- AmbiguousMacros &Ambig,
- ArrayRef<SubmoduleID> Overrides) {
- for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) {
- SubmoduleID OwnerID = Overrides[OI];
-
- // If this macro is not yet visible, remove it from the hidden names list.
- // It won't be there if we're in the middle of making the owner visible.
- Module *Owner = getSubmodule(OwnerID);
- auto HiddenIt = HiddenNamesMap.find(Owner);
- if (HiddenIt != HiddenNamesMap.end()) {
- HiddenNames &Hidden = HiddenIt->second;
- HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II);
- if (HI != Hidden.HiddenMacros.end()) {
- // Register the macro now so we don't lose it when we re-export.
- PP.appendMacroDirective(II, HI->second->import(PP, ImportLoc));
-
- auto SubOverrides = HI->second->getOverriddenSubmodules();
- Hidden.HiddenMacros.erase(HI);
- removeOverriddenMacros(II, ImportLoc, Ambig, SubOverrides);
- }
- }
-
- // If this macro is already in our list of conflicts, remove it from there.
- Ambig.erase(
- std::remove_if(Ambig.begin(), Ambig.end(), [&](DefMacroDirective *MD) {
- return MD->getInfo()->getOwningModuleID() == OwnerID;
- }),
- Ambig.end());
- }
-}
-
-ASTReader::AmbiguousMacros *
-ASTReader::removeOverriddenMacros(IdentifierInfo *II,
- SourceLocation ImportLoc,
- ArrayRef<SubmoduleID> Overrides) {
- MacroDirective *Prev = PP.getMacroDirective(II);
- if (!Prev && Overrides.empty())
- return nullptr;
-
- DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective()
- : nullptr;
- if (PrevDef && PrevDef->isAmbiguous()) {
- // We had a prior ambiguity. Check whether we resolve it (or make it worse).
- AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
- Ambig.push_back(PrevDef);
-
- removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
-
- if (!Ambig.empty())
- return &Ambig;
-
- AmbiguousMacroDefs.erase(II);
- } else {
- // There's no ambiguity yet. Maybe we're introducing one.
- AmbiguousMacros Ambig;
- if (PrevDef)
- Ambig.push_back(PrevDef);
-
- removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
-
- if (!Ambig.empty()) {
- AmbiguousMacros &Result = AmbiguousMacroDefs[II];
- std::swap(Result, Ambig);
- return &Result;
- }
- }
-
- // We ended up with no ambiguity.
- return nullptr;
-}
-
-void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
- Module *Owner) {
- assert(II && Owner);
-
- SourceLocation ImportLoc = Owner->MacroVisibilityLoc;
- if (ImportLoc.isInvalid()) {
- // FIXME: If we made macros from this module visible but didn't provide a
- // source location for the import, we don't have a location for the macro.
- // Use the location at which the containing module file was first imported
- // for now.
- ImportLoc = MMI->F->DirectImportLoc;
- assert(ImportLoc.isValid() && "no import location for a visible macro?");
- }
-
- AmbiguousMacros *Prev =
- removeOverriddenMacros(II, ImportLoc, MMI->getOverriddenSubmodules());
-
- // Create a synthetic macro definition corresponding to the import (or null
- // if this was an undefinition of the macro).
- MacroDirective *Imported = MMI->import(PP, ImportLoc);
- DefMacroDirective *MD = dyn_cast<DefMacroDirective>(Imported);
-
- // If there's no ambiguity, just install the macro.
- if (!Prev) {
- PP.appendMacroDirective(II, Imported);
- return;
- }
- assert(!Prev->empty());
-
- if (!MD) {
- // We imported a #undef that didn't remove all prior definitions. The most
- // recent prior definition remains, and we install it in the place of the
- // imported directive, as if by a local #pragma pop_macro.
- MacroInfo *NewMI = Prev->back()->getInfo();
- Prev->pop_back();
- MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc);
-
- // Install our #undef first so that we don't lose track of it. We'll replace
- // this with whichever macro definition ends up winning.
- PP.appendMacroDirective(II, Imported);
- }
-
- // We're introducing a macro definition that creates or adds to an ambiguity.
- // We can resolve that ambiguity if this macro is token-for-token identical to
- // all of the existing definitions.
- MacroInfo *NewMI = MD->getInfo();
- assert(NewMI && "macro definition with no MacroInfo?");
- while (!Prev->empty()) {
- MacroInfo *PrevMI = Prev->back()->getInfo();
- assert(PrevMI && "macro definition with no MacroInfo?");
-
- // Before marking the macros as ambiguous, check if this is a case where
- // both macros are in system headers. If so, we trust that the system
- // did not get it wrong. This also handles cases where Clang's own
- // headers have a different spelling of certain system macros:
- // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
- // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
- //
- // FIXME: Remove the defined-in-system-headers check. clang's limits.h
- // overrides the system limits.h's macros, so there's no conflict here.
- if (NewMI != PrevMI &&
- !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) &&
- !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this))
- break;
-
- // The previous definition is the same as this one (or both are defined in
- // system modules so we can assume they're equivalent); we don't need to
- // track it any more.
- Prev->pop_back();
- }
-
- if (!Prev->empty())
- MD->setAmbiguous(true);
-
- PP.appendMacroDirective(II, MD);
+ if (Latest)
+ PP.setLoadedMacroDirective(II, Latest);
}
ASTReader::InputFileInfo
@@ -2426,6 +2185,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
}
+ case KNOWN_MODULE_FILES:
+ break;
+
case LANGUAGE_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
// FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
@@ -2440,7 +2202,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case TARGET_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
- ParseTargetOptions(Record, Complain, *Listener) &&
+ ParseTargetOptions(Record, Complain, *Listener,
+ AllowCompatibleConfigurationMismatch) &&
!DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
@@ -2543,7 +2306,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case INPUT_FILE_OFFSETS:
NumInputs = Record[0];
NumUserInputs = Record[1];
- F.InputFileOffsets = (const uint32_t *)Blob.data();
+ F.InputFileOffsets = (const uint64_t *)Blob.data();
F.InputFilesLoaded.resize(NumInputs);
break;
}
@@ -2795,6 +2558,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case EAGERLY_DESERIALIZED_DECLS:
+ // FIXME: Skip reading this record if our ASTConsumer doesn't care
+ // about "interesting" decls (for instance, if we're building a module).
for (unsigned I = 0, N = Record.size(); I != N; ++I)
EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I]));
break;
@@ -2859,11 +2624,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
- case LOCALLY_SCOPED_EXTERN_C_DECLS:
- for (unsigned I = 0, N = Record.size(); I != N; ++I)
- LocallyScopedExternCDecls.push_back(getGlobalDeclID(F, Record[I]));
- break;
-
case SELECTOR_OFFSETS: {
F.SelectorOffsets = (const uint32_t *)Blob.data();
F.LocalNumSelectors = Record[0];
@@ -3066,11 +2826,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
- case DYNAMIC_CLASSES:
- for (unsigned I = 0, N = Record.size(); I != N; ++I)
- DynamicClasses.push_back(getGlobalDeclID(F, Record[I]));
- break;
-
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
Error("Invalid existing PendingInstantiations");
@@ -3172,16 +2927,26 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case OBJC_CATEGORIES:
F.ObjCCategories.swap(Record);
break;
-
+
case CXX_BASE_SPECIFIER_OFFSETS: {
if (F.LocalNumCXXBaseSpecifiers != 0) {
Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
return Failure;
}
-
+
F.LocalNumCXXBaseSpecifiers = Record[0];
F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data();
- NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers;
+ break;
+ }
+
+ case CXX_CTOR_INITIALIZERS_OFFSETS: {
+ if (F.LocalNumCXXCtorInitializers != 0) {
+ Error("duplicate CXX_CTOR_INITIALIZERS_OFFSETS record in AST file");
+ return Failure;
+ }
+
+ F.LocalNumCXXCtorInitializers = Record[0];
+ F.CXXCtorInitializersOffsets = (const uint32_t *)Blob.data();
break;
}
@@ -3256,6 +3021,18 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
ReadSourceLocation(F, Record, I).getRawEncoding());
}
break;
+ case DELETE_EXPRS_TO_ANALYZE:
+ for (unsigned I = 0, N = Record.size(); I != N;) {
+ DelayedDeleteExprs.push_back(getGlobalDeclID(F, Record[I++]));
+ const uint64_t Count = Record[I++];
+ DelayedDeleteExprs.push_back(Count);
+ for (uint64_t C = 0; C < Count; ++C) {
+ DelayedDeleteExprs.push_back(ReadSourceLocation(F, Record, I).getRawEncoding());
+ bool IsArrayForm = Record[I++] == 1;
+ DelayedDeleteExprs.push_back(IsArrayForm);
+ }
+ }
+ break;
case IMPORTED_MODULES: {
if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) {
@@ -3288,16 +3065,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case MERGED_DECLARATIONS: {
- for (unsigned Idx = 0; Idx < Record.size(); /* increment in loop */) {
- GlobalDeclID CanonID = getGlobalDeclID(F, Record[Idx++]);
- SmallVectorImpl<GlobalDeclID> &Decls = StoredMergedDecls[CanonID];
- for (unsigned N = Record[Idx++]; N > 0; --N)
- Decls.push_back(getGlobalDeclID(F, Record[Idx++]));
- }
- break;
- }
-
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
@@ -3322,11 +3089,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
- case MACRO_TABLE: {
- // FIXME: Not used yet.
- break;
- }
-
case LATE_PARSED_TEMPLATE: {
LateParsedTemplates.append(Record.begin(), Record.end());
break;
@@ -3472,10 +3234,9 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
}
}
-void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
- bool FromFinalization) {
- // FIXME: Only do this if Owner->NameVisibility == AllVisible.
- for (Decl *D : Names.HiddenDecls) {
+void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
+ assert(Owner->NameVisibility != Module::Hidden && "nothing to make visible?");
+ for (Decl *D : Names) {
bool wasHidden = D->Hidden;
D->Hidden = false;
@@ -3485,22 +3246,11 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
}
}
}
-
- assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) &&
- "nothing to make visible?");
- for (const auto &Macro : Names.HiddenMacros) {
- if (FromFinalization)
- PP.appendMacroDirective(Macro.first,
- Macro.second->import(PP, SourceLocation()));
- else
- installImportedMacro(Macro.first, Macro.second, Owner);
- }
}
void ASTReader::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility,
- SourceLocation ImportLoc,
- bool Complain) {
+ SourceLocation ImportLoc) {
llvm::SmallPtrSet<Module *, 4> Visited;
SmallVector<Module *, 4> Stack;
Stack.push_back(Mod);
@@ -3519,9 +3269,6 @@ void ASTReader::makeModuleVisible(Module *Mod,
}
// Update the module's name visibility.
- if (NameVisibility >= Module::MacrosVisible &&
- Mod->NameVisibility < Module::MacrosVisible)
- Mod->MacroVisibilityLoc = ImportLoc;
Mod->NameVisibility = NameVisibility;
// If we've already deserialized any names from this module,
@@ -3530,8 +3277,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
if (Hidden != HiddenNamesMap.end()) {
auto HiddenNames = std::move(*Hidden);
HiddenNamesMap.erase(Hidden);
- makeNamesVisible(HiddenNames.second, HiddenNames.first,
- /*FromFinalization*/false);
+ makeNamesVisible(HiddenNames.second, HiddenNames.first);
assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() &&
"making names visible added hidden names");
}
@@ -3545,20 +3291,6 @@ void ASTReader::makeModuleVisible(Module *Mod,
if (Visited.insert(Exported).second)
Stack.push_back(Exported);
}
-
- // Detect any conflicts.
- if (Complain) {
- assert(ImportLoc.isValid() && "Missing import location");
- for (unsigned I = 0, N = Mod->Conflicts.size(); I != N; ++I) {
- if (Mod->Conflicts[I].Other->NameVisibility >= NameVisibility) {
- Diag(ImportLoc, diag::warn_module_conflict)
- << Mod->getFullModuleName()
- << Mod->Conflicts[I].Other->getFullModuleName()
- << Mod->Conflicts[I].Message;
- // FIXME: Need note where the other module was imported.
- }
- }
- }
}
}
@@ -3717,7 +3449,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
case UnresolvedModuleRef::Import:
if (ResolvedMod)
- Unresolved.Mod->Imports.push_back(ResolvedMod);
+ Unresolved.Mod->Imports.insert(ResolvedMod);
continue;
case UnresolvedModuleRef::Export:
@@ -3785,6 +3517,14 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
+static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
+ return Stream.Read(8) == 'C' &&
+ Stream.Read(8) == 'P' &&
+ Stream.Read(8) == 'C' &&
+ Stream.Read(8) == 'H';
+}
+
ASTReader::ASTReadResult
ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type,
@@ -3854,10 +3594,7 @@ ASTReader::ReadASTCore(StringRef FileName,
F.SizeInBits = F.Buffer->getBufferSize() * 8;
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream)) {
Diag(diag::err_not_a_pch_file) << FileName;
return Failure;
}
@@ -3924,7 +3661,7 @@ ASTReader::ReadASTCore(StringRef FileName,
return Success;
}
-void ASTReader::InitializeContext() {
+void ASTReader::InitializeContext() {
// If there's a listener, notify them that we "read" the translation unit.
if (DeserializationListener)
DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
@@ -4047,24 +3784,19 @@ void ASTReader::InitializeContext() {
}
// Re-export any modules that were imported by a non-module AST file.
- // FIXME: This does not make macro-only imports visible again. It also doesn't
- // make #includes mapped to module imports visible.
+ // FIXME: This does not make macro-only imports visible again.
for (auto &Import : ImportedModules) {
- if (Module *Imported = getSubmodule(Import.ID))
+ if (Module *Imported = getSubmodule(Import.ID)) {
makeModuleVisible(Imported, Module::AllVisible,
- /*ImportLoc=*/Import.ImportLoc,
- /*Complain=*/false);
+ /*ImportLoc=*/Import.ImportLoc);
+ PP.makeModuleVisible(Imported, Import.ImportLoc);
+ }
}
ImportedModules.clear();
}
void ASTReader::finalizeForWriting() {
- while (!HiddenNamesMap.empty()) {
- auto HiddenNames = std::move(*HiddenNamesMap.begin());
- HiddenNamesMap.erase(HiddenNamesMap.begin());
- makeNamesVisible(HiddenNames.second, HiddenNames.first,
- /*FromFinalization*/true);
- }
+ // Nothing to do for now.
}
/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
@@ -4097,14 +3829,12 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
}
}
+/// \brief Reads and return the signature record from \p StreamFile's control
+/// block, or else returns 0.
static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
BitstreamCursor Stream(StreamFile);
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream))
return 0;
- }
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
@@ -4146,10 +3876,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream)) {
Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
return std::string();
}
@@ -4184,16 +3911,19 @@ namespace {
const LangOptions &ExistingLangOpts;
const TargetOptions &ExistingTargetOpts;
const PreprocessorOptions &ExistingPPOpts;
+ std::string ExistingModuleCachePath;
FileManager &FileMgr;
-
+
public:
SimplePCHValidator(const LangOptions &ExistingLangOpts,
const TargetOptions &ExistingTargetOpts,
const PreprocessorOptions &ExistingPPOpts,
+ StringRef ExistingModuleCachePath,
FileManager &FileMgr)
: ExistingLangOpts(ExistingLangOpts),
ExistingTargetOpts(ExistingTargetOpts),
ExistingPPOpts(ExistingPPOpts),
+ ExistingModuleCachePath(ExistingModuleCachePath),
FileMgr(FileMgr)
{
}
@@ -4203,9 +3933,17 @@ namespace {
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
AllowCompatibleDifferences);
}
- bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain) override {
- return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr);
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
+ return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr,
+ AllowCompatibleDifferences);
+ }
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) override {
+ return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ ExistingModuleCachePath,
+ nullptr, ExistingLangOpts);
}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool Complain,
@@ -4220,6 +3958,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
FileManager &FileMgr,
ASTReaderListener &Listener) {
// Open the AST file.
+ // FIXME: This allows use of the VFS; we do not allow use of the
+ // VFS when actually loading a module.
auto Buffer = FileMgr.getBufferForFile(Filename);
if (!Buffer) {
return true;
@@ -4232,12 +3972,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
- if (Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'P' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(8) != 'H') {
+ if (!startsWithASTFileMagic(Stream))
return true;
- }
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
@@ -4310,7 +4046,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
break;
case TARGET_OPTIONS:
- if (ParseTargetOptions(Record, false, Listener))
+ if (ParseTargetOptions(Record, false, Listener,
+ /*AllowCompatibleConfigurationMismatch*/ false))
return true;
break;
@@ -4343,7 +4080,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
unsigned NumInputFiles = Record[0];
unsigned NumUserFiles = Record[1];
- const uint32_t *InputFileOffs = (const uint32_t *)Blob.data();
+ const uint64_t *InputFileOffs = (const uint64_t *)Blob.data();
for (unsigned I = 0; I != NumInputFiles; ++I) {
// Go find this input file.
bool isSystemFile = I >= NumUserFiles;
@@ -4389,6 +4126,20 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
break;
}
+ case KNOWN_MODULE_FILES: {
+ // Known-but-not-technically-used module files are treated as imports.
+ if (!NeedsImports)
+ break;
+
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(Filename, ModuleDir);
+ Listener.visitImport(Filename);
+ }
+ break;
+ }
+
default:
// No other validation to perform.
break;
@@ -4401,8 +4152,10 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename,
FileManager &FileMgr,
const LangOptions &LangOpts,
const TargetOptions &TargetOpts,
- const PreprocessorOptions &PPOpts) {
- SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, FileMgr);
+ const PreprocessorOptions &PPOpts,
+ std::string ExistingModuleCachePath) {
+ SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
+ ExistingModuleCachePath, FileMgr);
return !readASTFileControlBlock(Filename, FileMgr, validator);
}
@@ -4529,13 +4282,19 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_UMBRELLA_HEADER: {
- if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) {
+ std::string Filename = Blob;
+ ResolveImportedPath(F, Filename);
+ if (auto *Umbrella = PP.getFileManager().getFile(Filename)) {
if (!CurrentModule->getUmbrellaHeader())
- ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
- else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
- Error("mismatched umbrella headers in submodule");
- return OutOfDate;
+ ModMap.setUmbrellaHeader(CurrentModule, Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaHeader().Entry != Umbrella) {
+ // This can be a spurious difference caused by changing the VFS to
+ // point to a different copy of the file, and it is too late to
+ // to rebuild safely.
+ // FIXME: If we wrote the virtual paths instead of the 'real' paths,
+ // after input file validation only real problems would remain and we
+ // could just error. For now, assume it's okay.
+ break;
}
}
break;
@@ -4561,11 +4320,12 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
case SUBMODULE_UMBRELLA_DIR: {
- if (const DirectoryEntry *Umbrella
- = PP.getFileManager().getDirectory(Blob)) {
+ std::string Dirname = Blob;
+ ResolveImportedPath(F, Dirname);
+ if (auto *Umbrella = PP.getFileManager().getDirectory(Dirname)) {
if (!CurrentModule->getUmbrellaDir())
- ModMap.setUmbrellaDir(CurrentModule, Umbrella);
- else if (CurrentModule->getUmbrellaDir() != Umbrella) {
+ ModMap.setUmbrellaDir(CurrentModule, Umbrella, Blob);
+ else if (CurrentModule->getUmbrellaDir().Entry != Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella directories in submodule");
return OutOfDate;
@@ -4696,9 +4456,9 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
AllowCompatibleDifferences);
}
-bool ASTReader::ParseTargetOptions(const RecordData &Record,
- bool Complain,
- ASTReaderListener &Listener) {
+bool ASTReader::ParseTargetOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences) {
unsigned Idx = 0;
TargetOptions TargetOpts;
TargetOpts.Triple = ReadString(Record, Idx);
@@ -4711,7 +4471,8 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record,
TargetOpts.Features.push_back(ReadString(Record, Idx));
}
- return Listener.ReadTargetOptions(TargetOpts, Complain);
+ return Listener.ReadTargetOptions(TargetOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain,
@@ -4773,8 +4534,10 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
HSOpts.UseStandardSystemIncludes = Record[Idx++];
HSOpts.UseStandardCXXIncludes = Record[Idx++];
HSOpts.UseLibcxx = Record[Idx++];
+ std::string SpecificModuleCachePath = ReadString(Record, Idx);
- return Listener.ReadHeaderSearchOptions(HSOpts, Complain);
+ return Listener.ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
+ Complain);
}
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
@@ -4823,21 +4586,22 @@ ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
return std::make_pair(M, LocalIndex);
}
-std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+llvm::iterator_range<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());
+ return llvm::make_range(PreprocessingRecord::iterator(),
+ PreprocessingRecord::iterator());
}
-std::pair<ASTReader::ModuleDeclIterator, ASTReader::ModuleDeclIterator>
+llvm::iterator_range<ASTReader::ModuleDeclIterator>
ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
- return std::make_pair(ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
- ModuleDeclIterator(this, &Mod,
- Mod.FileSortedDecls + Mod.NumFileSortedDecls));
+ return llvm::make_range(
+ ModuleDeclIterator(this, &Mod, Mod.FileSortedDecls),
+ ModuleDeclIterator(this, &Mod,
+ Mod.FileSortedDecls + Mod.NumFileSortedDecls));
}
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
@@ -4873,13 +4637,14 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
case PPD_MACRO_EXPANSION: {
bool isBuiltin = Record[0];
IdentifierInfo *Name = nullptr;
- MacroDefinition *Def = nullptr;
+ MacroDefinitionRecord *Def = nullptr;
if (isBuiltin)
Name = getLocalIdentifier(M, Record[1]);
else {
- PreprocessedEntityID
- GlobalID = getGlobalPreprocessedEntityID(M, Record[1]);
- Def =cast<MacroDefinition>(PPRec.getLoadedPreprocessedEntity(GlobalID-1));
+ PreprocessedEntityID GlobalID =
+ getGlobalPreprocessedEntityID(M, Record[1]);
+ Def = cast<MacroDefinitionRecord>(
+ PPRec.getLoadedPreprocessedEntity(GlobalID - 1));
}
MacroExpansion *ME;
@@ -4895,8 +4660,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
// Decode the identifier info and then check again; if the macro is
// still defined and associated with the identifier,
IdentifierInfo *II = getLocalIdentifier(M, Record[0]);
- MacroDefinition *MD
- = new (PPRec) MacroDefinition(II, Range);
+ MacroDefinitionRecord *MD = new (PPRec) MacroDefinitionRecord(II, Range);
if (DeserializationListener)
DeserializationListener->MacroDefinitionRead(PPID, MD);
@@ -6081,6 +5845,12 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) {
return GetDecl(ID);
}
+template<typename TemplateSpecializationDecl>
+static void completeRedeclChainForTemplateSpecialization(Decl *D) {
+ if (auto *TSD = dyn_cast<TemplateSpecializationDecl>(D))
+ TSD->getSpecializedTemplate()->LoadLazySpecializations();
+}
+
void ASTReader::CompleteRedeclChain(const Decl *D) {
if (NumCurrentElementsDeserializing) {
// We arrange to not care about the complete redeclaration chain while we're
@@ -6114,6 +5884,47 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
D->getDeclContext()->decls_begin();
}
}
+
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ CTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
+ VTSD->getSpecializedTemplate()->LoadLazySpecializations();
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (auto *Template = FD->getPrimaryTemplate())
+ Template->LoadLazySpecializations();
+ }
+}
+
+uint64_t ASTReader::ReadCXXCtorInitializersRef(ModuleFile &M,
+ const RecordData &Record,
+ unsigned &Idx) {
+ if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXCtorInitializers) {
+ Error("malformed AST file: missing C++ ctor initializers");
+ return 0;
+ }
+
+ unsigned LocalID = Record[Idx++];
+ return getGlobalBitOffset(M, M.CXXCtorInitializersOffsets[LocalID - 1]);
+}
+
+CXXCtorInitializer **
+ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) {
+ RecordLocation Loc = getLocalBitOffset(Offset);
+ BitstreamCursor &Cursor = Loc.F->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(Loc.Offset);
+ ReadingKindTracker ReadingKind(Read_Decl, *this);
+
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record);
+ if (RecCode != DECL_CXX_CTOR_INITIALIZERS) {
+ Error("malformed AST file: missing C++ ctor initializers");
+ return nullptr;
+ }
+
+ unsigned Idx = 0;
+ return ReadCXXCtorInitializers(*Loc.F, Record, Idx);
}
uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M,
@@ -6165,6 +5976,10 @@ ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
ModuleFile &M) const {
+ // Predefined decls aren't from any module.
+ if (ID < NUM_PREDEF_DECL_IDS)
+ return false;
+
GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
return &M == I->second;
@@ -6197,39 +6012,55 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
return ReadSourceLocation(*Rec.F, RawLocation);
}
-Decl *ASTReader::GetExistingDecl(DeclID ID) {
- if (ID < NUM_PREDEF_DECL_IDS) {
- switch ((PredefinedDeclIDs)ID) {
- case PREDEF_DECL_NULL_ID:
- return nullptr;
+static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
+ switch (ID) {
+ case PREDEF_DECL_NULL_ID:
+ return nullptr;
+
+ case PREDEF_DECL_TRANSLATION_UNIT_ID:
+ return Context.getTranslationUnitDecl();
- case PREDEF_DECL_TRANSLATION_UNIT_ID:
- return Context.getTranslationUnitDecl();
+ case PREDEF_DECL_OBJC_ID_ID:
+ return Context.getObjCIdDecl();
- case PREDEF_DECL_OBJC_ID_ID:
- return Context.getObjCIdDecl();
+ case PREDEF_DECL_OBJC_SEL_ID:
+ return Context.getObjCSelDecl();
- case PREDEF_DECL_OBJC_SEL_ID:
- return Context.getObjCSelDecl();
+ case PREDEF_DECL_OBJC_CLASS_ID:
+ return Context.getObjCClassDecl();
- case PREDEF_DECL_OBJC_CLASS_ID:
- return Context.getObjCClassDecl();
+ case PREDEF_DECL_OBJC_PROTOCOL_ID:
+ return Context.getObjCProtocolDecl();
- case PREDEF_DECL_OBJC_PROTOCOL_ID:
- return Context.getObjCProtocolDecl();
+ case PREDEF_DECL_INT_128_ID:
+ return Context.getInt128Decl();
- case PREDEF_DECL_INT_128_ID:
- return Context.getInt128Decl();
+ case PREDEF_DECL_UNSIGNED_INT_128_ID:
+ return Context.getUInt128Decl();
- case PREDEF_DECL_UNSIGNED_INT_128_ID:
- return Context.getUInt128Decl();
+ case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
+ return Context.getObjCInstanceTypeDecl();
- case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
- return Context.getObjCInstanceTypeDecl();
+ case PREDEF_DECL_BUILTIN_VA_LIST_ID:
+ return Context.getBuiltinVaListDecl();
- case PREDEF_DECL_BUILTIN_VA_LIST_ID:
- return Context.getBuiltinVaListDecl();
+ case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
+ return Context.getExternCContextDecl();
+ }
+ llvm_unreachable("PredefinedDeclIDs unknown enum value");
+}
+
+Decl *ASTReader::GetExistingDecl(DeclID ID) {
+ if (ID < NUM_PREDEF_DECL_IDS) {
+ Decl *D = getPredefinedDecl(Context, (PredefinedDeclIDs)ID);
+ if (D) {
+ // Track that we have merged the declaration with ID \p ID into the
+ // pre-existing predefined declaration \p D.
+ auto &Merged = MergedDecls[D->getCanonicalDecl()];
+ if (Merged.empty())
+ Merged.push_back(ID);
}
+ return D;
}
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
@@ -6326,10 +6157,7 @@ namespace {
PredefsVisited[I] = false;
}
- static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
- if (Preorder)
- return false;
-
+ static bool visitPostorder(ModuleFile &M, void *UserData) {
FindExternalLexicalDeclsVisitor *This
= static_cast<FindExternalLexicalDeclsVisitor *>(UserData);
@@ -6371,7 +6199,8 @@ ExternalLoadResult ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
// There might be lexical decls in multiple modules, for the TU at
// least. Walk all of the modules in the order they were loaded.
FindExternalLexicalDeclsVisitor Visitor(*this, DC, isKindWeWant, Decls);
- ModuleMgr.visitDepthFirst(&FindExternalLexicalDeclsVisitor::visit, &Visitor);
+ ModuleMgr.visitDepthFirst(
+ nullptr, &FindExternalLexicalDeclsVisitor::visitPostorder, &Visitor);
++NumLexicalDeclContextsRead;
return ELR_Success;
}
@@ -6460,13 +6289,16 @@ namespace {
ArrayRef<const DeclContext *> Contexts;
DeclarationName Name;
SmallVectorImpl<NamedDecl *> &Decls;
+ llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet;
public:
DeclContextNameLookupVisitor(ASTReader &Reader,
ArrayRef<const DeclContext *> Contexts,
DeclarationName Name,
- SmallVectorImpl<NamedDecl *> &Decls)
- : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
+ SmallVectorImpl<NamedDecl *> &Decls,
+ llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet)
+ : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls),
+ DeclSet(DeclSet) { }
static bool visit(ModuleFile &M, void *UserData) {
DeclContextNameLookupVisitor *This
@@ -6515,7 +6347,8 @@ namespace {
// Record this declaration.
FoundAnything = true;
- This->Decls.push_back(ND);
+ if (This->DeclSet.insert(ND).second)
+ This->Decls.push_back(ND);
}
return FoundAnything;
@@ -6555,6 +6388,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Deserializing LookupResults(this);
SmallVector<NamedDecl *, 64> Decls;
+ llvm::SmallPtrSet<NamedDecl*, 64> DeclSet;
// Compute the declaration contexts we need to look into. Multiple such
// declaration contexts occur when two declaration contexts from disjoint
@@ -6572,7 +6406,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
}
auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) {
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
+ DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls, DeclSet);
// If we can definitively determine which module file to look into,
// only look there. Otherwise, look in all module files.
@@ -6592,19 +6426,14 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
// individually, because finding an entity in one of them doesn't imply that
// we can't find a different entity in another one.
if (isa<CXXRecordDecl>(DC)) {
- auto Kind = Name.getNameKind();
- if (Kind == DeclarationName::CXXConstructorName ||
- Kind == DeclarationName::CXXDestructorName ||
- (Kind == DeclarationName::CXXOperatorName &&
- Name.getCXXOverloadedOperator() == OO_Equal)) {
- auto Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end()) {
- for (unsigned I = 0; I != Merged->second.size(); ++I) {
- LookUpInContexts(Merged->second[I]);
- // We might have just added some more merged lookups. If so, our
- // iterator is now invalid, so grab a fresh one before continuing.
- Merged = MergedLookups.find(DC);
- }
+ auto Merged = MergedLookups.find(DC);
+ if (Merged != MergedLookups.end()) {
+ for (unsigned I = 0; I != Merged->second.size(); ++I) {
+ const DeclContext *Context = Merged->second[I];
+ LookUpInContexts(Context);
+ // We might have just added some more merged lookups. If so, our
+ // iterator is now invalid, so grab a fresh one before continuing.
+ Merged = MergedLookups.find(DC);
}
}
}
@@ -6621,6 +6450,7 @@ namespace {
ASTReader &Reader;
SmallVectorImpl<const DeclContext *> &Contexts;
DeclsMap &Decls;
+ llvm::SmallPtrSet<NamedDecl *, 256> DeclSet;
bool VisitAll;
public:
@@ -6665,7 +6495,8 @@ namespace {
// Record this declaration.
FoundAnything = true;
- This->Decls[ND->getDeclName()].push_back(ND);
+ if (This->DeclSet.insert(ND).second)
+ This->Decls[ND->getDeclName()].push_back(ND);
}
}
@@ -6731,6 +6562,12 @@ void ASTReader::PassInterestingDeclsToConsumer() {
SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
true);
+ // Ensure that we've loaded all potentially-interesting declarations
+ // that need to be eagerly loaded.
+ for (auto ID : EagerlyDeserializedDecls)
+ GetDecl(ID);
+ EagerlyDeserializedDecls.clear();
+
while (!InterestingDecls.empty()) {
Decl *D = InterestingDecls.front();
InterestingDecls.pop_front();
@@ -6749,17 +6586,11 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;
- if (!Consumer)
- return;
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
- for (unsigned I = 0, N = EagerlyDeserializedDecls.size(); I != N; ++I) {
- // Force deserialization of this decl, which will cause it to be queued for
- // passing to the consumer.
- GetDecl(EagerlyDeserializedDecls[I]);
- }
- EagerlyDeserializedDecls.clear();
-
- PassInterestingDeclsToConsumer();
+ if (DeserializationListener)
+ DeserializationListener->ReaderInitialized(this);
}
void ASTReader::PrintStats() {
@@ -7195,6 +7026,21 @@ void ASTReader::ReadUndefinedButUsed(
}
}
+void ASTReader::ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) {
+ for (unsigned Idx = 0, N = DelayedDeleteExprs.size(); Idx != N;) {
+ FieldDecl *FD = cast<FieldDecl>(GetDecl(DelayedDeleteExprs[Idx++]));
+ uint64_t Count = DelayedDeleteExprs[Idx++];
+ for (uint64_t C = 0; C < Count; ++C) {
+ SourceLocation DeleteLoc =
+ SourceLocation::getFromRawEncoding(DelayedDeleteExprs[Idx++]);
+ const bool IsArrayForm = DelayedDeleteExprs[Idx++];
+ Exprs[FD].push_back(std::make_pair(DeleteLoc, IsArrayForm));
+ }
+ }
+}
+
void ASTReader::ReadTentativeDefinitions(
SmallVectorImpl<VarDecl *> &TentativeDefs) {
for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
@@ -7237,16 +7083,6 @@ void ASTReader::ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {
ExtVectorDecls.clear();
}
-void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
- for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) {
- CXXRecordDecl *D
- = dyn_cast_or_null<CXXRecordDecl>(GetDecl(DynamicClasses[I]));
- if (D)
- Decls.push_back(D);
- }
- DynamicClasses.clear();
-}
-
void ASTReader::ReadUnusedLocalTypedefNameCandidates(
llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N;
@@ -7259,17 +7095,6 @@ void ASTReader::ReadUnusedLocalTypedefNameCandidates(
UnusedLocalTypedefNameCandidates.clear();
}
-void
-ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) {
- for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) {
- NamedDecl *D
- = dyn_cast_or_null<NamedDecl>(GetDecl(LocallyScopedExternCDecls[I]));
- if (D)
- Decls.push_back(D);
- }
- LocallyScopedExternCDecls.clear();
-}
-
void ASTReader::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
if (ReferencedSelectorsData.empty())
@@ -7333,7 +7158,7 @@ void ASTReader::ReadPendingInstantiations(
}
void ASTReader::ReadLateParsedTemplates(
- llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N;
/* In loop */) {
FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++]));
@@ -7349,7 +7174,7 @@ void ASTReader::ReadLateParsedTemplates(
for (unsigned T = 0; T < TokN; ++T)
LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx));
- LPTMap[FD] = LT;
+ LPTMap.insert(std::make_pair(FD, LT));
}
LateParsedTemplates.clear();
@@ -7840,92 +7665,89 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
return Result;
}
-std::pair<CXXCtorInitializer **, unsigned>
+CXXCtorInitializer **
ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
- CXXCtorInitializer **CtorInitializers = nullptr;
unsigned NumInitializers = Record[Idx++];
- if (NumInitializers) {
- CtorInitializers
- = new (Context) CXXCtorInitializer*[NumInitializers];
- for (unsigned i=0; i != NumInitializers; ++i) {
- TypeSourceInfo *TInfo = nullptr;
- bool IsBaseVirtual = false;
- FieldDecl *Member = nullptr;
- IndirectFieldDecl *IndirectMember = nullptr;
-
- CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
- switch (Type) {
- case CTOR_INITIALIZER_BASE:
- TInfo = GetTypeSourceInfo(F, Record, Idx);
- IsBaseVirtual = Record[Idx++];
- break;
-
- case CTOR_INITIALIZER_DELEGATING:
- TInfo = GetTypeSourceInfo(F, Record, Idx);
- break;
+ assert(NumInitializers && "wrote ctor initializers but have no inits");
+ auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers];
+ for (unsigned i = 0; i != NumInitializers; ++i) {
+ TypeSourceInfo *TInfo = nullptr;
+ bool IsBaseVirtual = false;
+ FieldDecl *Member = nullptr;
+ IndirectFieldDecl *IndirectMember = nullptr;
- case CTOR_INITIALIZER_MEMBER:
- Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
- break;
+ CtorInitializerType Type = (CtorInitializerType)Record[Idx++];
+ switch (Type) {
+ case CTOR_INITIALIZER_BASE:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ IsBaseVirtual = Record[Idx++];
+ break;
- case CTOR_INITIALIZER_INDIRECT_MEMBER:
- IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
- break;
- }
+ case CTOR_INITIALIZER_DELEGATING:
+ TInfo = GetTypeSourceInfo(F, Record, Idx);
+ break;
- SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
- Expr *Init = ReadExpr(F);
- SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
- SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
- bool IsWritten = Record[Idx++];
- unsigned SourceOrderOrNumArrayIndices;
- SmallVector<VarDecl *, 8> Indices;
- if (IsWritten) {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- } else {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- Indices.reserve(SourceOrderOrNumArrayIndices);
- for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
- Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
- }
+ case CTOR_INITIALIZER_MEMBER:
+ Member = ReadDeclAs<FieldDecl>(F, Record, Idx);
+ break;
- CXXCtorInitializer *BOMInit;
- if (Type == CTOR_INITIALIZER_BASE) {
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual,
- LParenLoc, Init, RParenLoc,
- MemberOrEllipsisLoc);
- } else if (Type == CTOR_INITIALIZER_DELEGATING) {
- BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc,
- Init, RParenLoc);
- } else if (IsWritten) {
- if (Member)
- BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc);
- else
- BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
- MemberOrEllipsisLoc, LParenLoc,
- Init, RParenLoc);
+ case CTOR_INITIALIZER_INDIRECT_MEMBER:
+ IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx);
+ break;
+ }
+
+ SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ Expr *Init = ReadExpr(F);
+ SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
+ SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
+ bool IsWritten = Record[Idx++];
+ unsigned SourceOrderOrNumArrayIndices;
+ SmallVector<VarDecl *, 8> Indices;
+ if (IsWritten) {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ } else {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ Indices.reserve(SourceOrderOrNumArrayIndices);
+ for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+ Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
+ }
+
+ CXXCtorInitializer *BOMInit;
+ if (Type == CTOR_INITIALIZER_BASE) {
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init,
+ RParenLoc, MemberOrEllipsisLoc);
+ } else if (Type == CTOR_INITIALIZER_DELEGATING) {
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc);
+ } else if (IsWritten) {
+ if (Member)
+ BOMInit = new (Context) CXXCtorInitializer(
+ Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc);
+ else
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
+ } else {
+ if (IndirectMember) {
+ assert(Indices.empty() && "Indirect field improperly initialized");
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
} else {
- if (IndirectMember) {
- assert(Indices.empty() && "Indirect field improperly initialized");
- BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember,
- MemberOrEllipsisLoc, LParenLoc,
- Init, RParenLoc);
- } else {
- BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc,
- Indices.data(), Indices.size());
- }
+ BOMInit = CXXCtorInitializer::Create(
+ Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc,
+ Indices.data(), Indices.size());
}
-
- if (IsWritten)
- BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
- CtorInitializers[i] = BOMInit;
}
+
+ if (IsWritten)
+ BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
+ CtorInitializers[i] = BOMInit;
}
- return std::make_pair(CtorInitializers, NumInitializers);
+ return CtorInitializers;
}
NestedNameSpecifier *
@@ -8203,7 +8025,7 @@ void ASTReader::getInputFiles(ModuleFile &F,
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
- if (Module *M = D->getOwningModule())
+ if (Module *M = D->getImportedOwningModule())
return M->getFullModuleName();
// Otherwise, use the name of the top-level module the decl is within.
@@ -8243,9 +8065,10 @@ void ASTReader::finishPendingActions() {
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
- loadPendingDeclChain(PendingDeclChains[I]);
PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+ loadPendingDeclChain(PendingDeclChains[I]);
}
+ assert(PendingDeclChainsKnown.empty());
PendingDeclChains.clear();
// Make the most recent of the top-level declarations visible.
@@ -8298,7 +8121,12 @@ void ASTReader::finishPendingActions() {
loadDeclUpdateRecords(Update.first, Update.second);
}
}
-
+
+ // At this point, all update records for loaded decls are in place, so any
+ // fake class definitions should have become real.
+ assert(PendingFakeDefinitionData.empty() &&
+ "faked up a class definition but never saw the real one");
+
// If we deserialized any C++ or Objective-C class definitions, any
// Objective-C protocol definitions, or any redeclarable templates, make sure
// that all redeclarations point to the definitions. Note that this can only
@@ -8309,10 +8137,12 @@ void ASTReader::finishPendingActions() {
// Make sure that the TagType points at the definition.
const_cast<TagType*>(TagT)->decl = TD;
}
-
+
if (auto RD = dyn_cast<CXXRecordDecl>(D)) {
- for (auto R : RD->redecls()) {
- assert((R == D) == R->isThisDeclarationADefinition() &&
+ for (auto *R = getMostRecentExistingDecl(RD); R;
+ R = R->getPreviousDecl()) {
+ assert((R == D) ==
+ cast<CXXRecordDecl>(R)->isThisDeclarationADefinition() &&
"declaration thinks it's the definition but it isn't");
cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData;
}
@@ -8320,34 +8150,36 @@ void ASTReader::finishPendingActions() {
continue;
}
-
+
if (auto ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// Make sure that the ObjCInterfaceType points at the definition.
const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
->Decl = ID;
-
- for (auto R : ID->redecls())
- R->Data = ID->Data;
-
+
+ for (auto *R = getMostRecentExistingDecl(ID); R; R = R->getPreviousDecl())
+ cast<ObjCInterfaceDecl>(R)->Data = ID->Data;
+
continue;
}
-
+
if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) {
- for (auto R : PD->redecls())
- R->Data = PD->Data;
-
+ for (auto *R = getMostRecentExistingDecl(PD); R; R = R->getPreviousDecl())
+ cast<ObjCProtocolDecl>(R)->Data = PD->Data;
+
continue;
}
-
+
auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
- for (auto R : RTD->redecls())
- R->Common = RTD->Common;
+ for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
+ cast<RedeclarableTemplateDecl>(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.
+ // FIXME: There seems to be no point in delaying this, it does not depend
+ // on the redecl chains having been wired up.
for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) {
@@ -8364,6 +8196,11 @@ void ASTReader::finishPendingActions() {
MD->setLazyBody(PB->second);
}
PendingBodies.clear();
+
+ // Do some cleanup.
+ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
+ getContext().deduplicateMergedDefinitonsFor(ND);
+ PendingMergedDefinitionsToDeduplicate.clear();
}
void ASTReader::diagnoseOdrViolations() {
@@ -8440,6 +8277,10 @@ void ASTReader::diagnoseOdrViolations() {
// completed. We only really need to mark FieldDecls as invalid here.
if (!isa<TagDecl>(D))
D->setInvalidDecl();
+
+ // Ensure we don't accidentally recursively enter deserialization while
+ // we're producing our diagnostic.
+ Deserializing RecursionGuard(this);
std::string CanonDefModule =
getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
@@ -8461,6 +8302,13 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+ if (OdrMergeFailures.empty())
+ return;
+
+ // Ensure we don't accidentally recursively enter deserialization while
+ // we're producing our diagnostics.
+ Deserializing RecursionGuard(this);
+
// Issue any pending ODR-failure diagnostics.
for (auto &Merge : OdrMergeFailures) {
// If we've already pointed out a specific problem with this class, don't
@@ -8514,6 +8362,17 @@ void ASTReader::FinishedDeserializing() {
--NumCurrentElementsDeserializing;
if (NumCurrentElementsDeserializing == 0) {
+ // Propagate exception specification updates along redeclaration chains.
+ while (!PendingExceptionSpecUpdates.empty()) {
+ auto Updates = std::move(PendingExceptionSpecUpdates);
+ PendingExceptionSpecUpdates.clear();
+ for (auto Update : Updates) {
+ auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
+ SemaObj->UpdateExceptionSpec(Update.second,
+ FPT->getExtProtoInfo().ExceptionSpec);
+ }
+ }
+
diagnoseOdrViolations();
// We are not in recursive loading, so it's safe to pass the "interesting"
@@ -8524,7 +8383,18 @@ void ASTReader::FinishedDeserializing() {
}
void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
- D = D->getMostRecentDecl();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ // Remove any fake results before adding any real ones.
+ auto It = PendingFakeLookupResults.find(II);
+ if (It != PendingFakeLookupResults.end()) {
+ for (auto *ND : PendingFakeLookupResults[II])
+ SemaObj->IdResolver.RemoveDecl(ND);
+ // FIXME: this works around module+PCH performance issue.
+ // Rather than erase the result from the map, which is O(n), just clear
+ // the vector of NamedDecls.
+ It->second.clear();
+ }
+ }
if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) {
SemaObj->TUScope->AddDecl(D);
@@ -8562,8 +8432,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot,
NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0),
- PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0),
- ReadingKind(Read_None) {
+ PassingDeclsToConsumer(false), ReadingKind(Read_None) {
SourceMgr.setExternalSLocEntrySource(this);
}