Update aosp/master Clang for rebase to r222490.
Change-Id: Ic557ac55e97fbf6ee08771c7b7c3594777b0aefd
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index ad046ff..1339322 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "ASTCommon.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTDeserializationListener.h"
@@ -150,7 +151,7 @@
switch (static_cast<Decl::Kind>(Kind)) {
case Decl::TranslationUnit: // Special case of a "merged" declaration.
case Decl::Namespace:
- case Decl::NamespaceAlias: // FIXME: Not yet redeclarable, but will be.
+ case Decl::NamespaceAlias:
case Decl::Typedef:
case Decl::TypeAlias:
case Decl::Enum:
@@ -188,8 +189,6 @@
case Decl::MSProperty:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
- case Decl::ImplicitParam:
- case Decl::ParmVar:
case Decl::NonTypeTemplateParm:
case Decl::TemplateTemplateParm:
case Decl::Using:
@@ -212,7 +211,20 @@
case Decl::Import:
case Decl::OMPThreadPrivate:
return false;
+
+ // These indirectly derive from Redeclarable<T> but are not actually
+ // redeclarable.
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ return false;
}
llvm_unreachable("Unhandled declaration kind");
}
+
+bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
+ if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
+ return false;
+ return isa<TagDecl>(D) || isa<FieldDecl>(D);
+}
+
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index c766974..38a0ff5 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/lib/Serialization/ASTCommon.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
-#define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
+#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
+#define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
#include "clang/AST/ASTContext.h"
#include "clang/Serialization/ASTBitCodes.h"
@@ -25,14 +25,15 @@
UPD_CXX_ADDED_IMPLICIT_MEMBER,
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
+ UPD_CXX_ADDED_FUNCTION_DEFINITION,
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
- UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
UPD_DECL_MARKED_USED,
UPD_MANGLING_NUMBER,
- UPD_STATIC_LOCAL_NUMBER
+ UPD_STATIC_LOCAL_NUMBER,
+ UPD_DECL_MARKED_OPENMP_THREADPRIVATE
};
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
@@ -80,6 +81,10 @@
/// \brief Determine whether the given declaration kind is redeclarable.
bool isRedeclarableDeclKind(unsigned Kind);
+/// \brief Determine whether the given declaration needs an anonymous
+/// declaration number.
+bool needsAnonymousDeclarationNumber(const NamedDecl *D);
+
} // namespace serialization
} // namespace clang
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();
}
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index d8495da..a783183 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -43,6 +43,9 @@
const RecordData &Record;
unsigned &Idx;
TypeID TypeIDForTypeDecl;
+ unsigned AnonymousDeclNumber;
+ GlobalDeclID NamedDeclForTagDecl;
+ IdentifierInfo *TypedefNameForLinkage;
bool HasPendingBody;
@@ -106,12 +109,18 @@
void MergeDefinitionData(CXXRecordDecl *D,
struct CXXRecordDecl::DefinitionData &NewDD);
+ static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
+ DeclContext *DC,
+ unsigned Index);
+ static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
+ unsigned Index, NamedDecl *D);
+
/// \brief RAII class used to capture the first ID within a redeclaration
/// chain and to introduce it into the list of pending redeclaration chains
/// on destruction.
///
- /// The caller can choose not to introduce this ID into the redeclaration
- /// chain by calling \c suppress().
+ /// The caller can choose not to introduce this ID into the list of pending
+ /// redeclaration chains by calling \c suppress().
class RedeclarableResult {
ASTReader &Reader;
GlobalDeclID FirstID;
@@ -134,7 +143,7 @@
~RedeclarableResult() {
if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) &&
- Reader.PendingDeclChainsKnown.insert(FirstID))
+ Reader.PendingDeclChainsKnown.insert(FirstID).second)
Reader.PendingDeclChains.push_back(FirstID);
}
@@ -158,50 +167,59 @@
NamedDecl *New;
NamedDecl *Existing;
mutable bool AddResult;
-
+
+ unsigned AnonymousDeclNumber;
+ IdentifierInfo *TypedefNameForLinkage;
+
void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION;
-
+
public:
FindExistingResult(ASTReader &Reader)
- : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {}
+ : Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false),
+ AnonymousDeclNumber(0), TypedefNameForLinkage(0) {}
- FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
- : Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
-
+ FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
+ unsigned AnonymousDeclNumber,
+ IdentifierInfo *TypedefNameForLinkage)
+ : Reader(Reader), New(New), Existing(Existing), AddResult(true),
+ AnonymousDeclNumber(AnonymousDeclNumber),
+ TypedefNameForLinkage(TypedefNameForLinkage) {}
+
FindExistingResult(const FindExistingResult &Other)
- : Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
- AddResult(Other.AddResult)
- {
+ : Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
+ AddResult(Other.AddResult),
+ AnonymousDeclNumber(Other.AnonymousDeclNumber),
+ TypedefNameForLinkage(Other.TypedefNameForLinkage) {
Other.AddResult = false;
}
-
+
~FindExistingResult();
-
+
/// \brief Suppress the addition of this result into the known set of
/// names.
void suppress() { AddResult = false; }
-
+
operator NamedDecl*() const { return Existing; }
-
+
template<typename T>
operator T*() const { return dyn_cast_or_null<T>(Existing); }
};
-
+
FindExistingResult findExisting(NamedDecl *D);
-
+
public:
- ASTDeclReader(ASTReader &Reader, ModuleFile &F,
- DeclID thisDeclID,
- unsigned RawLocation,
- const RecordData &Record, unsigned &Idx)
- : Reader(Reader), F(F), ThisDeclID(thisDeclID),
- RawLocation(RawLocation), Record(Record), Idx(Idx),
- TypeIDForTypeDecl(0), HasPendingBody(false) { }
+ ASTDeclReader(ASTReader &Reader, ModuleFile &F, DeclID thisDeclID,
+ unsigned RawLocation, const RecordData &Record, unsigned &Idx)
+ : Reader(Reader), F(F), ThisDeclID(thisDeclID),
+ RawLocation(RawLocation), Record(Record), Idx(Idx),
+ TypeIDForTypeDecl(0), NamedDeclForTagDecl(0),
+ TypedefNameForLinkage(nullptr), HasPendingBody(false) {}
template <typename DeclT>
- static void attachPreviousDeclImpl(Redeclarable<DeclT> *D, Decl *Previous);
- static void attachPreviousDeclImpl(...);
- static void attachPreviousDecl(Decl *D, Decl *previous);
+ static void attachPreviousDeclImpl(ASTReader &Reader,
+ Redeclarable<DeclT> *D, Decl *Previous);
+ static void attachPreviousDeclImpl(ASTReader &Reader, ...);
+ static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous);
template <typename DeclT>
static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
@@ -233,7 +251,7 @@
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
void VisitTypeDecl(TypeDecl *TD);
- void VisitTypedefNameDecl(TypedefNameDecl *TD);
+ RedeclarableResult VisitTypedefNameDecl(TypedefNameDecl *TD);
void VisitTypedefDecl(TypedefDecl *TD);
void VisitTypeAliasDecl(TypeAliasDecl *TD);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
@@ -359,6 +377,12 @@
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
// We have a fully initialized TypeDecl. Read its type now.
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
+
+ // If this is a tag declaration with a typedef name for linkage, it's safe
+ // to load that typedef now.
+ if (NamedDeclForTagDecl)
+ cast<TagDecl>(D)->NamedDeclOrQualifier =
+ cast<NamedDecl>(Reader.GetDecl(NamedDeclForTagDecl));
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull();
@@ -446,6 +470,8 @@
void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
VisitDecl(ND);
ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
+ if (needsAnonymousDeclarationNumber(ND))
+ AnonymousDeclNumber = Record[Idx++];
}
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
@@ -455,7 +481,8 @@
TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
}
-void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
+ASTDeclReader::RedeclarableResult
+ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx);
@@ -464,15 +491,21 @@
TD->setModedTypeSourceInfo(TInfo, modedT);
} else
TD->setTypeSourceInfo(TInfo);
- mergeRedeclarable(TD, Redecl);
+ return Redecl;
}
void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
- VisitTypedefNameDecl(TD);
+ RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
+ mergeRedeclarable(TD, Redecl);
}
void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
- VisitTypedefNameDecl(TD);
+ RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
+ if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>(Record, Idx))
+ // Merged when we merge the template.
+ TD->setDescribedAliasTemplate(Template);
+ else
+ mergeRedeclarable(TD, Redecl);
}
ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
@@ -481,18 +514,32 @@
TD->IdentifierNamespace = Record[Idx++];
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
- TD->setCompleteDefinition(Record[Idx++]);
+ if (!isa<CXXRecordDecl>(TD))
+ TD->setCompleteDefinition(Record[Idx++]);
TD->setEmbeddedInDeclarator(Record[Idx++]);
TD->setFreeStanding(Record[Idx++]);
TD->setCompleteDefinitionRequired(Record[Idx++]);
TD->setRBraceLoc(ReadSourceLocation(Record, Idx));
- if (Record[Idx++]) { // hasExtInfo
+ switch (Record[Idx++]) {
+ case 0:
+ break;
+ case 1: { // ExtInfo
TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
ReadQualifierInfo(*Info, Record, Idx);
TD->NamedDeclOrQualifier = Info;
- } else
- TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx);
+ break;
+ }
+ case 2: // TypedefNameForAnonDecl
+ NamedDeclForTagDecl = ReadDeclID(Record, Idx);
+ TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx);
+ break;
+ case 3: // DeclaratorForAnonDecl
+ NamedDeclForTagDecl = ReadDeclID(Record, Idx);
+ break;
+ default:
+ llvm_unreachable("unexpected tag info kind");
+ }
if (!isa<CXXRecordDecl>(TD))
mergeRedeclarable(TD, Redecl);
@@ -953,8 +1000,15 @@
VisitDeclaratorDecl(FD);
FD->Mutable = Record[Idx++];
if (int BitWidthOrInitializer = Record[Idx++]) {
- FD->InitializerOrBitWidth.setInt(BitWidthOrInitializer - 1);
- FD->InitializerOrBitWidth.setPointer(Reader.ReadExpr(F));
+ FD->InitStorage.setInt(
+ static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1));
+ if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
+ // Read captured variable length array.
+ FD->InitStorage.setPointer(
+ Reader.readType(F, Record, Idx).getAsOpaquePtr());
+ } else {
+ FD->InitStorage.setPointer(Reader.ReadExpr(F));
+ }
}
if (!FD->getDeclName()) {
if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx))
@@ -1017,7 +1071,8 @@
switch ((VarKind)Record[Idx++]) {
case VarNotTemplate:
// Only true variables (not parameters or implicit parameters) can be merged
- if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam)
+ if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam &&
+ !isa<VarTemplateSpecializationDecl>(VD))
mergeRedeclarable(VD, Redecl);
break;
case VarTemplate:
@@ -1133,29 +1188,31 @@
D->setInline(Record[Idx++]);
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
- // FIXME: At the point of this call, D->getCanonicalDecl() returns 0.
- mergeRedeclarable(D, Redecl);
if (Redecl.getFirstID() == ThisDeclID) {
// Each module has its own anonymous namespace, which is disjoint from
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
- if (F.Kind != MK_Module)
+ if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
D->setAnonymousNamespace(Anon);
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
}
+
+ mergeRedeclarable(D, Redecl);
}
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
D->NamespaceLoc = ReadSourceLocation(Record, Idx);
D->IdentLoc = ReadSourceLocation(Record, Idx);
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx);
+ mergeRedeclarable(D, Redecl);
}
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
@@ -1167,6 +1224,7 @@
D->setTypename(Record[Idx++]);
if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx))
Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
+ mergeMergeable(D);
}
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
@@ -1194,6 +1252,7 @@
D->setUsingLoc(ReadSourceLocation(Record, Idx));
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
+ mergeMergeable(D);
}
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
@@ -1201,6 +1260,7 @@
VisitTypeDecl(D);
D->TypenameLocation = ReadSourceLocation(Record, Idx);
D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ mergeMergeable(D);
}
void ASTDeclReader::ReadCXXDefinitionData(
@@ -1278,6 +1338,7 @@
LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
switch (Kind) {
case LCK_This:
+ case LCK_VLAType:
*ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
break;
case LCK_ByCopy:
@@ -1299,8 +1360,11 @@
// If the new definition has new special members, let the name lookup
// code know that it needs to look in the new definition too.
- if ((MergeDD.DeclaredSpecialMembers & ~DD.DeclaredSpecialMembers) &&
- DD.Definition != MergeDD.Definition) {
+ //
+ // FIXME: We only need to do this if the merged definition declares members
+ // that this definition did not declare, or if it defines members that this
+ // definition did not define.
+ if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) {
Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
DD.Definition->setHasExternalVisibleStorage();
}
@@ -1438,7 +1502,9 @@
};
switch ((CXXRecKind)Record[Idx++]) {
case CXXRecNotTemplate:
- mergeRedeclarable(D, Redecl);
+ // Merged when we merge the folding set entry in the primary template.
+ if (!isa<ClassTemplateSpecializationDecl>(D))
+ mergeRedeclarable(D, Redecl);
break;
case CXXRecTemplate: {
// Merged when we merge the template.
@@ -1490,12 +1556,19 @@
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
+
unsigned NumOverridenMethods = Record[Idx++];
- while (NumOverridenMethods--) {
- // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
- // MD may be initializing.
- if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx))
- Reader.getContext().addOverriddenMethod(D, MD);
+ if (D->isCanonicalDecl()) {
+ while (NumOverridenMethods--) {
+ // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
+ // MD may be initializing.
+ if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx))
+ Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl());
+ }
+ } else {
+ // We don't care about which declarations this used to override; we get
+ // the relevant information from the canonical declaration.
+ Idx += NumOverridenMethods;
}
}
@@ -1755,11 +1828,11 @@
Reader.MergedDeclContexts.insert(
std::make_pair(D, CanonDD->Definition));
D->IsCompleteDefinition = false;
- D->DefinitionData = CanonSpec->DefinitionData;
} else {
CanonSpec->DefinitionData = D->DefinitionData;
}
}
+ D->DefinitionData = CanonSpec->DefinitionData;
}
}
}
@@ -2006,14 +2079,27 @@
/// \brief Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
-void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
+void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
RedeclarableResult &Redecl,
DeclID TemplatePatternID) {
+ T *D = static_cast<T*>(DBase);
+ T *DCanon = D->getCanonicalDecl();
+ if (D != DCanon &&
+ // IDs < NUM_PREDEF_DECL_IDS are not loaded from an AST file.
+ Redecl.getFirstID() >= NUM_PREDEF_DECL_IDS &&
+ (!Reader.getContext().getLangOpts().Modules ||
+ Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) {
+ // All redeclarations between this declaration and its originally-canonical
+ // declaration get pulled in when we load DCanon; we don't need to
+ // perform any more merging now.
+ Redecl.suppress();
+ }
+
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
- if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
+ if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes)
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
}
@@ -2033,16 +2119,37 @@
DeclID DsID) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
- RedeclarableResult Result(Reader, DsID, DPattern->getKind());
- if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern))
- // FIXME: Merge definitions here, if both declarations had definitions.
+ RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
+ DPattern->getKind());
+ if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
+ // Merge with any existing definition.
+ // FIXME: This is duplicated in several places. Refactor.
+ auto *ExistingClass =
+ cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
+ if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
+ if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) {
+ MergeDefinitionData(ExistingClass, *DDD);
+ Reader.PendingDefinitions.erase(DClass);
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(DClass, ExistingDD->Definition));
+ DClass->IsCompleteDefinition = false;
+ } else {
+ ExistingClass->DefinitionData = DClass->DefinitionData;
+ }
+ }
+ DClass->DefinitionData = ExistingClass->DefinitionData;
+
return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
Result);
+ }
if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
Result);
if (auto *DVar = dyn_cast<VarDecl>(DPattern))
return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result);
+ if (auto *DAlias = dyn_cast<TypeAliasDecl>(DPattern))
+ return mergeRedeclarable(DAlias, cast<TypedefNameDecl>(ExistingPattern),
+ Result);
llvm_unreachable("merged an unknown kind of redeclarable template");
}
@@ -2056,8 +2163,10 @@
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
+ assert(DCanon->getGlobalID() == Redecl.getFirstID());
+
// Have our redeclaration link point back at the canonical declaration
- // of the existing declaration, so that this declaration has the
+ // of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
@@ -2072,18 +2181,6 @@
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
TemplatePatternID);
- // Don't introduce DCanon into the set of pending declaration chains.
- Redecl.suppress();
-
- // Introduce ExistingCanon into the set of pending declaration chains,
- // if in fact it came from a module file.
- if (ExistingCanon->isFromASTFile()) {
- GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
- assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
- if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
- Reader.PendingDeclChains.push_back(ExistingCanonID);
- }
-
// If this declaration was the canonical declaration, make a note of
// that. We accept the linear algorithm here because the number of
// unique canonical declarations of an entity should always be tiny.
@@ -2092,14 +2189,6 @@
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
== Merged.end())
Merged.push_back(Redecl.getFirstID());
-
- // If ExistingCanon did not come from a module file, introduce the
- // first declaration that *does* come from a module file to the
- // set of pending declaration chains, so that we merge this
- // declaration.
- if (!ExistingCanon->isFromASTFile() &&
- Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
- Reader.PendingDeclChains.push_back(Merged[0]);
}
}
}
@@ -2185,7 +2274,8 @@
if (isa<FileScopeAsmDecl>(D) ||
isa<ObjCProtocolDecl>(D) ||
isa<ObjCImplDecl>(D) ||
- isa<ImportDecl>(D))
+ isa<ImportDecl>(D) ||
+ isa<OMPThreadPrivateDecl>(D))
return true;
if (VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
@@ -2255,6 +2345,53 @@
TY->getTemplateParameters());
}
+static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
+ if (auto *NS = X->getAsNamespace())
+ return NS;
+ if (auto *NAS = X->getAsNamespaceAlias())
+ return NAS->getNamespace();
+ return nullptr;
+}
+
+static bool isSameQualifier(const NestedNameSpecifier *X,
+ const NestedNameSpecifier *Y) {
+ if (auto *NSX = getNamespace(X)) {
+ auto *NSY = getNamespace(Y);
+ if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl())
+ return false;
+ } else if (X->getKind() != Y->getKind())
+ return false;
+
+ // FIXME: For namespaces and types, we're permitted to check that the entity
+ // is named via the same tokens. We should probably do so.
+ switch (X->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ if (X->getAsIdentifier() != Y->getAsIdentifier())
+ return false;
+ break;
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ // We've already checked that we named the same namespace.
+ break;
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (X->getAsType()->getCanonicalTypeInternal() !=
+ Y->getAsType()->getCanonicalTypeInternal())
+ return false;
+ break;
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ return true;
+ }
+
+ // Recurse into earlier portion of NNS, if any.
+ auto *PX = X->getPrefix();
+ auto *PY = Y->getPrefix();
+ if (PX && PY)
+ return isSameQualifier(PX, PY);
+ return !PX && !PY;
+}
+
/// \brief Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
static bool isSameTemplateParameterList(const TemplateParameterList *X,
@@ -2272,10 +2409,10 @@
/// \brief Determine whether the two declarations refer to the same entity.
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
-
+
if (X == Y)
return true;
-
+
// Must be in the same context.
if (!X->getDeclContext()->getRedeclContext()->Equals(
Y->getDeclContext()->getRedeclContext()))
@@ -2287,11 +2424,11 @@
if (TypedefNameDecl *TypedefY = dyn_cast<TypedefNameDecl>(Y))
return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
TypedefY->getUnderlyingType());
-
+
// Must have the same kind.
if (X->getKind() != Y->getKind())
return false;
-
+
// Objective-C classes and protocols with the same name always match.
if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
return true;
@@ -2313,8 +2450,8 @@
}
// Functions with the same type and linkage match.
- // FIXME: This needs to cope with function template specializations,
- // merging of prototyped/non-prototyped functions, etc.
+ // FIXME: This needs to cope with merging of prototyped/non-prototyped
+ // functions, etc.
if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) {
FunctionDecl *FuncY = cast<FunctionDecl>(Y);
return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) &&
@@ -2347,7 +2484,6 @@
// Fields with the same name and the same type match.
if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) {
FieldDecl *FDY = cast<FieldDecl>(Y);
- // FIXME: Diagnose if the types don't match.
// FIXME: Also check the bitwidth is odr-equivalent, if any.
return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
}
@@ -2363,6 +2499,30 @@
return USX->getTargetDecl() == USY->getTargetDecl();
}
+ // Using declarations with the same qualifier match. (We already know that
+ // the name matches.)
+ if (auto *UX = dyn_cast<UsingDecl>(X)) {
+ auto *UY = cast<UsingDecl>(Y);
+ return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
+ UX->hasTypename() == UY->hasTypename() &&
+ UX->isAccessDeclaration() == UY->isAccessDeclaration();
+ }
+ if (auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
+ auto *UY = cast<UnresolvedUsingValueDecl>(Y);
+ return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
+ UX->isAccessDeclaration() == UY->isAccessDeclaration();
+ }
+ if (auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
+ return isSameQualifier(
+ UX->getQualifier(),
+ cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
+
+ // Namespace alias definitions with the same target match.
+ if (auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
+ auto *NAY = cast<NamespaceAliasDecl>(Y);
+ return NAX->getNamespace()->Equals(NAY->getNamespace());
+ }
+
// FIXME: Many other cases to implement.
return false;
}
@@ -2373,8 +2533,14 @@
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
return ND->getOriginalNamespace();
+ // There is one tricky case here: if DC is a class with no definition, then
+ // we're merging a declaration whose definition is added by an update record,
+ // but we've not yet loaded that update record. In this case, we use the
+ // canonical declaration for merging until we get a real definition.
+ // FIXME: When we add a definition, we may need to move the partial lookup
+ // information from the canonical declaration onto the chosen definition.
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
- return RD->getDefinition();
+ return RD->getPrimaryContext();
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
@@ -2387,9 +2553,17 @@
if (!AddResult || Existing)
return;
+ DeclarationName Name = New->getDeclName();
DeclContext *DC = New->getDeclContext()->getRedeclContext();
- if (DC->isTranslationUnit() && Reader.SemaObj) {
- Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName());
+ if (TypedefNameForLinkage) {
+ Reader.ImportedTypedefNamesForLinkage.insert(
+ std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
+ } else if (!Name) {
+ assert(needsAnonymousDeclarationNumber(New));
+ setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
+ AnonymousDeclNumber, New);
+ } else if (DC->isTranslationUnit() && Reader.SemaObj) {
+ Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name);
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
// Add the declaration to its redeclaration context so later merging
// lookups will find it.
@@ -2397,11 +2571,83 @@
}
}
+/// Find the declaration that should be merged into, given the declaration found
+/// by name lookup. If we're merging an anonymous declaration within a typedef,
+/// we need a matching typedef, and we merge with the type inside it.
+static NamedDecl *getDeclForMerging(NamedDecl *Found,
+ bool IsTypedefNameForLinkage) {
+ if (!IsTypedefNameForLinkage)
+ return Found;
+
+ // If we found a typedef declaration that gives a name to some other
+ // declaration, then we want that inner declaration. Declarations from
+ // AST files are handled via ImportedTypedefNamesForLinkage.
+ if (Found->isFromASTFile()) return 0;
+ if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) {
+ if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>())
+ if (TT->getDecl()->getTypedefNameForAnonDecl() == TND)
+ return TT->getDecl();
+ }
+
+ return 0;
+}
+
+NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
+ DeclContext *DC,
+ unsigned Index) {
+ // If the lexical context has been merged, look into the now-canonical
+ // definition.
+ if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
+ DC = Merged;
+
+ // If we've seen this before, return the canonical declaration.
+ auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
+ if (Index < Previous.size() && Previous[Index])
+ return Previous[Index];
+
+ // If this is the first time, but we have parsed a declaration of the context,
+ // build the anonymous declaration list from the parsed declaration.
+ if (!cast<Decl>(DC)->isFromASTFile()) {
+ unsigned Index = 0;
+ for (Decl *LexicalD : DC->decls()) {
+ auto *ND = dyn_cast<NamedDecl>(LexicalD);
+ if (!ND || !needsAnonymousDeclarationNumber(ND))
+ continue;
+ if (Previous.size() == Index)
+ Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
+ else
+ Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl());
+ ++Index;
+ }
+ }
+
+ return Index < Previous.size() ? Previous[Index] : nullptr;
+}
+
+void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader,
+ DeclContext *DC, unsigned Index,
+ NamedDecl *D) {
+ if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
+ DC = Merged;
+
+ auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
+ if (Index >= Previous.size())
+ Previous.resize(Index + 1);
+ if (!Previous[Index])
+ Previous[Index] = D;
+}
+
ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
- DeclarationName Name = D->getDeclName();
- if (!Name) {
- // Don't bother trying to find unnamed declarations.
- FindExistingResult Result(Reader, D, /*Existing=*/nullptr);
+ DeclarationName Name = TypedefNameForLinkage ? TypedefNameForLinkage
+ : D->getDeclName();
+
+ if (!Name && !needsAnonymousDeclarationNumber(D)) {
+ // Don't bother trying to find unnamed declarations that are in
+ // unmergeable contexts.
+ FindExistingResult Result(Reader, D, /*Existing=*/nullptr,
+ AnonymousDeclNumber, TypedefNameForLinkage);
+ // FIXME: We may still need to pull in the redeclaration chain; there can
+ // be redeclarations via 'decltype'.
Result.suppress();
return Result;
}
@@ -2410,7 +2656,27 @@
// necessary merging already.
DeclContext *DC = D->getDeclContext()->getRedeclContext();
- if (DC->isTranslationUnit() && Reader.SemaObj) {
+ if (TypedefNameForLinkage) {
+ auto It = Reader.ImportedTypedefNamesForLinkage.find(
+ std::make_pair(DC, TypedefNameForLinkage));
+ if (It != Reader.ImportedTypedefNamesForLinkage.end())
+ if (isSameEntity(It->second, D))
+ return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber,
+ TypedefNameForLinkage);
+ // Go on to check in other places in case an existing typedef name
+ // was not imported.
+ }
+
+ if (!Name) {
+ // This is an anonymous declaration that we may need to merge. Look it up
+ // in its context by number.
+ assert(needsAnonymousDeclarationNumber(D));
+ if (auto *Existing = getAnonymousDeclForMerging(
+ Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
+ if (isSameEntity(Existing, D))
+ return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
+ TypedefNameForLinkage);
+ } else if (DC->isTranslationUnit() && Reader.SemaObj) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
// Temporarily consider the identifier to be up-to-date. We don't want to
@@ -2439,14 +2705,18 @@
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I) {
- if (isSameEntity(*I, D))
- return FindExistingResult(Reader, D, *I);
+ if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
+ if (isSameEntity(Existing, D))
+ return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
+ TypedefNameForLinkage);
}
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
- if (isSameEntity(*I, D))
- return FindExistingResult(Reader, D, *I);
+ if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
+ if (isSameEntity(Existing, D))
+ return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
+ TypedefNameForLinkage);
}
} else {
// Not in a mergeable context.
@@ -2458,29 +2728,78 @@
//
// FIXME: We should do something similar if we merge two definitions of the
// same template specialization into the same CXXRecordDecl.
- if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext()))
+ auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
+ if (MergedDCIt != Reader.MergedDeclContexts.end() &&
+ MergedDCIt->second == D->getDeclContext())
Reader.PendingOdrMergeChecks.push_back(D);
- return FindExistingResult(Reader, D, /*Existing=*/nullptr);
+ return FindExistingResult(Reader, D, /*Existing=*/nullptr,
+ AnonymousDeclNumber, TypedefNameForLinkage);
}
template<typename DeclT>
-void ASTDeclReader::attachPreviousDeclImpl(Redeclarable<DeclT> *D,
+void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
+ Redeclarable<DeclT> *D,
Decl *Previous) {
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
}
-void ASTDeclReader::attachPreviousDeclImpl(...) {
+namespace clang {
+template<>
+void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
+ Redeclarable<FunctionDecl> *D,
+ Decl *Previous) {
+ FunctionDecl *FD = static_cast<FunctionDecl*>(D);
+ FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
+
+ FD->RedeclLink.setPrevious(PrevFD);
+
+ // If the previous declaration is an inline function declaration, then this
+ // declaration is too.
+ if (PrevFD->IsInline != FD->IsInline) {
+ // FIXME: [dcl.fct.spec]p4:
+ // If a function with external linkage is declared inline in one
+ // translation unit, it shall be declared inline in all translation
+ // units in which it appears.
+ //
+ // Be careful of this case:
+ //
+ // module A:
+ // template<typename T> struct X { void f(); };
+ // template<typename T> inline void X<T>::f() {}
+ //
+ // module B instantiates the declaration of X<int>::f
+ // module C instantiates the definition of X<int>::f
+ //
+ // If module B and C are merged, we do not have a violation of this rule.
+ FD->IsInline = true;
+ }
+
+ // If this declaration has an unresolved exception specification but the
+ // previous declaration had a resolved one, resolve the exception
+ // specification now.
+ auto *FPT = FD->getType()->getAs<FunctionProtoType>();
+ auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
+ if (FPT && PrevFPT &&
+ isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
+ !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) {
+ Reader.Context.adjustExceptionSpec(
+ FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
+ }
+}
+}
+void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
}
-void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *Previous) {
+void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
+ Decl *Previous) {
assert(D && Previous);
switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
-#define DECL(TYPE, BASE) \
- case Decl::TYPE: \
- attachPreviousDeclImpl(cast<TYPE##Decl>(D), Previous); \
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \
break;
#include "clang/AST/DeclNodes.inc"
}
@@ -2498,32 +2817,6 @@
// be too.
if (Previous->Used)
D->Used = true;
-
- // If the previous declaration is an inline function declaration, then this
- // declaration is too.
- if (auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (cast<FunctionDecl>(Previous)->IsInline != FD->IsInline) {
- // FIXME: [dcl.fct.spec]p4:
- // If a function with external linkage is declared inline in one
- // translation unit, it shall be declared inline in all translation
- // units in which it appears.
- //
- // Be careful of this case:
- //
- // module A:
- // template<typename T> struct X { void f(); };
- // template<typename T> inline void X<T>::f() {}
- //
- // module B instantiates the declaration of X<int>::f
- // module C instantiates the definition of X<int>::f
- //
- // If module B and C are merged, we do not have a violation of this rule.
- //
- //if (!FD->IsInline || Previous->getOwningModule())
- // Diag(FD->getLocation(), diag::err_odr_differing_inline);
- FD->IsInline = true;
- }
- }
}
template<typename DeclT>
@@ -2577,11 +2870,11 @@
// Append the stored merged declarations to the merged declarations set.
MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
if (Pos == MergedDecls.end())
- Pos = MergedDecls.insert(std::make_pair(Canon,
+ Pos = MergedDecls.insert(std::make_pair(Canon,
SmallVector<DeclID, 2>())).first;
Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
StoredMergedDecls.erase(StoredPos);
-
+
// Sort and uniquify the set of merged declarations.
llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
@@ -2911,13 +3204,13 @@
class RedeclChainVisitor {
ASTReader &Reader;
SmallVectorImpl<DeclID> &SearchDecls;
- llvm::SmallPtrSet<Decl *, 16> &Deserialized;
+ llvm::SmallPtrSetImpl<Decl *> &Deserialized;
GlobalDeclID CanonID;
SmallVector<Decl *, 4> Chain;
public:
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
- llvm::SmallPtrSet<Decl *, 16> &Deserialized,
+ llvm::SmallPtrSetImpl<Decl *> &Deserialized,
GlobalDeclID CanonID)
: Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
CanonID(CanonID) {
@@ -2981,6 +3274,8 @@
// Visit each of the declarations.
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
searchForID(M, SearchDecls[I]);
+ // FIXME: If none of the SearchDecls had local IDs in this module, can
+ // we avoid searching any ancestor module files?
return false;
}
@@ -3020,7 +3315,7 @@
if (Chain[I] == CanonDecl)
continue;
- ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent);
+ ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent);
MostRecent = Chain[I];
}
@@ -3034,7 +3329,7 @@
ASTReader &Reader;
serialization::GlobalDeclID InterfaceID;
ObjCInterfaceDecl *Interface;
- llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized;
+ llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
unsigned PreviousGeneration;
ObjCCategoryDecl *Tail;
llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
@@ -3082,7 +3377,7 @@
ObjCCategoriesVisitor(ASTReader &Reader,
serialization::GlobalDeclID InterfaceID,
ObjCInterfaceDecl *Interface,
- llvm::SmallPtrSet<ObjCCategoryDecl *, 16> &Deserialized,
+ llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
unsigned PreviousGeneration)
: Reader(Reader), InterfaceID(InterfaceID), Interface(Interface),
Deserialized(Deserialized), PreviousGeneration(PreviousGeneration),
@@ -3150,13 +3445,80 @@
ModuleMgr.visit(ObjCCategoriesVisitor::visit, &Visitor);
}
+namespace {
+/// Iterator over the redeclarations of a declaration that have already
+/// been merged into the same redeclaration chain.
+template<typename DeclT>
+class MergedRedeclIterator {
+ DeclT *Start, *Canonical, *Current;
+public:
+ MergedRedeclIterator() : Current(nullptr) {}
+ MergedRedeclIterator(DeclT *Start)
+ : Start(Start), Canonical(nullptr), Current(Start) {}
+
+ DeclT *operator*() { return Current; }
+
+ MergedRedeclIterator &operator++() {
+ if (Current->isFirstDecl()) {
+ Canonical = Current;
+ Current = Current->getMostRecentDecl();
+ } else
+ Current = Current->getPreviousDecl();
+
+ // If we started in the merged portion, we'll reach our start position
+ // eventually. Otherwise, we'll never reach it, but the second declaration
+ // we reached was the canonical declaration, so stop when we see that one
+ // again.
+ if (Current == Start || Current == Canonical)
+ Current = nullptr;
+ return *this;
+ }
+
+ friend bool operator!=(const MergedRedeclIterator &A,
+ const MergedRedeclIterator &B) {
+ return A.Current != B.Current;
+ }
+};
+}
+template<typename DeclT>
+llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
+ return llvm::iterator_range<MergedRedeclIterator<DeclT>>(
+ MergedRedeclIterator<DeclT>(D),
+ MergedRedeclIterator<DeclT>());
+}
+
+template<typename DeclT, typename Fn>
+static void forAllLaterRedecls(DeclT *D, Fn F) {
+ F(D);
+
+ // Check whether we've already merged D into its redeclaration chain.
+ // MostRecent may or may not be nullptr if D has not been merged. If
+ // not, walk the merged redecl chain and see if it's there.
+ auto *MostRecent = D->getMostRecentDecl();
+ bool Found = false;
+ for (auto *Redecl = MostRecent; Redecl && !Found;
+ Redecl = Redecl->getPreviousDecl())
+ Found = (Redecl == D);
+
+ // If this declaration is merged, apply the functor to all later decls.
+ if (Found) {
+ for (auto *Redecl = MostRecent; Redecl != D;
+ Redecl = Redecl->getPreviousDecl())
+ F(Redecl);
+ }
+}
+
void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
const RecordData &Record) {
while (Idx < Record.size()) {
switch ((DeclUpdateKind)Record[Idx++]) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+ // FIXME: If we also have an update record for instantiating the
+ // definition of D, we need that to happen before we get here.
Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
assert(MD && "couldn't read decl from update record");
+ // FIXME: We should call addHiddenDecl instead, to add the member
+ // to its DeclContext.
cast<CXXRecordDecl>(D)->addedMember(MD);
break;
}
@@ -3173,7 +3535,8 @@
// Each module has its own anonymous namespace, which is disjoint from
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
- if (ModuleFile.Kind != MK_Module) {
+ if (ModuleFile.Kind != MK_ImplicitModule &&
+ ModuleFile.Kind != MK_ExplicitModule) {
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D))
TU->setAnonymousNamespace(Anon);
else
@@ -3187,7 +3550,7 @@
Reader.ReadSourceLocation(ModuleFile, Record, Idx));
break;
- case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
+ case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
FunctionDecl *FD = cast<FunctionDecl>(D);
if (Reader.PendingBodies[FD]) {
// FIXME: Maybe check for ODR violations.
@@ -3199,17 +3562,18 @@
// Maintain AST consistency: any later redeclarations of this function
// are inline if this one is. (We might have merged another declaration
// into this one.)
- for (auto *D = FD->getMostRecentDecl(); /**/;
- D = D->getPreviousDecl()) {
- D->setImplicitlyInline();
- if (D == FD)
- break;
- }
+ forAllLaterRedecls(FD, [](FunctionDecl *FD) {
+ FD->setImplicitlyInline();
+ });
}
FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
+ // FIXME: Check consistency.
+ DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile,
+ Record, Idx));
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
@@ -3228,6 +3592,7 @@
Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
std::make_pair(LexicalOffset, 0),
ModuleFile.DeclContextInfos[RD]);
+ Reader.PendingDefinitions.insert(RD);
}
auto TSK = (TemplateSpecializationKind)Record[Idx++];
@@ -3249,7 +3614,12 @@
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
auto *TemplArgList = TemplateArgumentList::CreateCopy(
Reader.getContext(), TemplArgs.data(), TemplArgs.size());
- Spec->setInstantiationOf(PartialSpec, TemplArgList);
+
+ // FIXME: If we already have a partial specialization set,
+ // check that it matches.
+ if (!Spec->getSpecializedTemplateOrPartial()
+ .is<ClassTemplatePartialSpecializationDecl *>())
+ Spec->setInstantiationOf(PartialSpec, TemplArgList);
}
}
@@ -3267,20 +3637,35 @@
}
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
- auto *FD = cast<FunctionDecl>(D);
- auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- auto EPI = FPT->getExtProtoInfo();
+ // FIXME: This doesn't send the right notifications if there are
+ // ASTMutationListeners other than an ASTWriter.
+ FunctionProtoType::ExceptionSpecInfo ESI;
SmallVector<QualType, 8> ExceptionStorage;
- Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx);
- FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(),
- FPT->getParamTypes(), EPI));
+ Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
+ for (auto *Redecl : merged_redecls(D)) {
+ auto *FD = cast<FunctionDecl>(Redecl);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
+ // AST invariant: if any exception spec in the redecl chain is
+ // resolved, all are resolved. We don't need to go any further.
+ // FIXME: If the exception spec is resolved, check that it matches.
+ break;
+ }
+ FD->setType(Reader.Context.getFunctionType(
+ FPT->getReturnType(), FPT->getParamTypes(),
+ FPT->getExtProtoInfo().withExceptionSpec(ESI)));
+ }
break;
}
case UPD_CXX_DEDUCED_RETURN_TYPE: {
- FunctionDecl *FD = cast<FunctionDecl>(D);
- Reader.Context.adjustDeducedFunctionResultType(
- FD, Reader.readType(ModuleFile, Record, Idx));
+ // FIXME: Also do this when merging redecls.
+ QualType DeducedResultType = Reader.readType(ModuleFile, Record, Idx);
+ for (auto *Redecl : merged_redecls(D)) {
+ // FIXME: If the return type is already deduced, check that it matches.
+ FunctionDecl *FD = cast<FunctionDecl>(Redecl);
+ Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType);
+ }
break;
}
@@ -3289,12 +3674,7 @@
// ASTMutationListeners other than an ASTWriter.
// Maintain AST consistency: any later redeclarations are used too.
- for (auto *Redecl = D->getMostRecentDecl(); /**/;
- Redecl = Redecl->getPreviousDecl()) {
- Redecl->Used = true;
- if (Redecl == D)
- break;
- }
+ forAllLaterRedecls(D, [](Decl *D) { D->Used = true; });
break;
}
@@ -3305,6 +3685,10 @@
case UPD_STATIC_LOCAL_NUMBER:
Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
break;
+ case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
+ D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
+ Reader.Context, ReadSourceRange(Record, Idx)));
+ break;
}
}
}
diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h
index a63e362..60494b1 100644
--- a/lib/Serialization/ASTReaderInternals.h
+++ b/lib/Serialization/ASTReaderInternals.h
@@ -10,8 +10,8 @@
// This file provides internal definitions used in the AST reader.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H
-#define LLVM_CLANG_SERIALIZATION_ASTREADER_INTERNALS_H
+#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
+#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#include "clang/AST/DeclarationName.h"
#include "clang/Serialization/ASTBitCodes.h"
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index cee2aa2..e0308d7 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -135,8 +135,8 @@
while (NumStmts--)
Stmts.push_back(Reader.ReadSubStmt());
S->setStmts(Reader.getContext(), Stmts.data(), Stmts.size());
- S->setLBracLoc(ReadSourceLocation(Record, Idx));
- S->setRBracLoc(ReadSourceLocation(Record, Idx));
+ S->LBraceLoc = ReadSourceLocation(Record, Idx);
+ S->RBraceLoc = ReadSourceLocation(Record, Idx);
}
void ASTStmtReader::VisitSwitchCase(SwitchCase *S) {
@@ -422,7 +422,8 @@
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
E->setLocation(ReadSourceLocation(Record, Idx));
- E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
+ E->Type = (PredefinedExpr::IdentType)Record[Idx++];
+ E->FnName = cast_or_null<StringLiteral>(Reader.ReadSubExpr());
}
void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -634,7 +635,7 @@
unsigned NumBaseSpecs = Record[Idx++];
assert(NumBaseSpecs == E->path_size());
E->setSubExpr(Reader.ReadSubExpr());
- E->setCastKind((CastExpr::CastKind)Record[Idx++]);
+ E->setCastKind((CastKind)Record[Idx++]);
CastExpr::path_iterator BaseI = E->path_begin();
while (NumBaseSpecs--) {
CXXBaseSpecifier *BaseSpec = new (Reader.getContext()) CXXBaseSpecifier;
@@ -1196,6 +1197,7 @@
E->setElidable(Record[Idx++]);
E->setHadMultipleCandidates(Record[Idx++]);
E->setListInitialization(Record[Idx++]);
+ E->setStdInitListInitialization(Record[Idx++]);
E->setRequiresZeroInitialization(Record[Idx++]);
E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]);
E->ParenOrBraceRange = ReadSourceRange(Record, Idx);
@@ -1578,12 +1580,26 @@
E->setExtendingDecl(VD, ManglingNumber);
}
+void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
+ VisitExpr(E);
+ E->LParenLoc = ReadSourceLocation(Record, Idx);
+ E->EllipsisLoc = ReadSourceLocation(Record, Idx);
+ E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->SubExprs[0] = Reader.ReadSubExpr();
+ E->SubExprs[1] = Reader.ReadSubExpr();
+ E->Opcode = (BinaryOperatorKind)Record[Idx++];
+}
+
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
E->SourceExpr = Reader.ReadSubExpr();
E->Loc = ReadSourceLocation(Record, Idx);
}
+void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
+ llvm_unreachable("Cannot read TypoExpr nodes");
+}
+
//===----------------------------------------------------------------------===//
// Microsoft Expressions and Statements
//===----------------------------------------------------------------------===//
@@ -1681,6 +1697,9 @@
case OMPC_if:
C = new (Context) OMPIfClause();
break;
+ case OMPC_final:
+ C = new (Context) OMPFinalClause();
+ break;
case OMPC_num_threads:
C = new (Context) OMPNumThreadsClause();
break;
@@ -1705,6 +1724,27 @@
case OMPC_nowait:
C = new (Context) OMPNowaitClause();
break;
+ case OMPC_untied:
+ C = new (Context) OMPUntiedClause();
+ break;
+ case OMPC_mergeable:
+ C = new (Context) OMPMergeableClause();
+ break;
+ case OMPC_read:
+ C = new (Context) OMPReadClause();
+ break;
+ case OMPC_write:
+ C = new (Context) OMPWriteClause();
+ break;
+ case OMPC_update:
+ C = new (Context) OMPUpdateClause();
+ break;
+ case OMPC_capture:
+ C = new (Context) OMPCaptureClause();
+ break;
+ case OMPC_seq_cst:
+ C = new (Context) OMPSeqCstClause();
+ break;
case OMPC_private:
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
break;
@@ -1732,6 +1772,9 @@
case OMPC_copyprivate:
C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_flush:
+ C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1745,6 +1788,11 @@
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
+void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
+ C->setCondition(Reader->Reader.ReadSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+}
+
void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
C->setNumThreads(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
@@ -1787,6 +1835,20 @@
void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
+void OMPClauseReader::VisitOMPUntiedClause(OMPUntiedClause *) {}
+
+void OMPClauseReader::VisitOMPMergeableClause(OMPMergeableClause *) {}
+
+void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {}
+
+void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {}
+
+void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {}
+
+void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {}
+
+void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
@@ -1795,6 +1857,10 @@
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivateCopies(Vars);
}
void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
@@ -1805,6 +1871,14 @@
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setInits(Vars);
}
void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
@@ -1889,6 +1963,16 @@
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -1900,7 +1984,38 @@
for (unsigned i = 0; i < E->getNumClauses(); ++i)
Clauses.push_back(ClauseReader.readClause());
E->setClauses(Clauses);
- E->setAssociatedStmt(Reader.ReadSubStmt());
+ if (E->hasAssociatedStmt())
+ E->setAssociatedStmt(Reader.ReadSubStmt());
+}
+
+void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
+ VisitStmt(D);
+ // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
+ Idx += 2;
+ VisitOMPExecutableDirective(D);
+ D->setIterationVariable(Reader.ReadSubExpr());
+ D->setLastIteration(Reader.ReadSubExpr());
+ D->setCalcLastIteration(Reader.ReadSubExpr());
+ D->setPreCond(Reader.ReadSubExpr());
+ auto Fst = Reader.ReadSubExpr();
+ auto Snd = Reader.ReadSubExpr();
+ D->setCond(Fst, Snd);
+ D->setInit(Reader.ReadSubExpr());
+ D->setInc(Reader.ReadSubExpr());
+ SmallVector<Expr *, 4> Sub;
+ unsigned CollapsedNum = D->getCollapsedNumber();
+ Sub.reserve(CollapsedNum);
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Reader.ReadSubExpr());
+ D->setCounters(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Reader.ReadSubExpr());
+ D->setUpdates(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Reader.ReadSubExpr());
+ D->setFinals(Sub);
}
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
@@ -1911,17 +2026,15 @@
}
void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
- VisitStmt(D);
- // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
- Idx += 2;
- VisitOMPExecutableDirective(D);
+ VisitOMPLoopDirective(D);
}
void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) {
- VisitStmt(D);
- // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
- Idx += 2;
- VisitOMPExecutableDirective(D);
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
}
void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
@@ -1943,13 +2056,26 @@
VisitOMPExecutableDirective(D);
}
-void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
+void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
VisitStmt(D);
- // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
- Idx += 2;
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ ReadDeclarationNameInfo(D->DirName, Record, Idx);
+}
+
+void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPParallelForSimdDirective(
+ OMPParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
void ASTStmtReader::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
VisitStmt(D);
@@ -1958,6 +2084,64 @@
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+ D->setX(Reader.ReadSubExpr());
+ D->setV(Reader.ReadSubExpr());
+ D->setExpr(Reader.ReadSubExpr());
+}
+
+void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2456,6 +2640,14 @@
break;
}
+ case STMT_OMP_FOR_SIMD_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPForSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
+ Empty);
+ break;
+ }
+
case STMT_OMP_SECTIONS_DIRECTIVE:
S = OMPSectionsDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
@@ -2470,6 +2662,14 @@
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_MASTER_DIRECTIVE:
+ S = OMPMasterDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_CRITICAL_DIRECTIVE:
+ S = OMPCriticalDirective::CreateEmpty(Context, Empty);
+ break;
+
case STMT_OMP_PARALLEL_FOR_DIRECTIVE: {
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
@@ -2478,11 +2678,60 @@
break;
}
+ case STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPParallelForSimdDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE:
S = OMPParallelSectionsDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_TASK_DIRECTIVE:
+ S = OMPTaskDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_TASKYIELD_DIRECTIVE:
+ S = OMPTaskyieldDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_BARRIER_DIRECTIVE:
+ S = OMPBarrierDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_TASKWAIT_DIRECTIVE:
+ S = OMPTaskwaitDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_FLUSH_DIRECTIVE:
+ S = OMPFlushDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_ORDERED_DIRECTIVE:
+ S = OMPOrderedDirective::CreateEmpty(Context, Empty);
+ break;
+
+ case STMT_OMP_ATOMIC_DIRECTIVE:
+ S = OMPAtomicDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_TARGET_DIRECTIVE:
+ S = OMPTargetDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_TEAMS_DIRECTIVE:
+ S = OMPTeamsDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
@@ -2672,7 +2921,11 @@
case EXPR_MATERIALIZE_TEMPORARY:
S = new (Context) MaterializeTemporaryExpr(Empty);
break;
-
+
+ case EXPR_CXX_FOLD:
+ S = new (Context) CXXFoldExpr(Empty);
+ break;
+
case EXPR_OPAQUE_VALUE:
S = new (Context) OpaqueValueExpr(Empty);
break;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index a02a959..b9be775 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -51,6 +51,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include <algorithm>
#include <cstdio>
#include <string.h>
@@ -83,6 +84,8 @@
public:
/// \brief Type code that corresponds to the record generated.
TypeCode Code;
+ /// \brief Abbreviation to use for the record, if any.
+ unsigned AbbrevToUse;
ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordDataImpl &Record)
: Writer(Writer), Record(Record), Code(TYPE_EXT_QUAL) { }
@@ -190,6 +193,9 @@
// FIXME: need to stabilize encoding of calling convention...
Record.push_back(C.getCC());
Record.push_back(C.getProducesResult());
+
+ if (C.getHasRegParm() || C.getRegParm() || C.getProducesResult())
+ AbbrevToUse = 0;
}
void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
@@ -216,14 +222,21 @@
void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
VisitFunctionType(T);
- Record.push_back(T->getNumParams());
- for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
- Writer.AddTypeRef(T->getParamType(I), Record);
+
Record.push_back(T->isVariadic());
Record.push_back(T->hasTrailingReturn());
Record.push_back(T->getTypeQuals());
Record.push_back(static_cast<unsigned>(T->getRefQualifier()));
addExceptionSpec(Writer, T, Record);
+
+ Record.push_back(T->getNumParams());
+ for (unsigned I = 0, N = T->getNumParams(); I != N; ++I)
+ Writer.AddTypeRef(T->getParamType(I), Record);
+
+ if (T->isVariadic() || T->hasTrailingReturn() || T->getTypeQuals() ||
+ T->getRefQualifier() || T->getExceptionSpecType() != EST_None)
+ AbbrevToUse = 0;
+
Code = TYPE_FUNCTION_PROTO;
}
@@ -649,6 +662,40 @@
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
}
+void ASTWriter::WriteTypeAbbrevs() {
+ using namespace llvm;
+
+ BitCodeAbbrev *Abv;
+
+ // Abbreviation for TYPE_EXT_QUAL
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals
+ TypeExtQualAbbrev = Stream.EmitAbbrev(Abv);
+
+ // Abbreviation for TYPE_FUNCTION_PROTO
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::TYPE_FUNCTION_PROTO));
+ // FunctionType
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ReturnType
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NoReturn
+ Abv->Add(BitCodeAbbrevOp(0)); // HasRegParm
+ Abv->Add(BitCodeAbbrevOp(0)); // RegParm
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // CC
+ Abv->Add(BitCodeAbbrevOp(0)); // ProducesResult
+ // FunctionProtoType
+ Abv->Add(BitCodeAbbrevOp(0)); // IsVariadic
+ Abv->Add(BitCodeAbbrevOp(0)); // HasTrailingReturn
+ Abv->Add(BitCodeAbbrevOp(0)); // TypeQuals
+ Abv->Add(BitCodeAbbrevOp(0)); // RefQualifier
+ Abv->Add(BitCodeAbbrevOp(EST_None)); // ExceptionSpec
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumParams
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Params
+ TypeFunctionProtoAbbrev = Stream.EmitAbbrev(Abv);
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
@@ -684,6 +731,7 @@
#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
RECORD(STMT_STOP);
RECORD(STMT_NULL_PTR);
+ RECORD(STMT_REF_PTR);
RECORD(STMT_NULL);
RECORD(STMT_COMPOUND);
RECORD(STMT_CASE);
@@ -711,6 +759,7 @@
RECORD(EXPR_STRING_LITERAL);
RECORD(EXPR_CHARACTER_LITERAL);
RECORD(EXPR_PAREN);
+ RECORD(EXPR_PAREN_LIST);
RECORD(EXPR_UNARY_OPERATOR);
RECORD(EXPR_SIZEOF_ALIGN_OF);
RECORD(EXPR_ARRAY_SUBSCRIPT);
@@ -752,8 +801,13 @@
RECORD(STMT_OBJC_AT_SYNCHRONIZED);
RECORD(STMT_OBJC_AT_THROW);
RECORD(EXPR_OBJC_BOOL_LITERAL);
+ RECORD(STMT_CXX_CATCH);
+ RECORD(STMT_CXX_TRY);
+ RECORD(STMT_CXX_FOR_RANGE);
RECORD(EXPR_CXX_OPERATOR_CALL);
+ RECORD(EXPR_CXX_MEMBER_CALL);
RECORD(EXPR_CXX_CONSTRUCT);
+ RECORD(EXPR_CXX_TEMPORARY_OBJECT);
RECORD(EXPR_CXX_STATIC_CAST);
RECORD(EXPR_CXX_DYNAMIC_CAST);
RECORD(EXPR_CXX_REINTERPRET_CAST);
@@ -765,11 +819,10 @@
RECORD(EXPR_CXX_NULL_PTR_LITERAL);
RECORD(EXPR_CXX_TYPEID_EXPR);
RECORD(EXPR_CXX_TYPEID_TYPE);
- RECORD(EXPR_CXX_UUIDOF_EXPR);
- RECORD(EXPR_CXX_UUIDOF_TYPE);
RECORD(EXPR_CXX_THIS);
RECORD(EXPR_CXX_THROW);
RECORD(EXPR_CXX_DEFAULT_ARG);
+ RECORD(EXPR_CXX_DEFAULT_INIT);
RECORD(EXPR_CXX_BIND_TEMPORARY);
RECORD(EXPR_CXX_SCALAR_VALUE_INIT);
RECORD(EXPR_CXX_NEW);
@@ -781,12 +834,22 @@
RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);
RECORD(EXPR_CXX_UNRESOLVED_MEMBER);
RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);
+ RECORD(EXPR_CXX_EXPRESSION_TRAIT);
RECORD(EXPR_CXX_NOEXCEPT);
RECORD(EXPR_OPAQUE_VALUE);
+ RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR);
+ RECORD(EXPR_TYPE_TRAIT);
+ RECORD(EXPR_ARRAY_TYPE_TRAIT);
RECORD(EXPR_PACK_EXPANSION);
RECORD(EXPR_SIZEOF_PACK);
+ RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM);
RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
+ RECORD(EXPR_FUNCTION_PARM_PACK);
+ RECORD(EXPR_MATERIALIZE_TEMPORARY);
RECORD(EXPR_CUDA_KERNEL_CALL);
+ RECORD(EXPR_CXX_UUIDOF_EXPR);
+ RECORD(EXPR_CXX_UUIDOF_TYPE);
+ RECORD(EXPR_LAMBDA);
#undef RECORD
}
@@ -800,6 +863,7 @@
// Control Block.
BLOCK(CONTROL_BLOCK);
RECORD(METADATA);
+ RECORD(SIGNATURE);
RECORD(MODULE_NAME);
RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
@@ -895,15 +959,14 @@
RECORD(TYPE_VARIABLE_ARRAY);
RECORD(TYPE_VECTOR);
RECORD(TYPE_EXT_VECTOR);
- RECORD(TYPE_FUNCTION_PROTO);
RECORD(TYPE_FUNCTION_NO_PROTO);
+ RECORD(TYPE_FUNCTION_PROTO);
RECORD(TYPE_TYPEDEF);
RECORD(TYPE_TYPEOF_EXPR);
RECORD(TYPE_TYPEOF);
RECORD(TYPE_RECORD);
RECORD(TYPE_ENUM);
RECORD(TYPE_OBJC_INTERFACE);
- RECORD(TYPE_OBJC_OBJECT);
RECORD(TYPE_OBJC_OBJECT_POINTER);
RECORD(TYPE_DECLTYPE);
RECORD(TYPE_ELABORATED);
@@ -920,8 +983,13 @@
RECORD(TYPE_PACK_EXPANSION);
RECORD(TYPE_ATTRIBUTED);
RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
+ RECORD(TYPE_AUTO);
+ RECORD(TYPE_UNARY_TRANSFORM);
RECORD(TYPE_ATOMIC);
+ RECORD(TYPE_DECAYED);
+ RECORD(TYPE_ADJUSTED);
RECORD(DECL_TYPEDEF);
+ RECORD(DECL_TYPEALIAS);
RECORD(DECL_ENUM);
RECORD(DECL_RECORD);
RECORD(DECL_ENUM_CONSTANT);
@@ -1026,6 +1094,14 @@
return Filename + Pos;
}
+static ASTFileSignature getSignature() {
+ while (1) {
+ if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber())
+ return S;
+ // Rely on GetRandomNumber to eventually return non-zero...
+ }
+}
+
/// \brief Write the control block.
void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
StringRef isysroot,
@@ -1055,6 +1131,11 @@
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
+ // Signature
+ Record.clear();
+ Record.push_back(getSignature());
+ Stream.EmitRecord(SIGNATURE, Record);
+
// Module name
if (WritingModule) {
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
@@ -1068,17 +1149,28 @@
// Module map file
if (WritingModule) {
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(MODULE_MAP_FILE));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Filename
- unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
+ Record.clear();
+ auto addModMap = [&](const FileEntry *F) {
+ SmallString<128> ModuleMap(F->getName());
+ llvm::sys::fs::make_absolute(ModuleMap);
+ AddString(ModuleMap.str(), Record);
+ };
- assert(WritingModule->ModuleMap && "missing module map");
- SmallString<128> ModuleMap(WritingModule->ModuleMap->getName());
- llvm::sys::fs::make_absolute(ModuleMap);
- RecordData Record;
- Record.push_back(MODULE_MAP_FILE);
- Stream.EmitRecordWithBlob(AbbrevCode, Record, ModuleMap.str());
+ auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+
+ // Primary module map file.
+ addModMap(Map.getModuleMapFileForUniquing(WritingModule));
+
+ // Additional module map files.
+ if (auto *AdditionalModMaps = Map.getAdditionalModuleMapFiles(WritingModule)) {
+ Record.push_back(AdditionalModMaps->size());
+ for (const FileEntry *F : *AdditionalModMaps)
+ addModMap(F);
+ } else {
+ Record.push_back(0);
+ }
+
+ Stream.EmitRecord(MODULE_MAP_FILE, Record);
}
// Imports
@@ -1096,6 +1188,7 @@
AddSourceLocation((*M)->ImportLoc, Record);
Record.push_back((*M)->File->getSize());
Record.push_back((*M)->File->getModificationTime());
+ Record.push_back((*M)->Signature);
const std::string &FileName = (*M)->FileName;
Record.push_back(FileName.size());
Record.append(FileName.begin(), FileName.end());
@@ -1110,8 +1203,9 @@
Record.push_back(LangOpts.Name);
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));
-#include "clang/Basic/LangOptions.def"
-#define SANITIZER(NAME, ID) Record.push_back(LangOpts.Sanitize.ID);
+#include "clang/Basic/LangOptions.def"
+#define SANITIZER(NAME, ID) \
+ Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID));
#include "clang/Basic/Sanitizers.def"
Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
@@ -1160,6 +1254,9 @@
Record.push_back(DiagOpts.Warnings.size());
for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I)
AddString(DiagOpts.Warnings[I], Record);
+ Record.push_back(DiagOpts.Remarks.size());
+ for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I)
+ AddString(DiagOpts.Remarks[I], Record);
// Note: we don't serialize the log or serialization file names, because they
// are generally transient files and will almost always be overridden.
Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record);
@@ -1900,6 +1997,10 @@
return true;
if (IsModule) {
+ // Re-export any imported directives.
+ if (MD->isImported())
+ return false;
+
SourceLocation Loc = MD->getLocation();
if (Loc.isInvalid())
return true;
@@ -1977,16 +2078,24 @@
AddSourceLocation(MD->getLocation(), Record);
Record.push_back(MD->getKind());
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
MacroID InfoID = getMacroRef(DefMD->getInfo(), Name);
Record.push_back(InfoID);
- Record.push_back(DefMD->isImported());
+ Record.push_back(DefMD->getOwningModuleID());
Record.push_back(DefMD->isAmbiguous());
-
- } else if (VisibilityMacroDirective *
- VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
+ } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
+ Record.push_back(UndefMD->getOwningModuleID());
+ } else {
+ auto *VisMD = cast<VisibilityMacroDirective>(MD);
Record.push_back(VisMD->isPublic());
}
+
+ if (MD->isImported()) {
+ auto Overrides = MD->getOverriddenModules();
+ Record.push_back(Overrides.size());
+ for (auto Override : Overrides)
+ Record.push_back(Override);
+ }
}
if (Record.empty())
continue;
@@ -2262,7 +2371,7 @@
}
// Enter the submodule description block.
- Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
+ Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);
// Write the abbreviations needed for the submodules block.
using namespace llvm;
@@ -2313,11 +2422,21 @@
unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
@@ -2389,35 +2508,27 @@
Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,
UmbrellaDir->getName());
}
-
+
// Emit the headers.
- for (unsigned I = 0, N = Mod->NormalHeaders.size(); I != N; ++I) {
+ struct {
+ unsigned Kind;
+ unsigned Abbrev;
+ ArrayRef<const FileEntry*> Headers;
+ } HeaderLists[] = {
+ {SUBMODULE_HEADER, HeaderAbbrev, Mod->NormalHeaders},
+ {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Mod->TextualHeaders},
+ {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Mod->PrivateHeaders},
+ {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev,
+ Mod->PrivateTextualHeaders},
+ {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Mod->ExcludedHeaders},
+ {SUBMODULE_TOPHEADER, TopHeaderAbbrev,
+ Mod->getTopHeaders(PP->getFileManager())}
+ };
+ for (auto &HL : HeaderLists) {
Record.clear();
- Record.push_back(SUBMODULE_HEADER);
- Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
- Mod->NormalHeaders[I]->getName());
- }
- // Emit the excluded headers.
- for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_EXCLUDED_HEADER);
- Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
- Mod->ExcludedHeaders[I]->getName());
- }
- // Emit the private headers.
- for (unsigned I = 0, N = Mod->PrivateHeaders.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_PRIVATE_HEADER);
- Stream.EmitRecordWithBlob(PrivateHeaderAbbrev, Record,
- Mod->PrivateHeaders[I]->getName());
- }
- ArrayRef<const FileEntry *>
- TopHeaders = Mod->getTopHeaders(PP->getFileManager());
- for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {
- Record.clear();
- Record.push_back(SUBMODULE_TOPHEADER);
- Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record,
- TopHeaders[I]->getName());
+ Record.push_back(HL.Kind);
+ for (auto *H : HL.Headers)
+ Stream.EmitRecordWithBlob(HL.Abbrev, Record, H->getName());
}
// Emit the imports.
@@ -2602,12 +2713,14 @@
// Emit the type's representation.
ASTTypeWriter W(*this, Record);
+ W.AbbrevToUse = 0;
if (T.hasLocalNonFastQualifiers()) {
Qualifiers Qs = T.getLocalQualifiers();
AddTypeRef(T.getLocalUnqualifiedType(), Record);
Record.push_back(Qs.getAsOpaqueValue());
W.Code = TYPE_EXT_QUAL;
+ W.AbbrevToUse = TypeExtQualAbbrev;
} else {
switch (T->getTypeClass()) {
// For all of the concrete, non-dependent types, call the
@@ -2620,7 +2733,7 @@
}
// Emit the serialized record.
- Stream.EmitRecord(W.Code, Record);
+ Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
// Flush any expressions that were written as part of this type.
FlushStmts();
@@ -2986,101 +3099,77 @@
if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) {
if (!IsModule)
return !shouldIgnoreMacro(Macro, IsModule, PP);
- SubmoduleID ModID;
- if (getFirstPublicSubmoduleMacro(Macro, ModID))
+
+ MacroState State;
+ if (getFirstPublicSubmoduleMacro(Macro, State))
return true;
}
return false;
}
- typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList;
+ enum class SubmoduleMacroState {
+ /// We've seen nothing about this macro.
+ None,
+ /// We've seen a public visibility directive.
+ Public,
+ /// We've either exported a macro for this module or found that the
+ /// module's definition of this macro is private.
+ Done
+ };
+ typedef llvm::DenseMap<SubmoduleID, SubmoduleMacroState> MacroState;
MacroDirective *
- getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) {
- ModID = 0;
- llvm::SmallVector<SubmoduleID, 1> Overridden;
- if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden))
- if (!shouldIgnoreMacro(NextMD, IsModule, PP))
- return NextMD;
+ getFirstPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) {
+ if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, State))
+ return NextMD;
return nullptr;
}
MacroDirective *
- getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID,
- OverriddenList &Overridden) {
+ getNextPublicSubmoduleMacro(MacroDirective *MD, MacroState &State) {
if (MacroDirective *NextMD =
- getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden))
- if (!shouldIgnoreMacro(NextMD, IsModule, PP))
- return NextMD;
+ getPublicSubmoduleMacro(MD->getPrevious(), State))
+ return NextMD;
return nullptr;
}
- /// \brief Traverses the macro directives history and returns the latest
- /// public macro definition or undefinition that is not in ModID.
+ /// \brief Traverses the macro directives history and returns the next
+ /// public macro definition or undefinition that has not been found so far.
+ ///
/// A macro that is defined in submodule A and undefined in submodule B
/// will still be considered as defined/exported from submodule A.
- /// ModID is updated to the module containing the returned directive.
- ///
- /// FIXME: This process breaks down if a module defines a macro, imports
- /// another submodule that changes the macro, then changes the
- /// macro again itself.
MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID,
- OverriddenList &Overridden) {
+ MacroState &State) {
if (!MD)
return nullptr;
- Overridden.clear();
- SubmoduleID OrigModID = ModID;
Optional<bool> IsPublic;
for (; MD; MD = MD->getPrevious()) {
- SubmoduleID ThisModID = getSubmoduleID(MD);
- if (ThisModID == 0) {
- IsPublic = Optional<bool>();
- continue;
- }
- if (ThisModID != ModID) {
- ModID = ThisModID;
- IsPublic = Optional<bool>();
- }
+ // Once we hit an ignored macro, we're done: the rest of the chain
+ // will all be ignored macros.
+ if (shouldIgnoreMacro(MD, IsModule, PP))
+ break;
- // If this is a definition from a submodule import, that submodule's
- // definition is overridden by the definition or undefinition that we
- // started with.
- // FIXME: This should only apply to macros defined in OrigModID.
- // We can't do that currently, because a #include of a different submodule
- // of the same module just leaks through macros instead of providing new
- // DefMacroDirectives for them.
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- // Figure out which submodule the macro was originally defined within.
- SubmoduleID SourceID = DefMD->getInfo()->getOwningModuleID();
- if (!SourceID) {
- SourceLocation DefLoc = DefMD->getInfo()->getDefinitionLoc();
- if (DefLoc == MD->getLocation())
- SourceID = ThisModID;
- else
- SourceID = Writer.inferSubmoduleIDFromLocation(DefLoc);
- }
- if (SourceID != OrigModID)
- Overridden.push_back(SourceID);
- }
+ // If this macro was imported, re-export it.
+ if (MD->isImported())
+ return MD;
- // We are looking for a definition in a different submodule than the one
- // that we started with. If a submodule has re-definitions of the same
- // macro, only the last definition will be used as the "exported" one.
- if (ModID == OrigModID)
+ SubmoduleID ModID = getSubmoduleID(MD);
+ auto &S = State[ModID];
+ assert(ModID && "found macro in no submodule");
+
+ if (S == SubmoduleMacroState::Done)
continue;
- // The latest visibility directive for a name in a submodule affects all
- // the directives that come before it.
- if (VisibilityMacroDirective *VisMD =
- dyn_cast<VisibilityMacroDirective>(MD)) {
- if (!IsPublic.hasValue())
- IsPublic = VisMD->isPublic();
- } else if (!IsPublic.hasValue() || IsPublic.getValue()) {
- // FIXME: If we find an imported macro, we should include its list of
- // overrides in our export.
+ if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
+ // The latest visibility directive for a name in a submodule affects all
+ // the directives that come before it.
+ if (S == SubmoduleMacroState::None)
+ S = VisMD->isPublic() ? SubmoduleMacroState::Public
+ : SubmoduleMacroState::Done;
+ } else {
+ S = SubmoduleMacroState::Done;
return MD;
}
}
@@ -3088,6 +3177,64 @@
return nullptr;
}
+ ArrayRef<SubmoduleID>
+ getOverriddenSubmodules(MacroDirective *MD,
+ SmallVectorImpl<SubmoduleID> &ScratchSpace) {
+ assert(!isa<VisibilityMacroDirective>(MD) &&
+ "only #define and #undef can override");
+ if (MD->isImported())
+ return MD->getOverriddenModules();
+
+ ScratchSpace.clear();
+ SubmoduleID ModID = getSubmoduleID(MD);
+ for (MD = MD->getPrevious(); MD; MD = MD->getPrevious()) {
+ if (shouldIgnoreMacro(MD, IsModule, PP))
+ break;
+
+ // If this is a definition from a submodule import, that submodule's
+ // definition is overridden by the definition or undefinition that we
+ // started with.
+ if (MD->isImported()) {
+ if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ SubmoduleID DefModuleID = DefMD->getInfo()->getOwningModuleID();
+ assert(DefModuleID && "imported macro has no owning module");
+ ScratchSpace.push_back(DefModuleID);
+ } else if (auto *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
+ // If we override a #undef, we override anything that #undef overrides.
+ // We don't need to override it, since an active #undef doesn't affect
+ // the meaning of a macro.
+ auto Overrides = UndefMD->getOverriddenModules();
+ ScratchSpace.insert(ScratchSpace.end(),
+ Overrides.begin(), Overrides.end());
+ }
+ }
+
+ // Stop once we leave the original macro's submodule.
+ //
+ // Either this submodule #included another submodule of the same
+ // module or it just happened to be built after the other module.
+ // In the former case, we override the submodule's macro.
+ //
+ // FIXME: In the latter case, we shouldn't do so, but we can't tell
+ // these cases apart.
+ //
+ // FIXME: We can leave this submodule and re-enter it if it #includes a
+ // header within a different submodule of the same module. In such cases
+ // the overrides list will be incomplete.
+ SubmoduleID DirectiveModuleID = getSubmoduleID(MD);
+ if (DirectiveModuleID != ModID) {
+ if (DirectiveModuleID && !MD->isImported())
+ ScratchSpace.push_back(DirectiveModuleID);
+ break;
+ }
+ }
+
+ std::sort(ScratchSpace.begin(), ScratchSpace.end());
+ ScratchSpace.erase(std::unique(ScratchSpace.begin(), ScratchSpace.end()),
+ ScratchSpace.end());
+ return ScratchSpace;
+ }
+
SubmoduleID getSubmoduleID(MacroDirective *MD) {
return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
}
@@ -3121,27 +3268,23 @@
if (hadMacroDefinition(II, Macro)) {
DataLen += 4; // MacroDirectives offset.
if (IsModule) {
- SubmoduleID ModID;
- llvm::SmallVector<SubmoduleID, 4> Overridden;
- for (MacroDirective *
- MD = getFirstPublicSubmoduleMacro(Macro, ModID);
- MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
- // Previous macro's overrides.
- if (!Overridden.empty())
- DataLen += 4 * (1 + Overridden.size());
+ MacroState State;
+ SmallVector<SubmoduleID, 16> Scratch;
+ for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State);
+ MD; MD = getNextPublicSubmoduleMacro(MD, State)) {
DataLen += 4; // MacroInfo ID or ModuleID.
+ if (unsigned NumOverrides =
+ getOverriddenSubmodules(MD, Scratch).size())
+ DataLen += 4 * (1 + NumOverrides);
}
- // Previous macro's overrides.
- if (!Overridden.empty())
- DataLen += 4 * (1 + Overridden.size());
- DataLen += 4;
+ DataLen += 4; // 0 terminator.
}
}
for (IdentifierResolver::iterator D = IdResolver.begin(II),
DEnd = IdResolver.end();
D != DEnd; ++D)
- DataLen += sizeof(DeclID);
+ DataLen += 4;
}
using namespace llvm::support;
endian::Writer<little> LE(Out);
@@ -3168,8 +3311,10 @@
using namespace llvm::support;
endian::Writer<little> LE(Out);
LE.write<uint32_t>(Overridden.size() | 0x80000000U);
- for (unsigned I = 0, N = Overridden.size(); I != N; ++I)
+ for (unsigned I = 0, N = Overridden.size(); I != N; ++I) {
+ assert(Overridden[I] && "zero module ID for override");
LE.write<uint32_t>(Overridden[I]);
+ }
}
}
@@ -3201,24 +3346,28 @@
LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
if (IsModule) {
// Write the IDs of macros coming from different submodules.
- SubmoduleID ModID;
- llvm::SmallVector<SubmoduleID, 4> Overridden;
- for (MacroDirective *
- MD = getFirstPublicSubmoduleMacro(Macro, ModID);
- MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
- MacroID InfoID = 0;
- emitMacroOverrides(Out, Overridden);
+ MacroState State;
+ SmallVector<SubmoduleID, 16> Scratch;
+ for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, State);
+ MD; MD = getNextPublicSubmoduleMacro(MD, State)) {
if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- InfoID = Writer.getMacroID(DefMD->getInfo());
+ // FIXME: If this macro directive was created by #pragma pop_macros,
+ // or if it was created implicitly by resolving conflicting macros,
+ // it may be for a different submodule from the one in the MacroInfo
+ // object. If so, we should write out its owning ModuleID.
+ MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
assert(InfoID);
LE.write<uint32_t>(InfoID << 1);
} else {
- assert(isa<UndefMacroDirective>(MD));
- LE.write<uint32_t>((ModID << 1) | 1);
+ auto *UndefMD = cast<UndefMacroDirective>(MD);
+ SubmoduleID Mod = UndefMD->isImported()
+ ? UndefMD->getOwningModuleID()
+ : getSubmoduleID(UndefMD);
+ LE.write<uint32_t>((Mod << 1) | 1);
}
+ emitMacroOverrides(Out, getOverriddenSubmodules(MD, Scratch));
}
- emitMacroOverrides(Out, Overridden);
- LE.write<uint32_t>(0);
+ LE.write<uint32_t>(0xdeadbeef);
}
}
@@ -3349,6 +3498,31 @@
// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//
+/// Determine the declaration that should be put into the name lookup table to
+/// represent the given declaration in this module. This is usually D itself,
+/// but if D was imported and merged into a local declaration, we want the most
+/// recent local declaration instead. The chosen declaration will be the most
+/// recent declaration in any module that imports this one.
+static NamedDecl *getDeclForLocalLookup(NamedDecl *D) {
+ if (!D->isFromASTFile())
+ return D;
+
+ if (Decl *Redecl = D->getPreviousDecl()) {
+ // For Redeclarable decls, a prior declaration might be local.
+ for (; Redecl; Redecl = Redecl->getPreviousDecl())
+ if (!Redecl->isFromASTFile())
+ return cast<NamedDecl>(Redecl);
+ } else if (Decl *First = D->getCanonicalDecl()) {
+ // For Mergeable decls, the first decl might be local.
+ if (!First->isFromASTFile())
+ return cast<NamedDecl>(First);
+ }
+
+ // All declarations are imported. Our most recent declaration will also be
+ // the most recent one in anyone who imports us.
+ return D;
+}
+
namespace {
// Trait used for the on-disk hash table used in the method pool.
class ASTDeclContextNameLookupTrait {
@@ -3466,7 +3640,7 @@
LE.write<uint16_t>(Lookup.size());
for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();
I != E; ++I)
- LE.write<uint32_t>(Writer.GetDeclRef(*I));
+ LE.write<uint32_t>(Writer.GetDeclRef(getDeclForLocalLookup(*I)));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
@@ -3506,13 +3680,13 @@
}
void ASTWriter::AddUpdatedDeclContext(const DeclContext *DC) {
- if (UpdatedDeclContexts.insert(DC) && WritingAST) {
+ if (UpdatedDeclContexts.insert(DC).second && WritingAST) {
// Ensure we emit all the visible declarations.
visitLocalLookupResults(DC, DC->NeedToReconcileExternalVisibleStorage,
[&](DeclarationName Name,
DeclContext::lookup_const_result Result) {
for (auto *Decl : Result)
- GetDeclRef(Decl);
+ GetDeclRef(getDeclForLocalLookup(Decl));
});
}
}
@@ -3628,8 +3802,6 @@
Record.push_back(BucketOffset);
Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
LookupTable.str());
-
- Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record);
++NumVisibleDeclContexts;
return Offset;
}
@@ -3711,6 +3883,8 @@
FirstFromAST = Prev;
}
+ // FIXME: Do we need to do this for the first declaration from each
+ // redeclaration chain that was merged into this one?
Chain->MergedDecls[FirstFromAST].push_back(getDeclID(First));
}
@@ -3932,29 +4106,26 @@
}
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
- : Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr),
- WritingModule(nullptr), WritingAST(false), DoneWritingDeclsAndTypes(false),
- ASTHasCompilerErrors(false),
- FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
- FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
- FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),
- FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID),
- FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
- NextSubmoduleID(FirstSubmoduleID),
- FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
- CollectedStmts(&StmtsToEmit),
- NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
- NumVisibleDeclContexts(0),
- NextCXXBaseSpecifiersID(1),
- DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0),
- DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0),
- DeclRefExprAbbrev(0), CharacterLiteralAbbrev(0),
- DeclRecordAbbrev(0), IntegerLiteralAbbrev(0),
- DeclTypedefAbbrev(0),
- DeclVarAbbrev(0), DeclFieldAbbrev(0),
- DeclEnumAbbrev(0), DeclObjCIvarAbbrev(0)
-{
-}
+ : Stream(Stream), Context(nullptr), PP(nullptr), Chain(nullptr),
+ WritingModule(nullptr), WritingAST(false),
+ DoneWritingDeclsAndTypes(false), ASTHasCompilerErrors(false),
+ FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
+ FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
+ FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),
+ FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID),
+ FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS),
+ NextSubmoduleID(FirstSubmoduleID),
+ FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID),
+ CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
+ NumLexicalDeclContexts(0), NumVisibleDeclContexts(0),
+ NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0),
+ TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0),
+ DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0),
+ UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0),
+ DeclVarAbbrev(0), DeclFieldAbbrev(0), DeclEnumAbbrev(0),
+ DeclObjCIvarAbbrev(0), DeclCXXMethodAbbrev(0), DeclRefExprAbbrev(0),
+ CharacterLiteralAbbrev(0), IntegerLiteralAbbrev(0),
+ ExprImplicitCastAbbrev(0) {}
ASTWriter::~ASTWriter() {
llvm::DeleteContainerSeconds(FileDeclIDs);
@@ -4132,6 +4303,11 @@
}
}
+ // Build a record containing all of the UnusedLocalTypedefNameCandidates.
+ RecordData UnusedLocalTypedefNameCandidates;
+ for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)
+ AddDeclRef(TD, UnusedLocalTypedefNameCandidates);
+
// Build a record containing all of dynamic classes declarations.
RecordData DynamicClasses;
AddLazyVectorDecls(*this, SemaRef.DynamicClasses, DynamicClasses);
@@ -4298,22 +4474,36 @@
SmallString<2048> Buffer;
{
llvm::raw_svector_ostream Out(Buffer);
- for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(),
- MEnd = Chain->ModuleMgr.end();
- M != MEnd; ++M) {
+ for (ModuleFile *M : Chain->ModuleMgr) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- StringRef FileName = (*M)->FileName;
+ StringRef FileName = M->FileName;
LE.write<uint16_t>(FileName.size());
Out.write(FileName.data(), FileName.size());
- LE.write<uint32_t>((*M)->SLocEntryBaseOffset);
- LE.write<uint32_t>((*M)->BaseIdentifierID);
- LE.write<uint32_t>((*M)->BaseMacroID);
- LE.write<uint32_t>((*M)->BasePreprocessedEntityID);
- LE.write<uint32_t>((*M)->BaseSubmoduleID);
- LE.write<uint32_t>((*M)->BaseSelectorID);
- LE.write<uint32_t>((*M)->BaseDeclID);
- LE.write<uint32_t>((*M)->BaseTypeIndex);
+
+ // Note: if a base ID was uint max, it would not be possible to load
+ // another module after it or have more than one entity inside it.
+ uint32_t None = std::numeric_limits<uint32_t>::max();
+
+ auto writeBaseIDOrNone = [&](uint32_t BaseID, bool ShouldWrite) {
+ assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high");
+ if (ShouldWrite)
+ LE.write<uint32_t>(BaseID);
+ else
+ LE.write<uint32_t>(None);
+ };
+
+ // These values should be unique within a chain, since they will be read
+ // as keys into ContinuousRangeMaps.
+ writeBaseIDOrNone(M->SLocEntryBaseOffset, M->LocalNumSLocEntries);
+ writeBaseIDOrNone(M->BaseIdentifierID, M->LocalNumIdentifiers);
+ writeBaseIDOrNone(M->BaseMacroID, M->LocalNumMacros);
+ writeBaseIDOrNone(M->BasePreprocessedEntityID,
+ M->NumPreprocessedEntities);
+ writeBaseIDOrNone(M->BaseSubmoduleID, M->LocalNumSubmodules);
+ writeBaseIDOrNone(M->BaseSelectorID, M->LocalNumSelectors);
+ writeBaseIDOrNone(M->BaseDeclID, M->LocalNumDecls);
+ writeBaseIDOrNone(M->BaseTypeIndex, M->LocalNumTypes);
}
}
Record.clear();
@@ -4326,8 +4516,9 @@
// Keep writing types, declarations, and declaration update records
// until we've emitted all of them.
- Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
- WriteDeclsBlockAbbrevs();
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5);
+ WriteTypeAbbrevs();
+ WriteDeclAbbrevs();
for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
E = DeclsToRewrite.end();
I != E; ++I)
@@ -4405,6 +4596,11 @@
if (!DynamicClasses.empty())
Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
+ // Write the record containing potentially unused local typedefs.
+ if (!UnusedLocalTypedefNameCandidates.empty())
+ Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
+ UnusedLocalTypedefNameCandidates);
+
// Write the record containing pending implicit instantiations.
if (!PendingInstantiations.empty())
Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
@@ -4451,10 +4647,13 @@
auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) {
return A.ID < B.ID;
};
+ auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) {
+ return A.ID == B.ID;
+ };
// Sort and deduplicate module IDs.
std::sort(Imports.begin(), Imports.end(), Cmp);
- Imports.erase(std::unique(Imports.begin(), Imports.end(), Cmp),
+ Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq),
Imports.end());
RecordData ImportedModules;
@@ -4514,17 +4713,17 @@
Record.push_back(GetDeclRef(Update.getDecl()));
break;
- case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
- AddSourceLocation(Update.getLoc(), Record);
- break;
-
- case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION:
+ case UPD_CXX_ADDED_FUNCTION_DEFINITION:
// An updated body is emitted last, so that the reader doesn't need
// to skip over the lazy body to reach statements for other records.
Record.pop_back();
HasUpdatedBody = true;
break;
+ case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+ AddSourceLocation(Update.getLoc(), Record);
+ break;
+
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
AddUpdatedDeclContext(RD->getPrimaryContext());
@@ -4564,8 +4763,8 @@
// Instantiation may change attributes; write them all out afresh.
Record.push_back(D->hasAttrs());
if (Record.back())
- WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(),
- D->getAttrs().size()), Record);
+ WriteAttributes(llvm::makeArrayRef(D->getAttrs().begin(),
+ D->getAttrs().size()), Record);
// FIXME: Ensure we don't get here for explicit instantiations.
break;
@@ -4589,15 +4788,21 @@
case UPD_STATIC_LOCAL_NUMBER:
Record.push_back(Update.getNumber());
break;
+ case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
+ AddSourceRange(D->getAttr<OMPThreadPrivateDeclAttr>()->getRange(),
+ Record);
+ break;
}
}
if (HasUpdatedBody) {
const FunctionDecl *Def = cast<FunctionDecl>(D);
- Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION);
+ Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
Record.push_back(Def->isInlined());
AddSourceLocation(Def->getInnerLocStart(), Record);
AddFunctionDefinition(Def, Record);
+ if (auto *DD = dyn_cast<CXXDestructorDecl>(Def))
+ Record.push_back(GetDeclRef(DD->getOperatorDelete()));
}
OffsetsRecord.push_back(GetDeclRef(D));
@@ -4963,6 +5168,30 @@
}
}
+unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {
+ assert(needsAnonymousDeclarationNumber(D) &&
+ "expected an anonymous declaration");
+
+ // Number the anonymous declarations within this context, if we've not
+ // already done so.
+ auto It = AnonymousDeclarationNumbers.find(D);
+ if (It == AnonymousDeclarationNumbers.end()) {
+ unsigned Index = 0;
+ for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) {
+ auto *ND = dyn_cast<NamedDecl>(LexicalD);
+ if (!ND || !needsAnonymousDeclarationNumber(ND))
+ continue;
+ AnonymousDeclarationNumbers[ND] = Index++;
+ }
+
+ It = AnonymousDeclarationNumbers.find(D);
+ assert(It != AnonymousDeclarationNumbers.end() &&
+ "declaration not found within its lexical context");
+ }
+
+ return It->second;
+}
+
void ASTWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
DeclarationName Name, RecordDataImpl &Record) {
switch (Name.getNameKind()) {
@@ -5050,6 +5279,10 @@
case NestedNameSpecifier::Global:
// Don't need to write an associated value.
break;
+
+ case NestedNameSpecifier::Super:
+ AddDeclRef(NNS->getAsRecordDecl(), Record);
+ break;
}
}
}
@@ -5099,6 +5332,11 @@
case NestedNameSpecifier::Global:
AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record);
break;
+
+ case NestedNameSpecifier::Super:
+ AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl(), Record);
+ AddSourceRange(NNS.getLocalSourceRange(), Record);
+ break;
}
}
}
@@ -5168,7 +5406,7 @@
break;
case TemplateArgument::Declaration:
AddDeclRef(Arg.getAsDecl(), Record);
- Record.push_back(Arg.isDeclForReferenceParam());
+ AddTypeRef(Arg.getParamTypeForDecl(), Record);
break;
case TemplateArgument::NullPtr:
AddTypeRef(Arg.getNullPtrType(), Record);
@@ -5192,9 +5430,8 @@
break;
case TemplateArgument::Pack:
Record.push_back(Arg.pack_size());
- for (TemplateArgument::pack_iterator I=Arg.pack_begin(), E=Arg.pack_end();
- I != E; ++I)
- AddTemplateArgument(*I, Record);
+ for (const auto &P : Arg.pack_elements())
+ AddTemplateArgument(P, Record);
break;
}
}
@@ -5401,6 +5638,7 @@
Record.push_back(Capture.getCaptureKind());
switch (Capture.getCaptureKind()) {
case LCK_This:
+ case LCK_VLAType:
break;
case LCK_ByCopy:
case LCK_ByRef:
@@ -5504,8 +5742,6 @@
}
void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
- assert(!WritingAST && "Already writing the AST!");
-
// TU and namespaces are handled elsewhere.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
return;
@@ -5514,12 +5750,12 @@
return; // Not a source decl added to a DeclContext from PCH.
assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
+ assert(!WritingAST && "Already writing the AST!");
AddUpdatedDeclContext(DC);
UpdatingVisibleDecls.push_back(D);
}
void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
- assert(!WritingAST && "Already writing the AST!");
assert(D->isImplicit());
if (!(!D->isFromASTFile() && RD->isFromASTFile()))
return; // Not a source member added to a class from PCH.
@@ -5528,17 +5764,18 @@
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
+ assert(!WritingAST && "Already writing the AST!");
DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {
// The specializations set is kept in the canonical template.
- assert(!WritingAST && "Already writing the AST!");
TD = TD->getCanonicalDecl();
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
+ assert(!WritingAST && "Already writing the AST!");
DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
D));
}
@@ -5546,11 +5783,11 @@
void ASTWriter::AddedCXXTemplateSpecialization(
const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
// The specializations set is kept in the canonical template.
- assert(!WritingAST && "Already writing the AST!");
TD = TD->getCanonicalDecl();
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
+ assert(!WritingAST && "Already writing the AST!");
DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
D));
}
@@ -5558,11 +5795,11 @@
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {
// The specializations set is kept in the canonical template.
- assert(!WritingAST && "Already writing the AST!");
TD = TD->getCanonicalDecl();
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
+ assert(!WritingAST && "Already writing the AST!");
DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
D));
}
@@ -5590,9 +5827,8 @@
if (!D->isFromASTFile())
return; // Declaration not imported from PCH.
- // Implicit decl from a PCH was defined.
- // FIXME: Should implicit definition be a separate FunctionDecl?
- RewriteDecl(D);
+ // Implicit function decl from a PCH was defined.
+ DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
@@ -5600,10 +5836,8 @@
if (!D->isFromASTFile())
return;
- // Since the actual instantiation is delayed, this really means that we need
- // to update the instantiation location.
DeclUpdates[D].push_back(
- DeclUpdate(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION));
+ DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
}
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
@@ -5651,3 +5885,11 @@
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED));
}
+
+void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));
+}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 47ce747..4899968 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -167,8 +167,8 @@
Record.push_back(D->isInvalidDecl());
Record.push_back(D->hasAttrs());
if (D->hasAttrs())
- Writer.WriteAttributes(ArrayRef<const Attr*>(D->getAttrs().begin(),
- D->getAttrs().size()), Record);
+ Writer.WriteAttributes(llvm::makeArrayRef(D->getAttrs().begin(),
+ D->getAttrs().size()), Record);
Record.push_back(D->isImplicit());
Record.push_back(D->isUsed(false));
Record.push_back(D->isReferenced());
@@ -203,6 +203,8 @@
void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
VisitDecl(D);
Writer.AddDeclarationName(D->getDeclName(), Record);
+ if (needsAnonymousDeclarationNumber(D))
+ Record.push_back(Writer.getAnonymousDeclarationNumber(D));
}
void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
@@ -224,13 +226,11 @@
VisitTypedefNameDecl(D);
if (!D->hasAttrs() &&
!D->isImplicit() &&
- !D->isUsed(false) &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
- !D->isReferenced() &&
!D->isTopLevelDeclInObjCContainer() &&
- D->getAccess() == AS_none &&
!D->isModulePrivate() &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier)
AbbrevToUse = Writer.getDeclTypedefAbbrev();
@@ -239,6 +239,7 @@
void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
VisitTypedefNameDecl(D);
+ Writer.AddDeclRef(D->getDescribedAliasTemplate(), Record);
Code = serialization::DECL_TYPEALIAS;
}
@@ -247,18 +248,26 @@
VisitTypeDecl(D);
Record.push_back(D->getIdentifierNamespace());
Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
- Record.push_back(D->isCompleteDefinition());
+ if (!isa<CXXRecordDecl>(D))
+ Record.push_back(D->isCompleteDefinition());
Record.push_back(D->isEmbeddedInDeclarator());
Record.push_back(D->isFreeStanding());
Record.push_back(D->isCompleteDefinitionRequired());
Writer.AddSourceLocation(D->getRBraceLoc(), Record);
- Record.push_back(D->hasExtInfo());
- if (D->hasExtInfo())
+
+ if (D->hasExtInfo()) {
+ Record.push_back(1);
Writer.AddQualifierInfo(*D->getExtInfo(), Record);
- else if (D->hasDeclaratorForAnonDecl())
- Writer.AddDeclRef(D->getDeclaratorForAnonDecl(), Record);
- else
- Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record);
+ } else if (auto *TD = D->getTypedefNameForAnonDecl()) {
+ Record.push_back(2);
+ Writer.AddDeclRef(TD, Record);
+ Writer.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo(), Record);
+ } else if (auto *DD = D->getDeclaratorForAnonDecl()) {
+ Record.push_back(3);
+ Writer.AddDeclRef(DD, Record);
+ } else {
+ Record.push_back(0);
+ }
}
void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
@@ -284,6 +293,8 @@
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
+ !D->getTypedefNameForAnonDecl() &&
+ !D->getDeclaratorForAnonDecl() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
@@ -293,6 +304,7 @@
!CXXRecordDecl::classofKind(D->getKind()) &&
!D->getIntegerTypeSourceInfo() &&
!D->getMemberSpecializationInfo() &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier)
AbbrevToUse = Writer.getDeclEnumAbbrev();
@@ -310,6 +322,8 @@
!D->isImplicit() &&
!D->isUsed(false) &&
!D->hasExtInfo() &&
+ !D->getTypedefNameForAnonDecl() &&
+ !D->getDeclaratorForAnonDecl() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
!D->isInvalidDecl() &&
!D->isReferenced() &&
@@ -317,6 +331,7 @@
D->getAccess() == AS_none &&
!D->isModulePrivate() &&
!CXXRecordDecl::classofKind(D->getKind()) &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier)
AbbrevToUse = Writer.getDeclRecordAbbrev();
@@ -349,7 +364,6 @@
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
VisitRedeclarable(D);
VisitDeclaratorDecl(D);
-
Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record);
Record.push_back(D->getIdentifierNamespace());
@@ -663,12 +677,17 @@
void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
VisitDeclaratorDecl(D);
Record.push_back(D->isMutable());
- if (D->InitializerOrBitWidth.getInt() != ICIS_NoInit ||
- D->InitializerOrBitWidth.getPointer()) {
- Record.push_back(D->InitializerOrBitWidth.getInt() + 1);
- Writer.AddStmt(D->InitializerOrBitWidth.getPointer());
- } else {
+ if (D->InitStorage.getInt() == FieldDecl::ISK_BitWidthOrNothing &&
+ D->InitStorage.getPointer() == nullptr) {
Record.push_back(0);
+ } else if (D->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
+ Record.push_back(D->InitStorage.getInt() + 1);
+ Writer.AddTypeRef(
+ QualType(static_cast<Type *>(D->InitStorage.getPointer()), 0),
+ Record);
+ } else {
+ Record.push_back(D->InitStorage.getInt() + 1);
+ Writer.AddStmt(static_cast<Expr *>(D->InitStorage.getPointer()));
}
if (!D->getDeclName())
Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
@@ -753,6 +772,7 @@
!D->isTopLevelDeclInObjCContainer() &&
D->getAccess() == AS_none &&
!D->isModulePrivate() &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
@@ -930,6 +950,7 @@
}
void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ VisitRedeclarable(D);
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getNamespaceLoc(), Record);
Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
@@ -1027,6 +1048,17 @@
// We only need to record overridden methods once for the canonical decl.
Record.push_back(0);
}
+
+ if (D->getFirstDecl() == D->getMostRecentDecl() &&
+ !D->isInvalidDecl() &&
+ !D->hasAttrs() &&
+ !D->isTopLevelDeclInObjCContainer() &&
+ D->getDeclName().getNameKind() == DeclarationName::Identifier &&
+ !D->hasExtInfo() &&
+ !D->hasInheritedPrototype() &&
+ D->hasWrittenPrototype())
+ AbbrevToUse = Writer.getDeclCXXMethodAbbrev();
+
Code = serialization::DECL_CXX_METHOD;
}
@@ -1449,7 +1481,7 @@
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
-void ASTWriter::WriteDeclsBlockAbbrevs() {
+void ASTWriter::WriteDeclAbbrevs() {
using namespace llvm;
BitCodeAbbrev *Abv;
@@ -1552,8 +1584,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
- Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind
// EnumDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddTypeRef
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IntegerType
@@ -1600,8 +1631,7 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
- Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind
// RecordDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion
@@ -1676,10 +1706,10 @@
Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl
Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
Abv->Add(BitCodeAbbrevOp(0)); // isImplicit
- Abv->Add(BitCodeAbbrevOp(0)); // isUsed
- Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isUsed
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced
Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer
- Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
// NamedDecl
@@ -1738,6 +1768,63 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
DeclVarAbbrev = Stream.EmitAbbrev(Abv);
+ // Abbreviation for DECL_CXX_METHOD
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD));
+ // RedeclarableDecl
+ Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl
+ // Decl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
+ Abv->Add(BitCodeAbbrevOp(0)); // Invalid
+ Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Implicit
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Used
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced
+ Abv->Add(BitCodeAbbrevOp(0)); // InObjCContainer
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
+ // NamedDecl
+ Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Identifier
+ // ValueDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
+ // DeclaratorDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart
+ Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo
+ // FunctionDecl
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // StorageClass
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure
+ Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto
+ Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // DeletedAsWritten
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind
+ // This Array slurps the rest of the record. Fortunately we want to encode
+ // (nearly) all the remaining (variable number of) fields in the same way.
+ //
+ // This is the function template information if any, then
+ // NumParams and Params[] from FunctionDecl, and
+ // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl.
+ //
+ // Add an AbbrevOp for 'size then elements' and use it here.
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
+ DeclCXXMethodAbbrev = Stream.EmitAbbrev(Abv);
+
// Abbreviation for EXPR_DECL_REF
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF));
@@ -1796,6 +1883,24 @@
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getKind
CharacterLiteralAbbrev = Stream.EmitAbbrev(Abv);
+ // Abbreviation for EXPR_IMPLICIT_CAST
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST));
+ // Stmt
+ // Expr
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind
+ // CastExpr
+ Abv->Add(BitCodeAbbrevOp(0)); // PathSize
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind
+ // ImplicitCastExpr
+ ExprImplicitCastAbbrev = Stream.EmitAbbrev(Abv);
+
Abv = new BitCodeAbbrev();
Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 8f0c69e..38996dd 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -307,7 +307,7 @@
// Captures
for (const auto &I : S->captures()) {
- if (I.capturesThis())
+ if (I.capturesThis() || I.capturesVariableArrayType())
Writer.AddDeclRef(nullptr, Record);
else
Writer.AddDeclRef(I.getCapturedVar(), Record);
@@ -333,6 +333,7 @@
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->getIdentType()); // FIXME: stable encoding
+ Writer.AddStmt(E->getFunctionName());
Code = serialization::EXPR_PREDEFINED;
}
@@ -635,6 +636,10 @@
void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
+
+ if (E->path_size() == 0)
+ AbbrevToUse = Writer.getExprImplicitCastAbbrev();
+
Code = serialization::EXPR_IMPLICIT_CAST;
}
@@ -1150,6 +1155,7 @@
Record.push_back(E->isElidable());
Record.push_back(E->hadMultipleCandidates());
Record.push_back(E->isListInitialization());
+ Record.push_back(E->isStdInitListInitialization());
Record.push_back(E->requiresZeroInitialization());
Record.push_back(E->getConstructionKind()); // FIXME: stable encoding
Writer.AddSourceRange(E->getParenOrBraceRange(), Record);
@@ -1573,6 +1579,17 @@
Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
}
+void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) {
+ VisitExpr(E);
+ Writer.AddSourceLocation(E->LParenLoc, Record);
+ Writer.AddSourceLocation(E->EllipsisLoc, Record);
+ Writer.AddSourceLocation(E->RParenLoc, Record);
+ Writer.AddStmt(E->SubExprs[0]);
+ Writer.AddStmt(E->SubExprs[1]);
+ Record.push_back(E->Opcode);
+ Code = serialization::EXPR_CXX_FOLD;
+}
+
void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getSourceExpr());
@@ -1580,6 +1597,12 @@
Code = serialization::EXPR_OPAQUE_VALUE;
}
+void ASTStmtWriter::VisitTypoExpr(TypoExpr *E) {
+ VisitExpr(E);
+ // TODO: Figure out sane writer behavior for a TypoExpr, if necessary
+ assert(false && "Cannot write TypoExpr nodes");
+}
+
//===----------------------------------------------------------------------===//
// CUDA Expressions and Statements.
//===----------------------------------------------------------------------===//
@@ -1686,6 +1709,11 @@
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
+void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {
+ Writer->Writer.AddStmt(C->getCondition());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+}
+
void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
Writer->Writer.AddStmt(C->getNumThreads());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
@@ -1725,18 +1753,43 @@
void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {}
+void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}
+
+void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}
+
+void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}
+
+void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}
+
+void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {}
+
+void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}
+
+void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
+
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *VE : C->varlists())
+ for (auto *VE : C->varlists()) {
Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->private_copies()) {
+ Writer->Writer.AddStmt(VE);
+ }
}
void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
- for (auto *VE : C->varlists())
+ for (auto *VE : C->varlists()) {
Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->private_copies()) {
+ Writer->Writer.AddStmt(VE);
+ }
+ for (auto *VE : C->inits()) {
+ Writer->Writer.AddStmt(VE);
+ }
}
void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
@@ -1795,6 +1848,13 @@
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -1805,7 +1865,32 @@
for (unsigned i = 0; i < E->getNumClauses(); ++i) {
ClauseWriter.writeClause(E->getClause(i));
}
- Writer.AddStmt(E->getAssociatedStmt());
+ if (E->hasAssociatedStmt())
+ Writer.AddStmt(E->getAssociatedStmt());
+}
+
+void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ Record.push_back(D->getCollapsedNumber());
+ VisitOMPExecutableDirective(D);
+ Writer.AddStmt(D->getIterationVariable());
+ Writer.AddStmt(D->getLastIteration());
+ Writer.AddStmt(D->getCalcLastIteration());
+ Writer.AddStmt(D->getPreCond());
+ Writer.AddStmt(D->getCond(/* SeparateIter */ false));
+ Writer.AddStmt(D->getCond(/* SeparateIter */ true));
+ Writer.AddStmt(D->getInit());
+ Writer.AddStmt(D->getInc());
+ for (auto I : D->counters()) {
+ Writer.AddStmt(I);
+ }
+ for (auto I : D->updates()) {
+ Writer.AddStmt(I);
+ }
+ for (auto I : D->finals()) {
+ Writer.AddStmt(I);
+ }
}
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
@@ -1816,21 +1901,20 @@
}
void ASTStmtWriter::VisitOMPSimdDirective(OMPSimdDirective *D) {
- VisitStmt(D);
- Record.push_back(D->getNumClauses());
- Record.push_back(D->getCollapsedNumber());
- VisitOMPExecutableDirective(D);
+ VisitOMPLoopDirective(D);
Code = serialization::STMT_OMP_SIMD_DIRECTIVE;
}
void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) {
- VisitStmt(D);
- Record.push_back(D->getNumClauses());
- Record.push_back(D->getCollapsedNumber());
- VisitOMPExecutableDirective(D);
+ VisitOMPLoopDirective(D);
Code = serialization::STMT_OMP_FOR_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_FOR_SIMD_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
@@ -1851,14 +1935,30 @@
Code = serialization::STMT_OMP_SINGLE_DIRECTIVE;
}
-void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
+void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) {
VisitStmt(D);
- Record.push_back(D->getNumClauses());
- Record.push_back(D->getCollapsedNumber());
VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_MASTER_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Writer.AddDeclarationNameInfo(D->getDirectiveName(), Record);
+ Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPParallelForSimdDirective(
+ OMPParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
VisitStmt(D);
@@ -1867,6 +1967,68 @@
Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TASK_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Writer.AddStmt(D->getX());
+ Writer.AddStmt(D->getV());
+ Writer.AddStmt(D->getExpr());
+ Code = serialization::STMT_OMP_ATOMIC_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTargetDirective(OMPTargetDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TARGET_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_BARRIER_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_FLUSH_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_ORDERED_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TEAMS_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 9858122..4791388 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -122,11 +122,10 @@
}
-GlobalModuleIndex::GlobalModuleIndex(llvm::MemoryBuffer *Buffer,
+GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
llvm::BitstreamCursor Cursor)
- : Buffer(Buffer), IdentifierIndex(),
- NumIdentifierLookups(), NumIdentifierLookupHits()
-{
+ : Buffer(std::move(Buffer)), IdentifierIndex(), NumIdentifierLookups(),
+ NumIdentifierLookupHits() {
// Read the global index.
bool InGlobalIndexBlock = false;
bool Done = false;
@@ -260,7 +259,7 @@
return std::make_pair(nullptr, EC_IOError);
}
- return std::make_pair(new GlobalModuleIndex(Buffer.release(), Cursor),
+ return std::make_pair(new GlobalModuleIndex(std::move(Buffer), Cursor),
EC_None);
}
@@ -494,19 +493,17 @@
bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Open the module file.
- std::unique_ptr<llvm::MemoryBuffer> Buffer;
- std::string ErrorStr;
- Buffer.reset(FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true));
+
+ auto Buffer = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
if (!Buffer) {
return true;
}
// Initialize the input stream
llvm::BitstreamReader InStreamFile;
- llvm::BitstreamCursor InStream;
- InStreamFile.init((const unsigned char *)Buffer->getBufferStart(),
- (const unsigned char *)Buffer->getBufferEnd());
- InStream.init(InStreamFile);
+ InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
+ (const unsigned char *)(*Buffer)->getBufferEnd());
+ llvm::BitstreamCursor InStream(InStreamFile);
// Sniff for the signature.
if (InStream.Read(8) != 'C' ||
@@ -591,6 +588,10 @@
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];
+ // Skip the stored signature.
+ // FIXME: we could read the signature out of the import and validate it.
+ Idx++;
+
// Retrieve the imported file name.
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index 6f2a3c2..6c48a41 100644
--- a/lib/Serialization/Module.cpp
+++ b/lib/Serialization/Module.cpp
@@ -21,7 +21,7 @@
using namespace reader;
ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
- : Kind(Kind), File(nullptr), DirectlyImported(false),
+ : Kind(Kind), File(nullptr), Signature(0), DirectlyImported(false),
Generation(Generation), SizeInBits(0),
LocalNumSLocEntries(0), SLocEntryBaseID(0),
SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr),
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index 2c10c11..b5ee414 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -45,10 +45,11 @@
return Known->second;
}
-llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
+std::unique_ptr<llvm::MemoryBuffer>
+ModuleManager::lookupBuffer(StringRef Name) {
const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
/*cacheFailure=*/false);
- return InMemoryBuffers[Entry];
+ return std::move(InMemoryBuffers[Entry]);
}
ModuleManager::AddModuleResult
@@ -56,6 +57,9 @@
SourceLocation ImportLoc, ModuleFile *ImportedBy,
unsigned Generation,
off_t ExpectedSize, time_t ExpectedModTime,
+ ASTFileSignature ExpectedSignature,
+ std::function<ASTFileSignature(llvm::BitstreamReader &)>
+ ReadSignature,
ModuleFile *&Module,
std::string &ErrorStr) {
Module = nullptr;
@@ -88,7 +92,7 @@
ModuleEntry = New;
New->InputFilesValidationTimestamp = 0;
- if (New->Kind == MK_Module) {
+ if (New->Kind == MK_ImplicitModule) {
std::string TimestampFilename = New->getTimestampFilename();
vfs::Status Status;
// A cached stat value would be fine as well.
@@ -98,39 +102,59 @@
}
// Load the contents of the module
- if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) {
+ if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us.
- assert(Buffer && "Passed null buffer");
- New->Buffer.reset(Buffer);
+ New->Buffer = std::move(Buffer);
} else {
// Open the AST file.
- std::error_code ec;
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf(
+ (std::error_code()));
if (FileName == "-") {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf =
- llvm::MemoryBuffer::getSTDIN();
- ec = Buf.getError();
- if (ec)
- ErrorStr = ec.message();
- else
- New->Buffer = std::move(Buf.get());
+ Buf = llvm::MemoryBuffer::getSTDIN();
} else {
// Leave the FileEntry open so if it gets read again by another
// ModuleManager it must be the same underlying file.
// FIXME: Because FileManager::getFile() doesn't guarantee that it will
// give us an open file, this may not be 100% reliable.
- New->Buffer.reset(FileMgr.getBufferForFile(New->File, &ErrorStr,
- /*IsVolatile*/false,
- /*ShouldClose*/false));
+ Buf = FileMgr.getBufferForFile(New->File,
+ /*IsVolatile=*/false,
+ /*ShouldClose=*/false);
}
-
- if (!New->Buffer)
+
+ if (!Buf) {
+ ErrorStr = Buf.getError().message();
return Missing;
+ }
+
+ New->Buffer = std::move(*Buf);
}
// Initialize the stream
New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(),
(const unsigned char *)New->Buffer->getBufferEnd());
}
+
+ if (ExpectedSignature) {
+ if (NewModule)
+ ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile);
+ else
+ assert(ModuleEntry->Signature == ReadSignature(ModuleEntry->StreamFile));
+
+ if (ModuleEntry->Signature != ExpectedSignature) {
+ ErrorStr = ModuleEntry->Signature ? "signature mismatch"
+ : "could not read module signature";
+
+ if (NewModule) {
+ // Remove the module file immediately, since removeModules might try to
+ // invalidate the file cache for Entry, and that is not safe if this
+ // module is *itself* up to date, but has an out-of-date importer.
+ Modules.erase(Entry);
+ Chain.pop_back();
+ delete ModuleEntry;
+ }
+ return OutOfDate;
+ }
+ }
if (ImportedBy) {
ModuleEntry->ImportedBy.insert(ImportedBy);
@@ -187,12 +211,13 @@
Chain.erase(first, last);
}
-void ModuleManager::addInMemoryBuffer(StringRef FileName,
- llvm::MemoryBuffer *Buffer) {
-
- const FileEntry *Entry = FileMgr.getVirtualFile(FileName,
- Buffer->getBufferSize(), 0);
- InMemoryBuffers[Entry] = Buffer;
+void
+ModuleManager::addInMemoryBuffer(StringRef FileName,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+
+ const FileEntry *Entry =
+ FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
+ InMemoryBuffers[Entry] = std::move(Buffer);
}
ModuleManager::VisitState *ModuleManager::allocateVisitState() {
@@ -249,7 +274,7 @@
void
ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData),
void *UserData,
- llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit) {
+ llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {
// If the visitation order vector is the wrong size, recompute the order.
if (VisitOrder.size() != Chain.size()) {
unsigned N = size();