summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp1341
1 files changed, 781 insertions, 560 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index ae41654..416164e 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -80,10 +80,14 @@ void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) {
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 @@ ASTReaderListener::~ASTReaderListener() {}
/// 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 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
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 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
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 @@ bool PCHValidator::ReadDiagnosticOptions(
// 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 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
continue;
SuggestedPredefines += "#include \"";
- SuggestedPredefines +=
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += File;
SuggestedPredefines += "\"\n";
}
@@ -556,8 +572,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
continue;
SuggestedPredefines += "#__include_macros \"";
- SuggestedPredefines +=
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += File;
SuggestedPredefines += "\"\n##\n";
}
@@ -635,14 +650,14 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
Result.ID = Reader.getGlobalSelectorID(
F, endian::readNext<uint32_t, little, unaligned>(d));
- unsigned NumInstanceMethodsAndBits =
- endian::readNext<uint16_t, little, unaligned>(d);
- unsigned NumFactoryMethodsAndBits =
- endian::readNext<uint16_t, little, unaligned>(d);
- Result.InstanceBits = NumInstanceMethodsAndBits & 0x3;
- Result.FactoryBits = NumFactoryMethodsAndBits & 0x3;
- unsigned NumInstanceMethods = NumInstanceMethodsAndBits >> 2;
- unsigned NumFactoryMethods = NumFactoryMethodsAndBits >> 2;
+ unsigned FullInstanceBits = endian::readNext<uint16_t, little, unaligned>(d);
+ unsigned FullFactoryBits = endian::readNext<uint16_t, little, unaligned>(d);
+ Result.InstanceBits = FullInstanceBits & 0x3;
+ Result.InstanceHasMoreThanOneDecl = (FullInstanceBits >> 2) & 0x1;
+ Result.FactoryBits = FullFactoryBits & 0x3;
+ Result.FactoryHasMoreThanOneDecl = (FullFactoryBits >> 2) & 0x1;
+ unsigned NumInstanceMethods = FullInstanceBits >> 3;
+ unsigned NumFactoryMethods = FullFactoryBits >> 3;
// Load instance methods
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
@@ -774,15 +789,16 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
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;
@@ -1013,7 +1029,7 @@ void ASTReader::Error(unsigned DiagID,
/// \brief Read the line table in the source manager block.
/// \returns true if there was an error.
bool ASTReader::ParseLineTable(ModuleFile &F,
- SmallVectorImpl<uint64_t> &Record) {
+ const RecordData &Record) {
unsigned Idx = 0;
LineTableInfo &LineTable = SourceMgr.getLineTable();
@@ -1021,10 +1037,7 @@ bool ASTReader::ParseLineTable(ModuleFile &F,
std::map<int, int> FileIDs;
for (int I = 0, N = Record[Idx++]; I != N; ++I) {
// Extract the file name
- unsigned FilenameLen = Record[Idx++];
- std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
- Idx += FilenameLen;
- MaybeAddSystemRootToFilename(F, Filename);
+ auto Filename = ReadPath(F, Record, Idx);
FileIDs[I] = LineTable.getLineTableFilenameID(Filename);
}
@@ -1225,9 +1238,9 @@ bool ASTReader::ReadSLocEntry(int ID) {
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 +1252,8 @@ bool ASTReader::ReadSLocEntry(int ID) {
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 +1266,10 @@ bool ASTReader::ReadSLocEntry(int ID) {
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 +1299,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
// 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
@@ -1466,11 +1480,11 @@ ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const
unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
return llvm::hash_combine(ikey.Size, ikey.ModTime);
}
-
+
HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
internal_key_type ikey = { FE->getSize(), FE->getModificationTime(),
- FE->getName() };
+ FE->getName(), /*Imported*/false };
return ikey;
}
@@ -1478,14 +1492,24 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
if (a.Size != b.Size || a.ModTime != b.ModTime)
return false;
- if (strcmp(a.Filename, b.Filename) == 0)
+ if (llvm::sys::path::is_absolute(a.Filename) &&
+ strcmp(a.Filename, b.Filename) == 0)
return true;
// Determine whether the actual files are equivalent.
FileManager &FileMgr = Reader.getFileManager();
- const FileEntry *FEA = FileMgr.getFile(a.Filename);
- const FileEntry *FEB = FileMgr.getFile(b.Filename);
- return (FEA && FEA == FEB);
+ auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {
+ if (!Key.Imported)
+ return FileMgr.getFile(Key.Filename);
+
+ std::string Resolved = Key.Filename;
+ Reader.ResolveImportedPath(M, Resolved);
+ return FileMgr.getFile(Resolved);
+ };
+
+ const FileEntry *FEA = GetFile(a);
+ const FileEntry *FEB = GetFile(b);
+ return FEA && FEA == FEB;
}
std::pair<unsigned, unsigned>
@@ -1503,6 +1527,7 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
ikey.Size = off_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.ModTime = time_t(endian::readNext<uint64_t, little, unaligned>(d));
ikey.Filename = (const char *)d;
+ ikey.Imported = true;
return ikey;
}
@@ -1542,7 +1567,14 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
FileManager &FileMgr = Reader.getFileManager();
ModuleMap &ModMap =
Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), HFI.getHeaderRole());
+ // FIXME: This information should be propagated through the
+ // SUBMODULE_HEADER etc records rather than from here.
+ // FIXME: We don't ever mark excluded headers.
+ std::string Filename = key.Filename;
+ if (key.Imported)
+ Reader.ResolveImportedPath(M, Filename);
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
+ ModMap.addHeader(Mod, H, HFI.getHeaderRole());
}
}
@@ -1732,10 +1764,12 @@ struct ASTReader::ModuleMacroInfo {
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 +1806,8 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
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;
@@ -1790,13 +1825,13 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
// install if we make this module visible.
HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI));
} else {
- installImportedMacro(II, MMI, Owner, /*FromFinalization*/false);
+ installImportedMacro(II, MMI, Owner);
}
}
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 +1863,36 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
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 +1925,27 @@ static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI,
}
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 +1959,7 @@ void ASTReader::removeOverriddenMacros(IdentifierInfo *II,
ASTReader::AmbiguousMacros *
ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ SourceLocation ImportLoc,
ArrayRef<SubmoduleID> Overrides) {
MacroDirective *Prev = PP.getMacroDirective(II);
if (!Prev && Overrides.empty())
@@ -1915,7 +1972,7 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II,
AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
Ambig.push_back(PrevDef);
- removeOverriddenMacros(II, Ambig, Overrides);
+ removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
if (!Ambig.empty())
return &Ambig;
@@ -1927,7 +1984,7 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II,
if (PrevDef)
Ambig.push_back(PrevDef);
- removeOverriddenMacros(II, Ambig, Overrides);
+ removeOverriddenMacros(II, ImportLoc, Ambig, Overrides);
if (!Ambig.empty()) {
AmbiguousMacros &Result = AmbiguousMacroDefs[II];
@@ -1941,11 +1998,11 @@ ASTReader::removeOverriddenMacros(IdentifierInfo *II,
}
void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
- Module *Owner, bool FromFinalization) {
+ Module *Owner) {
assert(II && Owner);
SourceLocation ImportLoc = Owner->MacroVisibilityLoc;
- if (ImportLoc.isInvalid() && !FromFinalization) {
+ 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
@@ -1955,18 +2012,16 @@ void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
}
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 +2029,14 @@ void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
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.
@@ -2035,14 +2094,14 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
off_t StoredSize;
time_t StoredTime;
bool Overridden;
-
+
assert(Record[0] == ID && "Bogus stored ID or offset");
StoredSize = static_cast<off_t>(Record[1]);
StoredTime = static_cast<time_t>(Record[2]);
Overridden = static_cast<bool>(Record[3]);
Filename = Blob;
- MaybeAddSystemRootToFilename(F, Filename);
-
+ ResolveImportedPath(F, Filename);
+
InputFileInfo R = { std::move(Filename), StoredSize, StoredTime, Overridden };
return R;
}
@@ -2128,12 +2187,23 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
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) {
@@ -2169,46 +2239,22 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
return IF;
}
-const FileEntry *ASTReader::getFileEntry(StringRef filenameStrRef) {
- ModuleFile &M = ModuleMgr.getPrimaryModule();
- std::string Filename = filenameStrRef;
- MaybeAddSystemRootToFilename(M, Filename);
- const FileEntry *File = FileMgr.getFile(Filename);
- if (File == nullptr && !M.OriginalDir.empty() && !CurrentDir.empty() &&
- M.OriginalDir != CurrentDir) {
- std::string resolved = resolveFileRelativeToOriginalDir(Filename,
- M.OriginalDir,
- CurrentDir);
- if (!resolved.empty())
- File = FileMgr.getFile(resolved);
- }
-
- return File;
+/// \brief If we are loading a relocatable PCH or module file, and the filename
+/// is not an absolute path, add the system or module root to the beginning of
+/// the file name.
+void ASTReader::ResolveImportedPath(ModuleFile &M, std::string &Filename) {
+ // Resolve relative to the base directory, if we have one.
+ if (!M.BaseDirectory.empty())
+ return ResolveImportedPath(Filename, M.BaseDirectory);
}
-/// \brief If we are loading a relocatable PCH file, and the filename is
-/// not an absolute path, add the system root to the beginning of the file
-/// name.
-void ASTReader::MaybeAddSystemRootToFilename(ModuleFile &M,
- std::string &Filename) {
- // If this is not a relocatable PCH file, there's nothing to do.
- if (!M.RelocatablePCH)
- return;
-
+void ASTReader::ResolveImportedPath(std::string &Filename, StringRef Prefix) {
if (Filename.empty() || llvm::sys::path::is_absolute(Filename))
return;
- if (isysroot.empty()) {
- // If no system root was given, default to '/'
- Filename.insert(Filename.begin(), '/');
- return;
- }
-
- unsigned Length = isysroot.size();
- if (isysroot[Length - 1] != '/')
- Filename.insert(Filename.begin(), '/');
-
- Filename.insert(Filename.begin(), isysroot.begin(), isysroot.end());
+ SmallString<128> Buffer;
+ llvm::sys::path::append(Buffer, Prefix, Filename);
+ Filename.assign(Buffer.begin(), Buffer.end());
}
ASTReader::ASTReadResult
@@ -2223,8 +2269,16 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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 +2291,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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 +2302,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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) {
@@ -2324,6 +2374,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
}
F.RelocatablePCH = Record[4];
+ // Relative paths in a relocatable PCH are relative to our sysroot.
+ if (F.RelocatablePCH)
+ F.BaseDirectory = isysroot.empty() ? "/" : isysroot;
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
@@ -2335,6 +2388,11 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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,14 +2406,12 @@ ASTReader::ReadControlBlock(ModuleFile &F,
SourceLocation::getFromRawEncoding(Record[Idx++]);
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];
- unsigned Length = Record[Idx++];
- SmallString<128> ImportedFile(Record.begin() + Idx,
- Record.begin() + Idx + Length);
- Idx += Length;
+ ASTFileSignature StoredSignature = Record[Idx++];
+ auto ImportedFile = ReadPath(F, Record, Idx);
// 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 +2428,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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 +2449,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case DIAGNOSTIC_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParseDiagnosticOptions(Record, Complain, *Listener) &&
!DisableValidation)
return OutOfDate;
@@ -2400,6 +2459,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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 +2469,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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 +2479,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
case PREPROCESSOR_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
+ !AllowCompatibleConfigurationMismatch &&
ParsePreprocessorOptions(Record, Complain, *Listener,
SuggestedPredefines) &&
!DisableValidation && !AllowConfigurationMismatch)
@@ -2429,7 +2491,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.OriginalSourceFileID = FileID::get(Record[0]);
F.ActualOriginalSourceFileName = Blob;
F.OriginalSourceFileName = F.ActualOriginalSourceFileName;
- MaybeAddSystemRootToFilename(F, F.OriginalSourceFileName);
+ ResolveImportedPath(F, F.OriginalSourceFileName);
break;
case ORIGINAL_FILE_ID:
@@ -2446,46 +2508,43 @@ ASTReader::ReadControlBlock(ModuleFile &F,
Listener->ReadModuleName(F.ModuleName);
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.
+ case MODULE_DIRECTORY: {
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;
+ "MODULE_DIRECTORY found before MODULE_NAME");
+ // If we've already loaded a module map file covering this module, we may
+ // have a better path for it (relative to the current build).
+ Module *M = PP.getHeaderSearchInfo().lookupModule(F.ModuleName);
+ if (M && M->Directory) {
+ // If we're implicitly loading a module, the base directory can't
+ // change between the build and use.
+ if (F.Kind != MK_ExplicitModule) {
+ const DirectoryEntry *BuildDir =
+ PP.getFileManager().getDirectory(Blob);
+ if (!BuildDir || BuildDir != M->Directory) {
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Diag(diag::err_imported_module_relocated)
+ << F.ModuleName << Blob << M->Directory->getName();
+ return OutOfDate;
+ }
}
+ F.BaseDirectory = M->Directory->getName();
+ } else {
+ F.BaseDirectory = Blob;
}
+ break;
+ }
- if (Listener)
- Listener->ReadModuleMapFile(F.ModuleMapPath);
+ case MODULE_MAP_FILE:
+ 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 +2687,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.TypeRemap.insertOrReplace(
std::make_pair(LocalBaseTypeIndex,
F.BaseTypeIndex - LocalBaseTypeIndex));
-
+
TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
}
break;
@@ -2658,7 +2717,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Introduce the global -> local mapping for declarations within this
// module.
F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
-
+
DeclsLoaded.resize(DeclsLoaded.size() + F.LocalNumDecls);
}
break;
@@ -2687,7 +2746,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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 +2787,8 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.IdentifierRemap.insertOrReplace(
std::make_pair(LocalBaseIdentifierID,
F.BaseIdentifierID - LocalBaseIdentifierID));
-
- IdentifiersLoaded.resize(IdentifiersLoaded.size()
+
+ IdentifiersLoaded.resize(IdentifiersLoaded.size()
+ F.LocalNumIdentifiers);
}
break;
@@ -2823,7 +2881,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
std::make_pair(LocalBaseSelectorID,
F.BaseSelectorID - LocalBaseSelectorID));
- SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);
+ SelectorsLoaded.resize(SelectorsLoaded.size() + F.LocalNumSelectors);
}
break;
}
@@ -2904,19 +2962,16 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
// 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 +3001,23 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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 +3258,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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 +3339,110 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
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 = ReadPath(F, 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 = ReadPath(F, 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.
@@ -3305,7 +3457,7 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
bool Found = false;
for (ObjCMethodList *List = &Start; List; List = List->getNext()) {
if (!Found) {
- if (List->Method == Method) {
+ if (List->getMethod() == Method) {
Found = true;
} else {
// Keep searching.
@@ -3314,9 +3466,9 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
}
if (List->getNext())
- List->Method = List->getNext()->Method;
+ List->setMethod(List->getNext()->getMethod());
else
- List->Method = Method;
+ List->setMethod(Method);
}
}
@@ -3336,8 +3488,13 @@ void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner,
assert((FromFinalization || Owner->NameVisibility >= Module::MacrosVisible) &&
"nothing to make visible?");
- for (const auto &Macro : Names.HiddenMacros)
- installImportedMacro(Macro.first, Macro.second, Owner, FromFinalization);
+ 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,
@@ -3385,7 +3542,7 @@ void ASTReader::makeModuleVisible(Module *Mod,
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);
}
@@ -3435,10 +3592,9 @@ bool ASTReader::isGlobalIndexUnavailable() const {
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";
}
@@ -3460,7 +3616,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
SmallVector<ImportedModule, 4> Loaded;
switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc,
/*ImportedBy=*/nullptr, Loaded,
- 0, 0,
+ 0, 0, 0,
ClientLoadCapabilities)) {
case Failure:
case Missing:
@@ -3618,7 +3774,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
// 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);
}
}
@@ -3627,6 +3783,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
return Success;
}
+static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+
ASTReader::ASTReadResult
ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type,
@@ -3634,12 +3792,14 @@ ASTReader::ReadASTCore(StringRef FileName,
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) {
@@ -3651,7 +3811,7 @@ ASTReader::ReadASTCore(StringRef FileName,
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;
@@ -3690,7 +3850,7 @@ ASTReader::ReadASTCore(StringRef FileName,
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.
@@ -3937,6 +4097,34 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
}
}
+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.
@@ -3944,20 +4132,18 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
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' ||
@@ -4012,9 +4198,10 @@ namespace {
{
}
- 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 {
@@ -4033,19 +4220,16 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
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' ||
@@ -4061,6 +4245,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
bool NeedsInputFiles = Listener.needsInputFileVisitation();
bool NeedsSystemInputFiles = Listener.needsSystemInputFileVisitation();
+ bool NeedsImports = Listener.needsImportVisitation();
BitstreamCursor InputFilesCursor;
if (NeedsInputFiles) {
InputFilesCursor = Stream;
@@ -4083,6 +4268,7 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
// Scan for ORIGINAL_FILE inside the control block.
RecordData Record;
+ std::string ModuleDir;
while (1) {
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
@@ -4107,11 +4293,19 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
case MODULE_NAME:
Listener.ReadModuleName(Blob);
break;
- case MODULE_MAP_FILE:
- Listener.ReadModuleMapFile(Blob);
+ case MODULE_DIRECTORY:
+ ModuleDir = Blob;
break;
+ case MODULE_MAP_FILE: {
+ unsigned Idx = 0;
+ auto Path = ReadString(Record, Idx);
+ ResolveImportedPath(Path, ModuleDir);
+ Listener.ReadModuleMapFile(Path);
+ break;
+ }
case LANGUAGE_OPTIONS:
- if (ParseLanguageOptions(Record, false, Listener))
+ if (ParseLanguageOptions(Record, false, Listener,
+ /*AllowCompatibleConfigurationMismatch*/false))
return true;
break;
@@ -4168,7 +4362,10 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
switch ((InputFileRecordTypes)Cursor.readRecord(Code, Record, &Blob)) {
case INPUT_FILE:
bool Overridden = static_cast<bool>(Record[3]);
- shouldContinue = Listener.visitInputFile(Blob, isSystemFile, Overridden);
+ std::string Filename = Blob;
+ ResolveImportedPath(Filename, ModuleDir);
+ shouldContinue =
+ Listener.visitInputFile(Filename, isSystemFile, Overridden);
break;
}
if (!shouldContinue)
@@ -4177,6 +4374,21 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
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
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(Filename, ModuleDir);
+ Listener.visitImport(Filename);
+ }
+ break;
+ }
+
default:
// No other validation to perform.
break;
@@ -4224,21 +4436,30 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// 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++]);
@@ -4253,20 +4474,17 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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]) {
@@ -4311,14 +4529,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
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);
@@ -4331,73 +4541,26 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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.
- // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead
- // of complete filenames or remove it entirely.
- 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.
+ 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;
- }
-
- case SUBMODULE_PRIVATE_HEADER: {
- if (First) {
- Error("missing submodule metadata record at beginning of block");
- return Failure;
- }
+ break;
- 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())
@@ -4412,12 +4575,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
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];
@@ -4431,21 +4588,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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;
@@ -4459,14 +4608,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
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;
@@ -4483,53 +4624,21 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
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;
@@ -4553,7 +4662,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
/// \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) \
@@ -4561,7 +4671,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
#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++];
@@ -4581,7 +4692,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
}
LangOpts.CommentOpts.ParseAllComments = Record[Idx++];
- return Listener.ReadLanguageOptions(LangOpts, Complain);
+ return Listener.ReadLanguageOptions(LangOpts, Complain,
+ AllowCompatibleDifferences);
}
bool ASTReader::ParseTargetOptions(const RecordData &Record,
@@ -5235,17 +5347,19 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
/*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);
}
@@ -5414,13 +5528,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
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);
}
@@ -5508,24 +5627,22 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
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);
}
}
@@ -5976,18 +6093,10 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
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)) {
@@ -6000,6 +6109,9 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
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();
}
}
}
@@ -6345,13 +6457,13 @@ namespace {
/// 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) { }
@@ -6364,9 +6476,9 @@ namespace {
// 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;
@@ -6375,7 +6487,7 @@ namespace {
if (!FoundInfo)
return false;
-
+
// Look for this name within this module.
ASTDeclContextNameLookupTable *LookupTable =
Info->second.NameLookupTableData;
@@ -6396,9 +6508,11 @@ namespace {
// 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);
@@ -6438,15 +6552,17 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
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()) {
@@ -6454,24 +6570,45 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
}
}
- if (isa<CXXRecordDecl>(DC)) {
- auto Merged = MergedLookups.find(DC);
- if (Merged != MergedLookups.end())
- Contexts.insert(Contexts.end(), Merged->second.begin(),
- Merged->second.end());
- }
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls);
+ 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(DC, *this))) {
- DeclContextNameLookupVisitor::visit(*Definitive, &Visitor);
- } else {
- ModuleMgr.visit(&DeclContextNameLookupVisitor::visit, &Visitor);
+ // 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 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);
+ }
+ }
+ }
}
+
++NumVisibleDeclContextsRead;
SetExternalVisibleDeclsForName(DC, Name, Decls);
return !Decls.empty();
@@ -6786,11 +6923,11 @@ void ASTReader::InitializeSema(Sema &S) {
// 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()) {
@@ -6924,15 +7061,18 @@ namespace clang { namespace serialization {
unsigned PriorGeneration;
unsigned InstanceBits;
unsigned FactoryBits;
+ bool InstanceHasMoreThanOneDecl;
+ bool FactoryHasMoreThanOneDecl;
SmallVector<ObjCMethodDecl *, 4> InstanceMethods;
SmallVector<ObjCMethodDecl *, 4> FactoryMethods;
public:
- ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel,
+ ReadMethodPoolVisitor(ASTReader &Reader, Selector Sel,
unsigned PriorGeneration)
- : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration),
- InstanceBits(0), FactoryBits(0) { }
-
+ : Reader(Reader), Sel(Sel), PriorGeneration(PriorGeneration),
+ InstanceBits(0), FactoryBits(0), InstanceHasMoreThanOneDecl(false),
+ FactoryHasMoreThanOneDecl(false) {}
+
static bool visit(ModuleFile &M, void *UserData) {
ReadMethodPoolVisitor *This
= static_cast<ReadMethodPoolVisitor *>(UserData);
@@ -6966,6 +7106,8 @@ namespace clang { namespace serialization {
This->FactoryMethods.append(Data.Factory.begin(), Data.Factory.end());
This->InstanceBits = Data.InstanceBits;
This->FactoryBits = Data.FactoryBits;
+ This->InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl;
+ This->FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl;
return true;
}
@@ -6981,6 +7123,10 @@ namespace clang { namespace serialization {
unsigned getInstanceBits() const { return InstanceBits; }
unsigned getFactoryBits() const { return FactoryBits; }
+ bool instanceHasMoreThanOneDecl() const {
+ return InstanceHasMoreThanOneDecl;
+ }
+ bool factoryHasMoreThanOneDecl() const { return FactoryHasMoreThanOneDecl; }
};
} } // end namespace clang::serialization
@@ -7015,11 +7161,17 @@ void ASTReader::ReadMethodPool(Selector Sel) {
Sema &S = *getSema();
Sema::GlobalMethodPool::iterator Pos
= S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
-
- addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
- addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
+
Pos->second.first.setBits(Visitor.getInstanceBits());
+ Pos->second.first.setHasMoreThanOneDecl(Visitor.instanceHasMoreThanOneDecl());
Pos->second.second.setBits(Visitor.getFactoryBits());
+ Pos->second.second.setHasMoreThanOneDecl(Visitor.factoryHasMoreThanOneDecl());
+
+ // Add methods to the global pool *after* setting hasMoreThanOneDecl, since
+ // when building a module we keep every method individually and may need to
+ // update hasMoreThanOneDecl as we add the methods.
+ addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first);
+ addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second);
}
void ASTReader::ReadKnownNamespaces(
@@ -7095,6 +7247,18 @@ void ASTReader::ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {
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) {
@@ -7230,24 +7394,26 @@ ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
}
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);
}
}
@@ -7584,8 +7750,7 @@ ASTReader::ReadTemplateArgument(ModuleFile &F,
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);
@@ -7806,6 +7971,12 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
// 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;
}
@@ -7862,9 +8033,16 @@ ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
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);
}
@@ -7906,6 +8084,13 @@ std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
return Result;
}
+std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx) {
+ std::string Filename = ReadString(Record, Idx);
+ ResolveImportedPath(F, Filename);
+ return Filename;
+}
+
VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
unsigned &Idx) {
unsigned Major = Record[Idx++];
@@ -8008,6 +8193,14 @@ void ASTReader::ReadComments() {
}
}
+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())
@@ -8025,7 +8218,7 @@ void ASTReader::finishPendingActions() {
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> >
@@ -8073,14 +8266,16 @@ void ASTReader::finishPendingActions() {
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);
}
}
@@ -8097,110 +8292,36 @@ void ASTReader::finishPendingActions() {
}
// 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;
@@ -8211,14 +8332,14 @@ void ASTReader::finishPendingActions() {
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;
}
@@ -8243,10 +8364,108 @@ void ASTReader::finishPendingActions() {
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;
@@ -8282,7 +8501,6 @@ void ASTReader::finishPendingActions() {
<< Merge.first;
}
}
- PendingOdrMergeFailures.clear();
}
void ASTReader::FinishedDeserializing() {
@@ -8295,10 +8513,13 @@ void ASTReader::FinishedDeserializing() {
}
--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();
}
}
OpenPOWER on IntegriCloud