Update aosp/master Clang for rebase to r222490.
Change-Id: Ic557ac55e97fbf6ee08771c7b7c3594777b0aefd
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index f18122d..1bbadfc 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -80,10 +80,14 @@
First->ReadModuleMapFile(ModuleMapPath);
Second->ReadModuleMapFile(ModuleMapPath);
}
-bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) {
- return First->ReadLanguageOptions(LangOpts, Complain) ||
- Second->ReadLanguageOptions(LangOpts, Complain);
+bool
+ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain,
+ bool AllowCompatibleDifferences) {
+ return First->ReadLanguageOptions(LangOpts, Complain,
+ AllowCompatibleDifferences) ||
+ Second->ReadLanguageOptions(LangOpts, Complain,
+ AllowCompatibleDifferences);
}
bool
ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts,
@@ -155,11 +159,14 @@
/// language options.
///
/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
+/// \param AllowCompatibleDifferences If true, differences between compatible
+/// language options will be permitted.
///
/// \returns true if the languagae options mis-match, false otherwise.
static bool checkLanguageOptions(const LangOptions &LangOpts,
const LangOptions &ExistingLangOpts,
- DiagnosticsEngine *Diags) {
+ DiagnosticsEngine *Diags,
+ bool AllowCompatibleDifferences = true) {
#define LANGOPT(Name, Bits, Default, Description) \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) \
@@ -184,6 +191,14 @@
return true; \
}
+#define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \
+ if (!AllowCompatibleDifferences) \
+ LANGOPT(Name, Bits, Default, Description)
+
+#define COMPATIBLE_ENUM_LANGOPT(Name, Bits, Default, Description) \
+ if (!AllowCompatibleDifferences) \
+ ENUM_LANGOPT(Name, Bits, Default, Description)
+
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
#include "clang/Basic/LangOptions.def"
@@ -278,10 +293,12 @@
bool
PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) {
+ bool Complain,
+ bool AllowCompatibleDifferences) {
const LangOptions &ExistingLangOpts = PP.getLangOpts();
return checkLanguageOptions(LangOpts, ExistingLangOpts,
- Complain? &Reader.Diags : nullptr);
+ Complain ? &Reader.Diags : nullptr,
+ AllowCompatibleDifferences);
}
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
@@ -389,14 +406,14 @@
// If the original import came from a file explicitly generated by the user,
// don't check the diagnostic mappings.
// FIXME: currently this is approximated by checking whether this is not a
- // module import.
+ // module import of an implicitly-loaded module file.
// Note: ModuleMgr.rbegin() may not be the current module, but it must be in
// the transitive closure of its imports, since unrelated modules cannot be
// imported until after this module finishes validation.
ModuleFile *TopImport = *ModuleMgr.rbegin();
while (!TopImport->ImportedBy.empty())
TopImport = TopImport->ImportedBy[0];
- if (TopImport->Kind != MK_Module)
+ if (TopImport->Kind != MK_ImplicitModule)
return false;
StringRef ModuleName = TopImport->ModuleName;
@@ -543,8 +560,7 @@
continue;
SuggestedPredefines += "#include \"";
- SuggestedPredefines +=
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += File;
SuggestedPredefines += "\"\n";
}
@@ -556,8 +572,7 @@
continue;
SuggestedPredefines += "#__include_macros \"";
- SuggestedPredefines +=
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += File;
SuggestedPredefines += "\"\n##\n";
}
@@ -774,15 +789,16 @@
DataLen -= 4;
SmallVector<uint32_t, 8> LocalMacroIDs;
if (hasSubmoduleMacros) {
- while (uint32_t LocalMacroID =
- endian::readNext<uint32_t, little, unaligned>(d)) {
+ while (true) {
+ uint32_t LocalMacroID =
+ endian::readNext<uint32_t, little, unaligned>(d);
DataLen -= 4;
+ if (LocalMacroID == 0xdeadbeef) break;
LocalMacroIDs.push_back(LocalMacroID);
}
- DataLen -= 4;
}
- if (F.Kind == MK_Module) {
+ 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;
@@ -1225,9 +1241,9 @@
return true;
}
- llvm::MemoryBuffer *Buffer
+ std::unique_ptr<llvm::MemoryBuffer> Buffer
= llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), File->getName());
- SourceMgr.overrideFileContents(File, Buffer);
+ SourceMgr.overrideFileContents(File, std::move(Buffer));
}
break;
@@ -1239,7 +1255,8 @@
SrcMgr::CharacteristicKind
FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
- if (IncludeLoc.isInvalid() && F->Kind == MK_Module) {
+ if (IncludeLoc.isInvalid() &&
+ (F->Kind == MK_ImplicitModule || F->Kind == MK_ExplicitModule)) {
IncludeLoc = getImportLocation(F);
}
unsigned Code = SLocEntryCursor.ReadCode();
@@ -1252,10 +1269,10 @@
return true;
}
- llvm::MemoryBuffer *Buffer
- = llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name);
- SourceMgr.createFileID(Buffer, FileCharacter, ID, BaseOffset + Offset,
- IncludeLoc);
+ std::unique_ptr<llvm::MemoryBuffer> Buffer =
+ llvm::MemoryBuffer::getMemBuffer(Blob.drop_back(1), Name);
+ SourceMgr.createFileID(std::move(Buffer), FileCharacter, ID,
+ BaseOffset + Offset, IncludeLoc);
break;
}
@@ -1285,7 +1302,7 @@
// Find which module file this entry lands in.
ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
- if (M->Kind != MK_Module)
+ if (M->Kind != MK_ImplicitModule && M->Kind != MK_ExplicitModule)
return std::make_pair(SourceLocation(), "");
// FIXME: Can we map this down to a particular submodule? That would be
@@ -1732,10 +1749,12 @@
return llvm::makeArrayRef(Overrides + 1, *Overrides);
}
- DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
+ MacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
if (!MI)
- return nullptr;
- return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true);
+ return PP.AllocateUndefMacroDirective(ImportLoc, SubModID,
+ getOverriddenSubmodules());
+ return PP.AllocateDefMacroDirective(MI, ImportLoc, SubModID,
+ getOverriddenSubmodules());
}
};
@@ -1772,7 +1791,8 @@
const PendingMacroInfo &PMInfo) {
assert(II);
- if (PMInfo.M->Kind != MK_Module) {
+ if (PMInfo.M->Kind != MK_ImplicitModule &&
+ PMInfo.M->Kind != MK_ExplicitModule) {
installPCHMacroDirectives(II, *PMInfo.M,
PMInfo.PCHMacroData.MacroDirectivesOffset);
return;
@@ -1796,7 +1816,7 @@
void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
ModuleFile &M, uint64_t Offset) {
- assert(M.Kind != MK_Module);
+ assert(M.Kind != MK_ImplicitModule && M.Kind != MK_ExplicitModule);
BitstreamCursor &Cursor = M.MacroCursor;
SavedStreamPosition SavedPosition(Cursor);
@@ -1828,23 +1848,36 @@
case MacroDirective::MD_Define: {
GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
MacroInfo *MI = getMacro(GMacID);
- bool isImported = Record[Idx++];
- bool isAmbiguous = Record[Idx++];
+ 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, isImported);
- DefMD->setAmbiguous(isAmbiguous);
+ PP.AllocateDefMacroDirective(MI, Loc, ImportedFrom, Overrides);
+ DefMD->setAmbiguous(IsAmbiguous);
MD = DefMD;
break;
}
- case MacroDirective::MD_Undefine:
- MD = PP.AllocateUndefMacroDirective(Loc);
+ 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);
break;
- case MacroDirective::MD_Visibility: {
+ }
+ case MacroDirective::MD_Visibility:
bool isPublic = Record[Idx++];
MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic);
break;
}
- }
if (!Latest)
Latest = MD;
@@ -1877,19 +1910,27 @@
}
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);
- HiddenNames &Hidden = HiddenNamesMap[Owner];
- HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II);
- if (HI != Hidden.HiddenMacros.end()) {
- auto SubOverrides = HI->second->getOverriddenSubmodules();
- Hidden.HiddenMacros.erase(HI);
- removeOverriddenMacros(II, Ambig, SubOverrides);
+ 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.
@@ -1903,6 +1944,7 @@
ASTReader::AmbiguousMacros *
ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ SourceLocation ImportLoc,
ArrayRef<SubmoduleID> Overrides) {
MacroDirective *Prev = PP.getMacroDirective(II);
if (!Prev && Overrides.empty())
@@ -1915,7 +1957,7 @@
AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
Ambig.push_back(PrevDef);
- removeOverriddenMacros(II, Ambig, Overrides);
+ removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
if (!Ambig.empty())
return &Ambig;
@@ -1927,7 +1969,7 @@
if (PrevDef)
Ambig.push_back(PrevDef);
- removeOverriddenMacros(II, Ambig, Overrides);
+ removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
if (!Ambig.empty()) {
AmbiguousMacros &Result = AmbiguousMacroDefs[II];
@@ -1955,18 +1997,16 @@
}
AmbiguousMacros *Prev =
- removeOverriddenMacros(II, MMI->getOverriddenSubmodules());
+ removeOverriddenMacros(II, ImportLoc, MMI->getOverriddenSubmodules());
// Create a synthetic macro definition corresponding to the import (or null
// if this was an undefinition of the macro).
- DefMacroDirective *MD = MMI->import(PP, ImportLoc);
+ MacroDirective *Imported = MMI->import(PP, ImportLoc);
+ DefMacroDirective *MD = dyn_cast<DefMacroDirective>(Imported);
// If there's no ambiguity, just install the macro.
if (!Prev) {
- if (MD)
- PP.appendMacroDirective(II, MD);
- else
- PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc));
+ PP.appendMacroDirective(II, Imported);
return;
}
assert(!Prev->empty());
@@ -1974,10 +2014,14 @@
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.
+ // imported directive, as if by a local #pragma pop_macro.
MacroInfo *NewMI = Prev->back()->getInfo();
Prev->pop_back();
- MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true);
+ 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.
@@ -2128,12 +2172,23 @@
bool IsOutOfDate = false;
// For an overridden file, there is nothing to validate.
- if (!Overridden && (StoredSize != File->getSize()
-#if !defined(LLVM_ON_WIN32)
+ if (!Overridden && //
+ (StoredSize != File->getSize() ||
+#if defined(LLVM_ON_WIN32)
+ false
+#else
// In our regression testing, the Windows file system seems to
// have inconsistent modification times that sometimes
// erroneously trigger this error-handling path.
- || StoredTime != File->getModificationTime()
+ //
+ // This also happens in networked file systems, so disable this
+ // check if validation is disabled or if we have an explicitly
+ // built PCM file.
+ //
+ // FIXME: Should we also do this for PCH files? They could also
+ // reasonably get shared across a network during a distributed build.
+ (StoredTime != File->getModificationTime() && !DisableValidation &&
+ F.Kind != MK_ExplicitModule)
#endif
)) {
if (Complain) {
@@ -2223,8 +2278,16 @@
return Failure;
}
+ // Should we allow the configuration of the module file to differ from the
+ // configuration of the current translation unit in a compatible way?
+ //
+ // FIXME: Allow this for files explicitly specified with -include-pch too.
+ bool AllowCompatibleConfigurationMismatch = F.Kind == MK_ExplicitModule;
+
// Read all of the records and blocks in the control block.
RecordData Record;
+ unsigned NumInputs = 0;
+ unsigned NumUserInputs = 0;
while (1) {
llvm::BitstreamEntry Entry = Stream.advance();
@@ -2237,15 +2300,9 @@
const HeaderSearchOptions &HSOpts =
PP.getHeaderSearchInfo().getHeaderSearchOpts();
- // All user input files reside at the index range [0, Record[1]), and
- // system input files reside at [Record[1], Record[0]).
- // Record is the one from INPUT_FILE_OFFSETS.
- unsigned NumInputs = Record[0];
- unsigned NumUserInputs = Record[1];
-
- if (!DisableValidation &&
- (ValidateSystemInputs || !HSOpts.ModulesValidateOncePerBuildSession ||
- F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp)) {
+ // All user input files reside at the index range [0, NumUserInputs), and
+ // system input files reside at [NumUserInputs, NumInputs).
+ if (!DisableValidation) {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
// If we are reading a module, we will create a verification timestamp,
@@ -2254,7 +2311,9 @@
unsigned N = NumUserInputs;
if (ValidateSystemInputs ||
- (HSOpts.ModulesValidateOncePerBuildSession && F.Kind == MK_Module))
+ (HSOpts.ModulesValidateOncePerBuildSession &&
+ F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp &&
+ F.Kind == MK_ImplicitModule))
N = NumInputs;
for (unsigned I = 0; I < N; ++I) {
@@ -2335,6 +2394,11 @@
break;
}
+ case SIGNATURE:
+ assert((!F.Signature || F.Signature == Record[0]) && "signature changed");
+ F.Signature = Record[0];
+ break;
+
case IMPORTS: {
// Load each of the imported PCH files.
unsigned Idx = 0, N = Record.size();
@@ -2348,6 +2412,7 @@
SourceLocation::getFromRawEncoding(Record[Idx++]);
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];
+ ASTFileSignature StoredSignature = Record[Idx++];
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
Record.begin() + Idx + Length);
@@ -2355,7 +2420,7 @@
// Load the AST file.
switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
- StoredSize, StoredModTime,
+ StoredSize, StoredModTime, StoredSignature,
ClientLoadCapabilities)) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
@@ -2372,8 +2437,10 @@
case LANGUAGE_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
+ // FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
if (Listener && &F == *ModuleMgr.begin() &&
- ParseLanguageOptions(Record, Complain, *Listener) &&
+ ParseLanguageOptions(Record, Complain, *Listener,
+ AllowCompatibleConfigurationMismatch) &&
!DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
break;
@@ -2391,6 +2458,7 @@
case DIAGNOSTIC_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParseDiagnosticOptions(Record, Complain, *Listener) &&
!DisableValidation)
return OutOfDate;
@@ -2400,6 +2468,7 @@
case FILE_SYSTEM_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParseFileSystemOptions(Record, Complain, *Listener) &&
!DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
@@ -2409,6 +2478,7 @@
case HEADER_SEARCH_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParseHeaderSearchOptions(Record, Complain, *Listener) &&
!DisableValidation && !AllowConfigurationMismatch)
return ConfigurationMismatch;
@@ -2418,6 +2488,7 @@
case PREPROCESSOR_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParsePreprocessorOptions(Record, Complain, *Listener,
SuggestedPredefines) &&
!DisableValidation && !AllowConfigurationMismatch)
@@ -2447,45 +2518,16 @@
break;
case MODULE_MAP_FILE:
- F.ModuleMapPath = Blob;
-
- // Try to resolve ModuleName in the current header search context and
- // verify that it is found in the same module map file as we saved. If the
- // top-level AST file is a main file, skip this check because there is no
- // usable header search context.
- assert(!F.ModuleName.empty() &&
- "MODULE_NAME should come before MOUDLE_MAP_FILE");
- if (F.Kind == MK_Module &&
- (*ModuleMgr.begin())->Kind != MK_MainFile) {
- Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
- if (!M) {
- assert(ImportedBy && "top-level import should be verified");
- if ((ClientLoadCapabilities & ARR_Missing) == 0)
- Diag(diag::err_imported_module_not_found)
- << F.ModuleName << ImportedBy->FileName;
- return Missing;
- }
-
- const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath);
- if (StoredModMap == nullptr || StoredModMap != M->ModuleMap) {
- assert(M->ModuleMap && "found module is missing module map file");
- assert(M->Name == F.ModuleName && "found module with different name");
- assert(ImportedBy && "top-level import should be verified");
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
- Diag(diag::err_imported_module_modmap_changed)
- << F.ModuleName << ImportedBy->FileName
- << M->ModuleMap->getName() << F.ModuleMapPath;
- return OutOfDate;
- }
- }
-
- if (Listener)
- Listener->ReadModuleMapFile(F.ModuleMapPath);
+ if (ASTReadResult Result =
+ ReadModuleMapFileBlock(Record, F, ImportedBy, ClientLoadCapabilities))
+ return Result;
break;
case INPUT_FILE_OFFSETS:
+ NumInputs = Record[0];
+ NumUserInputs = Record[1];
F.InputFileOffsets = (const uint32_t *)Blob.data();
- F.InputFilesLoaded.resize(Record[0]);
+ F.InputFilesLoaded.resize(NumInputs);
break;
}
}
@@ -2628,7 +2670,7 @@
F.TypeRemap.insertOrReplace(
std::make_pair(LocalBaseTypeIndex,
F.BaseTypeIndex - LocalBaseTypeIndex));
-
+
TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
}
break;
@@ -2658,7 +2700,7 @@
// Introduce the global -> local mapping for declarations within this
// module.
F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
-
+
DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
}
break;
@@ -2687,7 +2729,6 @@
auto *DC = cast<DeclContext>(D);
DC->getPrimaryContext()->setHasExternalVisibleStorage(true);
auto *&LookupTable = F.DeclContextInfos[DC].NameLookupTableData;
- // FIXME: There should never be an existing lookup table.
delete LookupTable;
LookupTable = Table;
} else
@@ -2729,8 +2770,8 @@
F.IdentifierRemap.insertOrReplace(
std::make_pair(LocalBaseIdentifierID,
F.BaseIdentifierID - LocalBaseIdentifierID));
-
- IdentifiersLoaded.resize(IdentifiersLoaded.size()
+
+ IdentifiersLoaded.resize(IdentifiersLoaded.size()
+ F.LocalNumIdentifiers);
}
break;
@@ -2823,7 +2864,7 @@
std::make_pair(LocalBaseSelectorID,
F.BaseSelectorID - LocalBaseSelectorID));
- SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);
+ SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);
}
break;
}
@@ -2904,19 +2945,16 @@
}
// Continuous range maps we may be updating in our module.
- ContinuousRangeMap<uint32_t, int, 2>::Builder SLocRemap(F.SLocRemap);
- ContinuousRangeMap<uint32_t, int, 2>::Builder
- IdentifierRemap(F.IdentifierRemap);
- 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);
- ContinuousRangeMap<uint32_t, int, 2>::Builder
- SelectorRemap(F.SelectorRemap);
- ContinuousRangeMap<uint32_t, int, 2>::Builder DeclRemap(F.DeclRemap);
- ContinuousRangeMap<uint32_t, int, 2>::Builder TypeRemap(F.TypeRemap);
+ typedef ContinuousRangeMap<uint32_t, int, 2>::Builder
+ RemapBuilder;
+ RemapBuilder SLocRemap(F.SLocRemap);
+ RemapBuilder IdentifierRemap(F.IdentifierRemap);
+ RemapBuilder MacroRemap(F.MacroRemap);
+ RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap);
+ RemapBuilder SubmoduleRemap(F.SubmoduleRemap);
+ RemapBuilder SelectorRemap(F.SelectorRemap);
+ RemapBuilder DeclRemap(F.DeclRemap);
+ RemapBuilder TypeRemap(F.TypeRemap);
while(Data < DataEnd) {
using namespace llvm::support;
@@ -2946,26 +2984,23 @@
uint32_t TypeIndexOffset =
endian::readNext<uint32_t, little, unaligned>(Data);
- // Source location offset is mapped to OM->SLocEntryBaseOffset.
- SLocRemap.insert(std::make_pair(SLocOffset,
- static_cast<int>(OM->SLocEntryBaseOffset - SLocOffset)));
- 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));
- SubmoduleRemap.insert(std::make_pair(SubmoduleIDOffset,
- OM->BaseSubmoduleID - SubmoduleIDOffset));
- SelectorRemap.insert(std::make_pair(SelectorIDOffset,
- OM->BaseSelectorID - SelectorIDOffset));
- DeclRemap.insert(std::make_pair(DeclIDOffset,
- OM->BaseDeclID - DeclIDOffset));
-
- TypeRemap.insert(std::make_pair(TypeIndexOffset,
- OM->BaseTypeIndex - TypeIndexOffset));
+ uint32_t None = std::numeric_limits<uint32_t>::max();
+
+ auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset,
+ RemapBuilder &Remap) {
+ if (Offset != None)
+ Remap.insert(std::make_pair(Offset,
+ static_cast<int>(BaseOffset - Offset)));
+ };
+ mapOffset(SLocOffset, OM->SLocEntryBaseOffset, SLocRemap);
+ mapOffset(IdentifierIDOffset, OM->BaseIdentifierID, IdentifierRemap);
+ mapOffset(MacroIDOffset, OM->BaseMacroID, MacroRemap);
+ mapOffset(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID,
+ PreprocessedEntityRemap);
+ mapOffset(SubmoduleIDOffset, OM->BaseSubmoduleID, SubmoduleRemap);
+ mapOffset(SelectorIDOffset, OM->BaseSelectorID, SelectorRemap);
+ mapOffset(DeclIDOffset, OM->BaseDeclID, DeclRemap);
+ mapOffset(TypeIndexOffset, OM->BaseTypeIndex, TypeRemap);
// Global -> local mappings.
F.GlobalToLocalDeclIDs[OM] = DeclIDOffset;
@@ -3206,7 +3241,7 @@
break;
case IMPORTED_MODULES: {
- if (F.Kind != MK_Module) {
+ if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) {
// If we aren't loading a module (which has its own exports), make
// all of the imported modules visible.
// FIXME: Deal with macros-only imports.
@@ -3287,10 +3322,110 @@
}
OptimizeOffPragmaLocation = ReadSourceLocation(F, Record[0]);
break;
+
+ case UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES:
+ for (unsigned I = 0, N = Record.size(); I != N; ++I)
+ UnusedLocalTypedefNameCandidates.push_back(
+ getGlobalDeclID(F, Record[I]));
+ break;
}
}
}
+ASTReader::ASTReadResult
+ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
+ const ModuleFile *ImportedBy,
+ unsigned ClientLoadCapabilities) {
+ unsigned Idx = 0;
+ F.ModuleMapPath = ReadString(Record, Idx);
+
+ if (F.Kind == MK_ExplicitModule) {
+ // For an explicitly-loaded module, we don't care whether the original
+ // module map file exists or matches.
+ return Success;
+ }
+
+ // Try to resolve ModuleName in the current header search context and
+ // verify that it is found in the same module map file as we saved. If the
+ // top-level AST file is a main file, skip this check because there is no
+ // usable header search context.
+ assert(!F.ModuleName.empty() &&
+ "MODULE_NAME should come before MODULE_MAP_FILE");
+ if (F.Kind == MK_ImplicitModule &&
+ (*ModuleMgr.begin())->Kind != MK_MainFile) {
+ // An implicitly-loaded module file should have its module listed in some
+ // module map file that we've already loaded.
+ Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+ auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+ const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
+ if (!ModMap) {
+ assert(ImportedBy && "top-level import should be verified");
+ if ((ClientLoadCapabilities & ARR_Missing) == 0)
+ Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName
+ << ImportedBy->FileName
+ << F.ModuleMapPath;
+ return Missing;
+ }
+
+ assert(M->Name == F.ModuleName && "found module with different name");
+
+ // Check the primary module map file.
+ const FileEntry *StoredModMap = FileMgr.getFile(F.ModuleMapPath);
+ if (StoredModMap == nullptr || StoredModMap != ModMap) {
+ assert(ModMap && "found module is missing module map file");
+ assert(ImportedBy && "top-level import should be verified");
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_imported_module_modmap_changed)
+ << F.ModuleName << ImportedBy->FileName
+ << ModMap->getName() << F.ModuleMapPath;
+ return OutOfDate;
+ }
+
+ llvm::SmallPtrSet<const FileEntry *, 1> AdditionalStoredMaps;
+ for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {
+ // FIXME: we should use input files rather than storing names.
+ std::string Filename = ReadString(Record, Idx);
+ const FileEntry *F =
+ FileMgr.getFile(Filename, false, false);
+ if (F == nullptr) {
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Error("could not find file '" + Filename +"' referenced by AST file");
+ return OutOfDate;
+ }
+ AdditionalStoredMaps.insert(F);
+ }
+
+ // Check any additional module map files (e.g. module.private.modulemap)
+ // that are not in the pcm.
+ if (auto *AdditionalModuleMaps = Map.getAdditionalModuleMapFiles(M)) {
+ for (const FileEntry *ModMap : *AdditionalModuleMaps) {
+ // Remove files that match
+ // Note: SmallPtrSet::erase is really remove
+ if (!AdditionalStoredMaps.erase(ModMap)) {
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_module_different_modmap)
+ << F.ModuleName << /*new*/0 << ModMap->getName();
+ return OutOfDate;
+ }
+ }
+ }
+
+ // Check any additional module map files that are in the pcm, but not
+ // found in header search. Cases that match are already removed.
+ for (const FileEntry *ModMap : AdditionalStoredMaps) {
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_module_different_modmap)
+ << F.ModuleName << /*not new*/1 << ModMap->getName();
+ return OutOfDate;
+ }
+ }
+
+ if (Listener)
+ Listener->ReadModuleMapFile(F.ModuleMapPath);
+ return Success;
+}
+
+
/// \brief Move the given method to the back of the global list of methods.
static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
// Find the entry for this selector in the method pool.
@@ -3320,9 +3455,10 @@
}
}
-void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
- for (unsigned I = 0, N = Names.HiddenDecls.size(); I != N; ++I) {
- Decl *D = Names.HiddenDecls[I];
+void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
+ bool FromFinalization) {
+ // FIXME: Only do this if Owner->NameVisibility == AllVisible.
+ for (Decl *D : Names.HiddenDecls) {
bool wasHidden = D->Hidden;
D->Hidden = false;
@@ -3333,10 +3469,15 @@
}
}
- for (HiddenMacrosMap::const_iterator I = Names.HiddenMacros.begin(),
- E = Names.HiddenMacros.end();
- I != E; ++I)
- installImportedMacro(I->first, I->second, 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,
@@ -3370,8 +3511,12 @@
// mark them as visible.
HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
if (Hidden != HiddenNamesMap.end()) {
- makeNamesVisible(Hidden->second, Hidden->first);
+ auto HiddenNames = std::move(*Hidden);
HiddenNamesMap.erase(Hidden);
+ makeNamesVisible(HiddenNames.second, HiddenNames.first,
+ /*FromFinalization*/false);
+ assert(HiddenNamesMap.find(Mod) == HiddenNamesMap.end() &&
+ "making names visible added hidden names");
}
// Push any exported modules onto the stack to be marked as visible.
@@ -3380,7 +3525,7 @@
for (SmallVectorImpl<Module *>::iterator
I = Exports.begin(), E = Exports.end(); I != E; ++I) {
Module *Exported = *I;
- if (Visited.insert(Exported))
+ if (Visited.insert(Exported).second)
Stack.push_back(Exported);
}
@@ -3430,10 +3575,9 @@
static void updateModuleTimestamp(ModuleFile &MF) {
// Overwrite the timestamp file contents so that file's mtime changes.
std::string TimestampFilename = MF.getTimestampFilename();
- std::string ErrorInfo;
- llvm::raw_fd_ostream OS(TimestampFilename.c_str(), ErrorInfo,
- llvm::sys::fs::F_Text);
- if (!ErrorInfo.empty())
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(TimestampFilename, EC, llvm::sys::fs::F_Text);
+ if (EC)
return;
OS << "Timestamp file\n";
}
@@ -3455,7 +3599,7 @@
SmallVector<ImportedModule, 4> Loaded;
switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
/*ImportedBy=*/nullptr, Loaded,
- 0, 0,
+ 0, 0, 0,
ClientLoadCapabilities)) {
case Failure:
case Missing:
@@ -3613,7 +3757,7 @@
// in the filesystem).
for (unsigned I = 0, N = Loaded.size(); I != N; ++I) {
ImportedModule &M = Loaded[I];
- if (M.Mod->Kind == MK_Module) {
+ if (M.Mod->Kind == MK_ImplicitModule) {
updateModuleTimestamp(*M.Mod);
}
}
@@ -3622,6 +3766,8 @@
return Success;
}
+static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+
ASTReader::ASTReadResult
ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type,
@@ -3629,12 +3775,14 @@
ModuleFile *ImportedBy,
SmallVectorImpl<ImportedModule> &Loaded,
off_t ExpectedSize, time_t ExpectedModTime,
+ ASTFileSignature ExpectedSignature,
unsigned ClientLoadCapabilities) {
ModuleFile *M;
std::string ErrorStr;
ModuleManager::AddModuleResult AddResult
= ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy,
getGeneration(), ExpectedSize, ExpectedModTime,
+ ExpectedSignature, readASTFileSignature,
M, ErrorStr);
switch (AddResult) {
@@ -3646,7 +3794,7 @@
break;
case ModuleManager::Missing:
- // The module file was missing; if the client handle handle, that, return
+ // The module file was missing; if the client can handle that, return
// it.
if (ClientLoadCapabilities & ARR_Missing)
return Missing;
@@ -3685,7 +3833,7 @@
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
- Stream.init(F.StreamFile);
+ Stream.init(&F.StreamFile);
F.SizeInBits = F.Buffer->getBufferSize() * 8;
// Sniff for the signature.
@@ -3894,12 +4042,12 @@
}
void ASTReader::finalizeForWriting() {
- for (HiddenNamesMapType::iterator Hidden = HiddenNamesMap.begin(),
- HiddenEnd = HiddenNamesMap.end();
- Hidden != HiddenEnd; ++Hidden) {
- makeNamesVisible(Hidden->second, Hidden->first);
+ while (!HiddenNamesMap.empty()) {
+ auto HiddenNames = std::move(*HiddenNamesMap.begin());
+ HiddenNamesMap.erase(HiddenNamesMap.begin());
+ makeNamesVisible(HiddenNames.second, HiddenNames.first,
+ /*FromFinalization*/true);
}
- HiddenNamesMap.clear();
}
/// \brief Given a cursor at the start of an AST file, scan ahead and drop the
@@ -3932,6 +4080,34 @@
}
}
+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') {
+ return 0;
+ }
+
+ // Scan for the CONTROL_BLOCK_ID block.
+ if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID))
+ return 0;
+
+ // Scan for SIGNATURE inside the control block.
+ ASTReader::RecordData Record;
+ while (1) {
+ llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ if (Entry.Kind == llvm::BitstreamEntry::EndBlock ||
+ Entry.Kind != llvm::BitstreamEntry::Record)
+ return 0;
+
+ Record.clear();
+ StringRef Blob;
+ if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob))
+ return Record[0];
+ }
+}
+
/// \brief Retrieve the name of the original source file name
/// directly from the AST file, without actually loading the AST
/// file.
@@ -3939,20 +4115,18 @@
FileManager &FileMgr,
DiagnosticsEngine &Diags) {
// Open the AST file.
- std::string ErrStr;
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
- Buffer.reset(FileMgr.getBufferForFile(ASTFileName, &ErrStr));
+ auto Buffer = FileMgr.getBufferForFile(ASTFileName);
if (!Buffer) {
- Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << ErrStr;
+ Diags.Report(diag::err_fe_unable_to_read_pch_file)
+ << ASTFileName << Buffer.getError().message();
return std::string();
}
// Initialize the stream
llvm::BitstreamReader StreamFile;
- BitstreamCursor Stream;
- StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
- (const unsigned char *)Buffer->getBufferEnd());
- Stream.init(StreamFile);
+ StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
+ (const unsigned char *)(*Buffer)->getBufferEnd());
+ BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
if (Stream.Read(8) != 'C' ||
@@ -4007,9 +4181,10 @@
{
}
- bool ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) override {
- return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr);
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
+ return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
+ AllowCompatibleDifferences);
}
bool ReadTargetOptions(const TargetOptions &TargetOpts,
bool Complain) override {
@@ -4028,19 +4203,16 @@
FileManager &FileMgr,
ASTReaderListener &Listener) {
// Open the AST file.
- std::string ErrStr;
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
- Buffer.reset(FileMgr.getBufferForFile(Filename, &ErrStr));
+ auto Buffer = FileMgr.getBufferForFile(Filename);
if (!Buffer) {
return true;
}
// Initialize the stream
llvm::BitstreamReader StreamFile;
- BitstreamCursor Stream;
- StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
- (const unsigned char *)Buffer->getBufferEnd());
- Stream.init(StreamFile);
+ StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
+ (const unsigned char *)(*Buffer)->getBufferEnd());
+ BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
if (Stream.Read(8) != 'C' ||
@@ -4056,6 +4228,7 @@
bool NeedsInputFiles = Listener.needsInputFileVisitation();
bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation();
+ bool NeedsImports = Listener.needsImportVisitation();
BitstreamCursor InputFilesCursor;
if (NeedsInputFiles) {
InputFilesCursor = Stream;
@@ -4102,11 +4275,14 @@
case MODULE_NAME:
Listener.ReadModuleName(Blob);
break;
- case MODULE_MAP_FILE:
- Listener.ReadModuleMapFile(Blob);
+ case MODULE_MAP_FILE: {
+ unsigned Idx = 0;
+ Listener.ReadModuleMapFile(ReadString(Record, Idx));
break;
+ }
case LANGUAGE_OPTIONS:
- if (ParseLanguageOptions(Record, false, Listener))
+ if (ParseLanguageOptions(Record, false, Listener,
+ /*AllowCompatibleConfigurationMismatch*/false))
return true;
break;
@@ -4172,6 +4348,23 @@
break;
}
+ case IMPORTS: {
+ if (!NeedsImports)
+ break;
+
+ unsigned Idx = 0, N = Record.size();
+ while (Idx < N) {
+ // Read information about the AST file.
+ Idx += 5; // ImportLoc, Size, ModTime, Signature
+ unsigned Length = Record[Idx++];
+ SmallString<128> ImportedFile(Record.begin() + Idx,
+ Record.begin() + Idx + Length);
+ Idx += Length;
+ Listener.visitImport(ImportedFile);
+ }
+ break;
+ }
+
default:
// No other validation to perform.
break;
@@ -4219,21 +4412,30 @@
// Read a record.
StringRef Blob;
Record.clear();
- switch (F.Stream.readRecord(Entry.ID, Record, &Blob)) {
+ auto Kind = F.Stream.readRecord(Entry.ID, Record, &Blob);
+
+ if ((Kind == SUBMODULE_METADATA) != First) {
+ Error("submodule metadata record should be at beginning of block");
+ return Failure;
+ }
+ First = false;
+
+ // Submodule information is only valid if we have a current module.
+ // FIXME: Should we error on these cases?
+ if (!CurrentModule && Kind != SUBMODULE_METADATA &&
+ Kind != SUBMODULE_DEFINITION)
+ continue;
+
+ switch (Kind) {
default: // Default behavior: ignore.
break;
-
- case SUBMODULE_DEFINITION: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
+ case SUBMODULE_DEFINITION: {
if (Record.size() < 8) {
Error("malformed module definition");
return Failure;
}
-
+
StringRef Name = Blob;
unsigned Idx = 0;
SubmoduleID GlobalID = getGlobalSubmoduleID(F, Record[Idx++]);
@@ -4248,20 +4450,17 @@
bool ConfigMacrosExhaustive = Record[Idx++];
Module *ParentModule = nullptr;
- const FileEntry *ModuleMap = nullptr;
- if (Parent) {
+ if (Parent)
ParentModule = getSubmodule(Parent);
- ModuleMap = ParentModule->ModuleMap;
- }
-
- if (!F.ModuleMapPath.empty())
- ModuleMap = FileMgr.getFile(F.ModuleMapPath);
// Retrieve this (sub)module from the module map, creating it if
// necessary.
- CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, ModuleMap,
- IsFramework,
+ CurrentModule = ModMap.findOrCreateModule(Name, ParentModule, IsFramework,
IsExplicit).first;
+
+ // FIXME: set the definition loc for CurrentModule, or call
+ // ModMap.setInferredModuleAllowedBy()
+
SubmoduleID GlobalIndex = GlobalID - NUM_PREDEF_SUBMODULE_IDS;
if (GlobalIndex >= SubmodulesLoaded.size() ||
SubmodulesLoaded[GlobalIndex]) {
@@ -4306,14 +4505,6 @@
}
case SUBMODULE_UMBRELLA_HEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
if (const FileEntry *Umbrella = PP.getFileManager().getFile(Blob)) {
if (!CurrentModule->getUmbrellaHeader())
ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
@@ -4326,73 +4517,26 @@
break;
}
- case SUBMODULE_HEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
- // We lazily associate headers with their modules via the HeaderInfoTable.
+ case SUBMODULE_HEADER:
+ case SUBMODULE_EXCLUDED_HEADER:
+ case SUBMODULE_PRIVATE_HEADER:
+ // We lazily associate headers with their modules via the HeaderInfo table.
// FIXME: Re-evaluate this section; maybe only store InputFile IDs instead
// of complete filenames or remove it entirely.
- break;
- }
+ break;
- case SUBMODULE_EXCLUDED_HEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
- // We lazily associate headers with their modules via the HeaderInfoTable.
- // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead
- // of complete filenames or remove it entirely.
- break;
- }
-
- case SUBMODULE_PRIVATE_HEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
- // We lazily associate headers with their modules via the HeaderInfoTable.
- // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead
- // of complete filenames or remove it entirely.
- break;
- }
+ case SUBMODULE_TEXTUAL_HEADER:
+ case SUBMODULE_PRIVATE_TEXTUAL_HEADER:
+ // FIXME: Textual headers are not marked in the HeaderInfo table. Load
+ // them here.
+ break;
case SUBMODULE_TOPHEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
CurrentModule->addTopHeaderFilename(Blob);
break;
}
case SUBMODULE_UMBRELLA_DIR: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
if (const DirectoryEntry *Umbrella
= PP.getFileManager().getDirectory(Blob)) {
if (!CurrentModule->getUmbrellaDir())
@@ -4407,12 +4551,6 @@
}
case SUBMODULE_METADATA: {
- if (!First) {
- Error("submodule metadata record not at beginning of block");
- return Failure;
- }
- First = false;
-
F.BaseSubmoduleID = getTotalNumSubmodules();
F.LocalNumSubmodules = Record[0];
unsigned LocalBaseSubmoduleID = Record[1];
@@ -4426,21 +4564,13 @@
F.SubmoduleRemap.insertOrReplace(
std::make_pair(LocalBaseSubmoduleID,
F.BaseSubmoduleID - LocalBaseSubmoduleID));
-
+
SubmodulesLoaded.resize(SubmodulesLoaded.size() + F.LocalNumSubmodules);
- }
+ }
break;
}
case SUBMODULE_IMPORTS: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
UnresolvedModuleRef Unresolved;
Unresolved.File = &F;
@@ -4454,14 +4584,6 @@
}
case SUBMODULE_EXPORTS: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
UnresolvedModuleRef Unresolved;
Unresolved.File = &F;
@@ -4478,53 +4600,21 @@
break;
}
case SUBMODULE_REQUIRES: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(),
Context.getTargetInfo());
break;
}
case SUBMODULE_LINK_LIBRARY:
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
CurrentModule->LinkLibraries.push_back(
Module::LinkLibrary(Blob, Record[0]));
break;
case SUBMODULE_CONFIG_MACRO:
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
CurrentModule->ConfigMacros.push_back(Blob.str());
break;
case SUBMODULE_CONFLICT: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
-
- if (!CurrentModule)
- break;
-
UnresolvedModuleRef Unresolved;
Unresolved.File = &F;
Unresolved.Mod = CurrentModule;
@@ -4548,7 +4638,8 @@
/// \returns true if the listener deems the file unacceptable, false otherwise.
bool ASTReader::ParseLanguageOptions(const RecordData &Record,
bool Complain,
- ASTReaderListener &Listener) {
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences) {
LangOptions LangOpts;
unsigned Idx = 0;
#define LANGOPT(Name, Bits, Default, Description) \
@@ -4556,7 +4647,8 @@
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
LangOpts.set##Name(static_cast<LangOptions::Type>(Record[Idx++]));
#include "clang/Basic/LangOptions.def"
-#define SANITIZER(NAME, ID) LangOpts.Sanitize.ID = Record[Idx++];
+#define SANITIZER(NAME, ID) \
+ LangOpts.Sanitize.set(SanitizerKind::ID, Record[Idx++]);
#include "clang/Basic/Sanitizers.def"
ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++];
@@ -4576,7 +4668,8 @@
}
LangOpts.CommentOpts.ParseAllComments = Record[Idx++];
- return Listener.ReadLanguageOptions(LangOpts, Complain);
+ return Listener.ReadLanguageOptions(LangOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ASTReader::ParseTargetOptions(const RecordData &Record,
@@ -4606,9 +4699,10 @@
DiagOpts->set##Name(static_cast<Type>(Record[Idx++]));
#include "clang/Basic/DiagnosticOptions.def"
- for (unsigned N = Record[Idx++]; N; --N) {
+ for (unsigned N = Record[Idx++]; N; --N)
DiagOpts->Warnings.push_back(ReadString(Record, Idx));
- }
+ for (unsigned N = Record[Idx++]; N; --N)
+ DiagOpts->Remarks.push_back(ReadString(Record, Idx));
return Listener.ReadDiagnosticOptions(DiagOpts, Complain);
}
@@ -5229,17 +5323,19 @@
/*produces*/ Record[5]);
unsigned Idx = 6;
- unsigned NumParams = Record[Idx++];
- SmallVector<QualType, 16> ParamTypes;
- for (unsigned I = 0; I != NumParams; ++I)
- ParamTypes.push_back(readType(*Loc.F, Record, Idx));
EPI.Variadic = Record[Idx++];
EPI.HasTrailingReturn = Record[Idx++];
EPI.TypeQuals = Record[Idx++];
EPI.RefQualifier = static_cast<RefQualifierKind>(Record[Idx++]);
SmallVector<QualType, 8> ExceptionStorage;
- readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx);
+ readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx);
+
+ unsigned NumParams = Record[Idx++];
+ SmallVector<QualType, 16> ParamTypes;
+ for (unsigned I = 0; I != NumParams; ++I)
+ ParamTypes.push_back(readType(*Loc.F, Record, Idx));
+
return Context.getFunctionType(ResultType, ParamTypes, EPI);
}
@@ -5408,13 +5504,18 @@
QualType TST = readType(*Loc.F, Record, Idx); // probably derivable
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
// for AST reading, too much interdependencies.
- const Type *T;
- if (const Type *Existing = D->getTypeForDecl())
- T = Existing;
- else if (auto *Prev = D->getPreviousDecl())
- T = Prev->getTypeForDecl();
- else
+ const Type *T = nullptr;
+ for (auto *DI = D; DI; DI = DI->getPreviousDecl()) {
+ if (const Type *Existing = DI->getTypeForDecl()) {
+ T = Existing;
+ break;
+ }
+ }
+ if (!T) {
T = new (Context, TypeAlignment) InjectedClassNameType(D, TST);
+ for (auto *DI = D; DI; DI = DI->getPreviousDecl())
+ DI->setTypeForDecl(T);
+ }
return QualType(T, 0);
}
@@ -5502,24 +5603,22 @@
void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
SmallVectorImpl<QualType> &Exceptions,
- FunctionProtoType::ExtProtoInfo &EPI,
+ FunctionProtoType::ExceptionSpecInfo &ESI,
const RecordData &Record, unsigned &Idx) {
ExceptionSpecificationType EST =
static_cast<ExceptionSpecificationType>(Record[Idx++]);
- EPI.ExceptionSpecType = EST;
+ ESI.Type = EST;
if (EST == EST_Dynamic) {
- EPI.NumExceptions = Record[Idx++];
- for (unsigned I = 0; I != EPI.NumExceptions; ++I)
+ for (unsigned I = 0, N = Record[Idx++]; I != N; ++I)
Exceptions.push_back(readType(ModuleFile, Record, Idx));
- EPI.Exceptions = Exceptions.data();
+ ESI.Exceptions = Exceptions;
} else if (EST == EST_ComputedNoexcept) {
- EPI.NoexceptExpr = ReadExpr(ModuleFile);
+ ESI.NoexceptExpr = ReadExpr(ModuleFile);
} else if (EST == EST_Uninstantiated) {
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
- EPI.ExceptionSpecTemplate =
- ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ ESI.SourceTemplate = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
} else if (EST == EST_Unevaluated) {
- EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ ESI.SourceDecl = ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
}
}
@@ -5970,18 +6069,10 @@
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
- // Recursively ensure that the decl context itself is complete
- // (in particular, this matters if the decl context is a namespace).
- //
- // FIXME: This should be performed by lookup instead of here.
- cast<Decl>(DC)->getMostRecentDecl();
-
// If this is a named declaration, complete it by looking it up
// within its context.
//
- // FIXME: We don't currently handle the cases where we can't do this;
- // merging a class definition that contains unnamed entities should merge
- // those entities. Likewise, merging a function definition should merge
+ // FIXME: Merging a function definition should merge
// all mergeable entities within it.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC) ||
isa<CXXRecordDecl>(DC) || isa<EnumDecl>(DC)) {
@@ -5994,6 +6085,9 @@
updateOutOfDateIdentifier(*II);
} else
DC->lookup(Name);
+ } else if (needsAnonymousDeclarationNumber(cast<NamedDecl>(D))) {
+ // FIXME: It'd be nice to do something a bit more targeted here.
+ D->getDeclContext()->decls_begin();
}
}
}
@@ -6339,13 +6433,13 @@
/// declaration context.
class DeclContextNameLookupVisitor {
ASTReader &Reader;
- SmallVectorImpl<const DeclContext *> &Contexts;
+ ArrayRef<const DeclContext *> Contexts;
DeclarationName Name;
SmallVectorImpl<NamedDecl *> &Decls;
public:
- DeclContextNameLookupVisitor(ASTReader &Reader,
- SmallVectorImpl<const DeclContext *> &Contexts,
+ DeclContextNameLookupVisitor(ASTReader &Reader,
+ ArrayRef<const DeclContext *> Contexts,
DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Decls)
: Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls) { }
@@ -6358,9 +6452,9 @@
// this context in this module.
ModuleFile::DeclContextInfosMap::iterator Info;
bool FoundInfo = false;
- for (unsigned I = 0, N = This->Contexts.size(); I != N; ++I) {
- Info = M.DeclContextInfos.find(This->Contexts[I]);
- if (Info != M.DeclContextInfos.end() &&
+ for (auto *DC : This->Contexts) {
+ Info = M.DeclContextInfos.find(DC);
+ if (Info != M.DeclContextInfos.end() &&
Info->second.NameLookupTableData) {
FoundInfo = true;
break;
@@ -6369,7 +6463,7 @@
if (!FoundInfo)
return false;
-
+
// Look for this name within this module.
ASTDeclContextNameLookupTable *LookupTable =
Info->second.NameLookupTableData;
@@ -6390,9 +6484,11 @@
// 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.
+ // FIXME: This should not happen; deserializing declarations should
+ // not perform lookups since that can lead to deserialization cycles.
continue;
}
-
+
// Record this declaration.
FoundAnything = true;
This->Decls.push_back(ND);
@@ -6432,15 +6528,17 @@
if (!Name)
return false;
+ Deserializing LookupResults(this);
+
SmallVector<NamedDecl *, 64> Decls;
-
+
// Compute the declaration contexts we need to look into. Multiple such
// declaration contexts occur when two declaration contexts from disjoint
// modules get merged, e.g., when two namespaces with the same name are
// independently defined in separate modules.
SmallVector<const DeclContext *, 2> Contexts;
Contexts.push_back(DC);
-
+
if (DC->isNamespace()) {
auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
if (Merged != MergedDecls.end()) {
@@ -6448,24 +6546,40 @@
Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
}
}
+
+ auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) {
+ DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
+
+ // If we can definitively determine which module file to look into,
+ // only look there. Otherwise, look in all module files.
+ ModuleFile *Definitive;
+ if (Contexts.size() == 1 &&
+ (Definitive = getDefinitiveModuleFileFor(Contexts[0], *this))) {
+ DeclContextNameLookupVisitor::visit(*Definitive, &Visitor);
+ } else {
+ ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
+ }
+ };
+
+ LookUpInContexts(Contexts);
+
+ // If this might be an implicit special member function, then also search
+ // all merged definitions of the surrounding class. We need to search them
+ // 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 Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end())
- Contexts.insert(Contexts.end(), Merged->second.begin(),
- Merged->second.end());
+ 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 (auto *MergedDC : Merged->second)
+ LookUpInContexts(MergedDC);
+ }
}
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
-
- // If we can definitively determine which module file to look into,
- // only look there. Otherwise, look in all module files.
- ModuleFile *Definitive;
- if (Contexts.size() == 1 &&
- (Definitive = getDefinitiveModuleFileFor(DC, *this))) {
- DeclContextNameLookupVisitor::visit(*Definitive, &Visitor);
- } else {
- ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
- }
++NumVisibleDeclContextsRead;
SetExternalVisibleDeclsForName(DC, Name, Decls);
return !Decls.empty();
@@ -6780,11 +6894,11 @@
// Makes sure any declarations that were deserialized "too early"
// still get added to the identifier's declaration chains.
- for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
- pushExternalDeclIntoScope(PreloadedDecls[I],
- PreloadedDecls[I]->getDeclName());
+ for (uint64_t ID : PreloadedDeclIDs) {
+ NamedDecl *D = cast<NamedDecl>(GetDecl(ID));
+ pushExternalDeclIntoScope(D, D->getDeclName());
}
- PreloadedDecls.clear();
+ PreloadedDeclIDs.clear();
// FIXME: What happens if these are changed by a module import?
if (!FPPragmaOptions.empty()) {
@@ -7089,6 +7203,18 @@
DynamicClasses.clear();
}
+void ASTReader::ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {
+ for (unsigned I = 0, N = UnusedLocalTypedefNameCandidates.size(); I != N;
+ ++I) {
+ TypedefNameDecl *D = dyn_cast_or_null<TypedefNameDecl>(
+ GetDecl(UnusedLocalTypedefNameCandidates[I]));
+ if (D)
+ Decls.insert(D);
+ }
+ UnusedLocalTypedefNameCandidates.clear();
+}
+
void
ASTReader::ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl *> &Decls) {
for (unsigned I = 0, N = LocallyScopedExternCDecls.size(); I != N; ++I) {
@@ -7224,24 +7350,26 @@
}
for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
- NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
- if (SemaObj) {
- // If we're simply supposed to record the declarations, do so now.
- if (Decls) {
- Decls->push_back(D);
- continue;
- }
-
- // Introduce this declaration into the translation-unit scope
- // and add it to the declaration chain for this identifier, so
- // that (unqualified) name lookup will find it.
- pushExternalDeclIntoScope(D, II);
- } else {
+ if (!SemaObj) {
// Queue this declaration so that it will be added to the
// translation unit scope and identifier's declaration chain
// once a Sema object is known.
- PreloadedDecls.push_back(D);
+ PreloadedDeclIDs.push_back(DeclIDs[I]);
+ continue;
}
+
+ NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
+
+ // If we're simply supposed to record the declarations, do so now.
+ if (Decls) {
+ Decls->push_back(D);
+ continue;
+ }
+
+ // Introduce this declaration into the translation-unit scope
+ // and add it to the declaration chain for this identifier, so
+ // that (unqualified) name lookup will find it.
+ pushExternalDeclIntoScope(D, II);
}
}
@@ -7578,8 +7706,7 @@
return TemplateArgument(readType(F, Record, Idx));
case TemplateArgument::Declaration: {
ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
- bool ForReferenceParam = Record[Idx++];
- return TemplateArgument(D, ForReferenceParam);
+ return TemplateArgument(D, readType(F, Record, Idx));
}
case TemplateArgument::NullPtr:
return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
@@ -7800,6 +7927,12 @@
// No associated value, and there can't be a prefix.
break;
}
+
+ case NestedNameSpecifier::Super: {
+ CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+ NNS = NestedNameSpecifier::SuperSpecifier(Context, RD);
+ break;
+ }
}
Prev = NNS;
}
@@ -7856,9 +7989,16 @@
Builder.MakeGlobal(Context, ColonColonLoc);
break;
}
+
+ case NestedNameSpecifier::Super: {
+ CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(F, Record, Idx);
+ SourceRange Range = ReadSourceRange(F, Record, Idx);
+ Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd());
+ break;
+ }
}
}
-
+
return Builder.getWithLocInContext(Context);
}
@@ -8002,6 +8142,14 @@
}
}
+void ASTReader::getInputFiles(ModuleFile &F,
+ SmallVectorImpl<serialization::InputFile> &Files) {
+ for (unsigned I = 0, E = F.InputFilesLoaded.size(); I != E; ++I) {
+ unsigned ID = I+1;
+ Files.push_back(getInputFile(F, ID));
+ }
+}
+
std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) {
// If we know the owning module, use it.
if (Module *M = D->getOwningModule())
@@ -8019,7 +8167,7 @@
while (!PendingIdentifierInfos.empty() ||
!PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() ||
!PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() ||
- !PendingUpdateRecords.empty() || !PendingOdrMergeChecks.empty()) {
+ !PendingUpdateRecords.empty()) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >
@@ -8067,14 +8215,16 @@
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
- if (Info.M->Kind != MK_Module)
+ if (Info.M->Kind != MK_ImplicitModule &&
+ Info.M->Kind != MK_ExplicitModule)
resolvePendingMacro(II, Info);
}
// Handle module imports.
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
- if (Info.M->Kind == MK_Module)
+ if (Info.M->Kind == MK_ImplicitModule ||
+ Info.M->Kind == MK_ExplicitModule)
resolvePendingMacro(II, Info);
}
}
@@ -8091,110 +8241,36 @@
}
// Perform any pending declaration updates.
- //
- // Don't do this if we have known-incomplete redecl chains: it relies on
- // being able to walk redeclaration chains.
- while (PendingDeclChains.empty() && !PendingUpdateRecords.empty()) {
+ while (!PendingUpdateRecords.empty()) {
auto Update = PendingUpdateRecords.pop_back_val();
ReadingKindTracker ReadingKind(Read_Decl, *this);
loadDeclUpdateRecords(Update.first, Update.second);
}
-
- // Trigger the import of the full definition of each class that had any
- // odr-merging problems, so we can produce better diagnostics for them.
- for (auto &Merge : PendingOdrMergeFailures) {
- Merge.first->buildLookup();
- Merge.first->decls_begin();
- Merge.first->bases_begin();
- Merge.first->vbases_begin();
- for (auto *RD : Merge.second) {
- RD->decls_begin();
- RD->bases_begin();
- RD->vbases_begin();
- }
- }
-
- // For each declaration from a merged context, check that the canonical
- // definition of that context also contains a declaration of the same
- // entity.
- while (!PendingOdrMergeChecks.empty()) {
- NamedDecl *D = PendingOdrMergeChecks.pop_back_val();
-
- // FIXME: Skip over implicit declarations for now. This matters for things
- // like implicitly-declared special member functions. This isn't entirely
- // correct; we can end up with multiple unmerged declarations of the same
- // implicit entity.
- if (D->isImplicit())
- continue;
-
- DeclContext *CanonDef = D->getDeclContext();
- DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName());
-
- bool Found = false;
- const Decl *DCanon = D->getCanonicalDecl();
-
- llvm::SmallVector<const NamedDecl*, 4> Candidates;
- for (DeclContext::lookup_iterator I = R.begin(), E = R.end();
- !Found && I != E; ++I) {
- for (auto RI : (*I)->redecls()) {
- if (RI->getLexicalDeclContext() == CanonDef) {
- // This declaration is present in the canonical definition. If it's
- // in the same redecl chain, it's the one we're looking for.
- if (RI->getCanonicalDecl() == DCanon)
- Found = true;
- else
- Candidates.push_back(cast<NamedDecl>(RI));
- break;
- }
- }
- }
-
- if (!Found) {
- D->setInvalidDecl();
-
- std::string CanonDefModule =
- getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
- Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl)
- << D << getOwningModuleNameForDiagnostic(D)
- << CanonDef << CanonDefModule.empty() << CanonDefModule;
-
- if (Candidates.empty())
- Diag(cast<Decl>(CanonDef)->getLocation(),
- diag::note_module_odr_violation_no_possible_decls) << D;
- else {
- for (unsigned I = 0, N = Candidates.size(); I != N; ++I)
- Diag(Candidates[I]->getLocation(),
- diag::note_module_odr_violation_possible_decl)
- << Candidates[I];
- }
-
- DiagnosedOdrMergeFailures.insert(CanonDef);
- }
- }
}
// 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
// happen now, after the redeclaration chains have been fully wired.
- for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
- DEnd = PendingDefinitions.end();
- D != DEnd; ++D) {
- if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
+ for (Decl *D : PendingDefinitions) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
if (const TagType *TagT = dyn_cast<TagType>(TD->getTypeForDecl())) {
// 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())
+ if (auto RD = dyn_cast<CXXRecordDecl>(D)) {
+ for (auto R : RD->redecls()) {
+ assert((R == D) == R->isThisDeclarationADefinition() &&
+ "declaration thinks it's the definition but it isn't");
cast<CXXRecordDecl>(R)->DefinitionData = RD->DefinitionData;
+ }
}
continue;
}
- if (auto ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+ 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;
@@ -8205,14 +8281,14 @@
continue;
}
- if (auto PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+ if (auto PD = dyn_cast<ObjCProtocolDecl>(D)) {
for (auto R : PD->redecls())
R->Data = PD->Data;
continue;
}
- auto RTD = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+ auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
for (auto R : RTD->redecls())
R->Common = RTD->Common;
}
@@ -8237,10 +8313,108 @@
MD->setLazyBody(PB->second);
}
PendingBodies.clear();
+}
+
+void ASTReader::diagnoseOdrViolations() {
+ if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty())
+ return;
+
+ // Trigger the import of the full definition of each class that had any
+ // odr-merging problems, so we can produce better diagnostics for them.
+ // These updates may in turn find and diagnose some ODR failures, so take
+ // ownership of the set first.
+ auto OdrMergeFailures = std::move(PendingOdrMergeFailures);
+ PendingOdrMergeFailures.clear();
+ for (auto &Merge : OdrMergeFailures) {
+ Merge.first->buildLookup();
+ Merge.first->decls_begin();
+ Merge.first->bases_begin();
+ Merge.first->vbases_begin();
+ for (auto *RD : Merge.second) {
+ RD->decls_begin();
+ RD->bases_begin();
+ RD->vbases_begin();
+ }
+ }
+
+ // For each declaration from a merged context, check that the canonical
+ // definition of that context also contains a declaration of the same
+ // entity.
+ //
+ // Caution: this loop does things that might invalidate iterators into
+ // PendingOdrMergeChecks. Don't turn this into a range-based for loop!
+ while (!PendingOdrMergeChecks.empty()) {
+ NamedDecl *D = PendingOdrMergeChecks.pop_back_val();
+
+ // FIXME: Skip over implicit declarations for now. This matters for things
+ // like implicitly-declared special member functions. This isn't entirely
+ // correct; we can end up with multiple unmerged declarations of the same
+ // implicit entity.
+ if (D->isImplicit())
+ continue;
+
+ DeclContext *CanonDef = D->getDeclContext();
+
+ bool Found = false;
+ const Decl *DCanon = D->getCanonicalDecl();
+
+ for (auto RI : D->redecls()) {
+ if (RI->getLexicalDeclContext() == CanonDef) {
+ Found = true;
+ break;
+ }
+ }
+ if (Found)
+ continue;
+
+ llvm::SmallVector<const NamedDecl*, 4> Candidates;
+ DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName());
+ for (DeclContext::lookup_iterator I = R.begin(), E = R.end();
+ !Found && I != E; ++I) {
+ for (auto RI : (*I)->redecls()) {
+ if (RI->getLexicalDeclContext() == CanonDef) {
+ // This declaration is present in the canonical definition. If it's
+ // in the same redecl chain, it's the one we're looking for.
+ if (RI->getCanonicalDecl() == DCanon)
+ Found = true;
+ else
+ Candidates.push_back(cast<NamedDecl>(RI));
+ break;
+ }
+ }
+ }
+
+ if (!Found) {
+ // The AST doesn't like TagDecls becoming invalid after they've been
+ // completed. We only really need to mark FieldDecls as invalid here.
+ if (!isa<TagDecl>(D))
+ D->setInvalidDecl();
+
+ std::string CanonDefModule =
+ getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
+ Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl)
+ << D << getOwningModuleNameForDiagnostic(D)
+ << CanonDef << CanonDefModule.empty() << CanonDefModule;
+
+ if (Candidates.empty())
+ Diag(cast<Decl>(CanonDef)->getLocation(),
+ diag::note_module_odr_violation_no_possible_decls) << D;
+ else {
+ for (unsigned I = 0, N = Candidates.size(); I != N; ++I)
+ Diag(Candidates[I]->getLocation(),
+ diag::note_module_odr_violation_possible_decl)
+ << Candidates[I];
+ }
+
+ DiagnosedOdrMergeFailures.insert(CanonDef);
+ }
+ }
// Issue any pending ODR-failure diagnostics.
- for (auto &Merge : PendingOdrMergeFailures) {
- if (!DiagnosedOdrMergeFailures.insert(Merge.first))
+ for (auto &Merge : OdrMergeFailures) {
+ // If we've already pointed out a specific problem with this class, don't
+ // bother issuing a general "something's different" diagnostic.
+ if (!DiagnosedOdrMergeFailures.insert(Merge.first).second)
continue;
bool Diagnosed = false;
@@ -8276,7 +8450,6 @@
<< Merge.first;
}
}
- PendingOdrMergeFailures.clear();
}
void ASTReader::FinishedDeserializing() {
@@ -8289,10 +8462,13 @@
}
--NumCurrentElementsDeserializing;
- if (NumCurrentElementsDeserializing == 0 && Consumer) {
+ if (NumCurrentElementsDeserializing == 0) {
+ diagnoseOdrViolations();
+
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
- PassInterestingDeclsToConsumer();
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
}
}