aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r--lib/Serialization/ASTWriter.cpp386
1 files changed, 265 insertions, 121 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 886523ea9431..bb869077f4cd 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -18,8 +18,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
@@ -33,8 +33,9 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/SourceManager.h"
@@ -64,20 +65,22 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/SHA1.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -348,6 +351,15 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) {
Code = TYPE_AUTO;
}
+void ASTTypeWriter::VisitDeducedTemplateSpecializationType(
+ const DeducedTemplateSpecializationType *T) {
+ Record.AddTemplateName(T->getTemplateName());
+ Record.AddTypeRef(T->getDeducedType());
+ if (T->getDeducedType().isNull())
+ Record.push_back(T->isDependentType());
+ Code = TYPE_DEDUCED_TEMPLATE_SPECIALIZATION;
+}
+
void ASTTypeWriter::VisitTagType(const TagType *T) {
Record.push_back(T->isDependentType());
Record.AddDeclRef(T->getDecl()->getCanonicalDecl());
@@ -414,8 +426,10 @@ ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
void
ASTTypeWriter::VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
- // FIXME: Serialize this type (C++ only)
- llvm_unreachable("Cannot serialize dependent sized extended vector types");
+ Record.AddTypeRef(T->getElementType());
+ Record.AddStmt(T->getSizeExpr());
+ Record.AddSourceLocation(T->getAttributeLoc());
+ Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
}
void
@@ -682,6 +696,11 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(
+ DeducedTemplateSpecializationTypeLoc TL) {
+ Record.AddSourceLocation(TL.getTemplateNameLoc());
+}
+
void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
@@ -1001,7 +1020,6 @@ void ASTWriter::WriteBlockInfoBlock() {
// Control Block.
BLOCK(CONTROL_BLOCK);
RECORD(METADATA);
- RECORD(SIGNATURE);
RECORD(MODULE_NAME);
RECORD(MODULE_DIRECTORY);
RECORD(MODULE_MAP_FILE);
@@ -1014,7 +1032,6 @@ void ASTWriter::WriteBlockInfoBlock() {
BLOCK(OPTIONS_BLOCK);
RECORD(LANGUAGE_OPTIONS);
RECORD(TARGET_OPTIONS);
- RECORD(DIAGNOSTIC_OPTIONS);
RECORD(FILE_SYSTEM_OPTIONS);
RECORD(HEADER_SEARCH_OPTIONS);
RECORD(PREPROCESSOR_OPTIONS);
@@ -1029,6 +1046,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(IDENTIFIER_OFFSET);
RECORD(IDENTIFIER_TABLE);
RECORD(EAGERLY_DESERIALIZED_DECLS);
+ RECORD(MODULAR_CODEGEN_DECLS);
RECORD(SPECIAL_TYPES);
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
@@ -1049,7 +1067,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(UPDATE_VISIBLE);
RECORD(DECL_UPDATE_OFFSETS);
RECORD(DECL_UPDATES);
- RECORD(DIAG_PRAGMA_MAPPINGS);
RECORD(CUDA_SPECIAL_DECL_REFS);
RECORD(HEADER_SEARCH_TABLE);
RECORD(FP_PRAGMA_OPTIONS);
@@ -1242,6 +1259,11 @@ void ASTWriter::WriteBlockInfoBlock() {
BLOCK(EXTENSION_BLOCK);
RECORD(EXTENSION_METADATA);
+ BLOCK(UNHASHED_CONTROL_BLOCK);
+ RECORD(SIGNATURE);
+ RECORD(DIAGNOSTIC_OPTIONS);
+ RECORD(DIAG_PRAGMA_MAPPINGS);
+
#undef RECORD
#undef BLOCK
Stream.ExitBlock();
@@ -1304,21 +1326,73 @@ adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
return Filename + Pos;
}
-static ASTFileSignature getSignature() {
- while (true) {
- if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber())
- return S;
- // Rely on GetRandomNumber to eventually return non-zero...
+ASTFileSignature ASTWriter::createSignature(StringRef Bytes) {
+ // Calculate the hash till start of UNHASHED_CONTROL_BLOCK.
+ llvm::SHA1 Hasher;
+ Hasher.update(ArrayRef<uint8_t>(Bytes.bytes_begin(), Bytes.size()));
+ auto Hash = Hasher.result();
+
+ // Convert to an array [5*i32].
+ ASTFileSignature Signature;
+ auto LShift = [&](unsigned char Val, unsigned Shift) {
+ return (uint32_t)Val << Shift;
+ };
+ for (int I = 0; I != 5; ++I)
+ Signature[I] = LShift(Hash[I * 4 + 0], 24) | LShift(Hash[I * 4 + 1], 16) |
+ LShift(Hash[I * 4 + 2], 8) | LShift(Hash[I * 4 + 3], 0);
+
+ return Signature;
+}
+
+ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,
+ ASTContext &Context) {
+ // Flush first to prepare the PCM hash (signature).
+ Stream.FlushToWord();
+ auto StartOfUnhashedControl = Stream.GetCurrentBitNo() >> 3;
+
+ // Enter the block and prepare to write records.
+ RecordData Record;
+ Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5);
+
+ // For implicit modules, write the hash of the PCM as its signature.
+ ASTFileSignature Signature;
+ if (WritingModule &&
+ PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent) {
+ Signature = createSignature(StringRef(Buffer.begin(), StartOfUnhashedControl));
+ Record.append(Signature.begin(), Signature.end());
+ Stream.EmitRecord(SIGNATURE, Record);
+ Record.clear();
}
+
+ // Diagnostic options.
+ const auto &Diags = Context.getDiagnostics();
+ const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
+#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name);
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+ Record.push_back(static_cast<unsigned>(DiagOpts.get##Name()));
+#include "clang/Basic/DiagnosticOptions.def"
+ 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);
+
+ // Write out the diagnostic/pragma mappings.
+ WritePragmaDiagnosticMappings(Diags, /* IsModule = */ WritingModule);
+
+ // Leave the options block.
+ Stream.ExitBlock();
+ return Signature;
}
/// \brief Write the control block.
-uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
- ASTContext &Context,
- StringRef isysroot,
- const std::string &OutputFile) {
- ASTFileSignature Signature = 0;
-
+void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
+ StringRef isysroot,
+ const std::string &OutputFile) {
using namespace llvm;
Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
RecordData Record;
@@ -1346,15 +1420,6 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
getClangFullRepositoryVersion());
}
if (WritingModule) {
- // For implicit modules we output a signature that we can use to ensure
- // duplicate module builds don't collide in the cache as their output order
- // is non-deterministic.
- // FIXME: Remove this when output is deterministic.
- if (Context.getLangOpts().ImplicitModules) {
- Signature = getSignature();
- RecordData::value_type Record[] = {Signature};
- Stream.EmitRecord(SIGNATURE, Record);
- }
// Module name
auto Abbrev = std::make_shared<BitCodeAbbrev>();
@@ -1420,17 +1485,23 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
serialization::ModuleManager &Mgr = Chain->getModuleManager();
Record.clear();
- for (auto *M : Mgr) {
+ for (ModuleFile &M : Mgr) {
// Skip modules that weren't directly imported.
- if (!M->isDirectlyImported())
+ if (!M.isDirectlyImported())
continue;
- Record.push_back((unsigned)M->Kind); // FIXME: Stable encoding
- AddSourceLocation(M->ImportLoc, Record);
- Record.push_back(M->File->getSize());
- Record.push_back(getTimestampForOutput(M->File));
- Record.push_back(M->Signature);
- AddPath(M->FileName, Record);
+ Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding
+ AddSourceLocation(M.ImportLoc, Record);
+
+ // If we have calculated signature, there is no need to store
+ // the size or timestamp.
+ Record.push_back(M.Signature ? 0 : M.File->getSize());
+ Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File));
+
+ for (auto I : M.Signature)
+ Record.push_back(I);
+
+ AddPath(M.FileName, Record);
}
Stream.EmitRecord(IMPORTS, Record);
}
@@ -1492,24 +1563,6 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
}
Stream.EmitRecord(TARGET_OPTIONS, Record);
- // Diagnostic options.
- Record.clear();
- const DiagnosticOptions &DiagOpts
- = Context.getDiagnostics().getDiagnosticOptions();
-#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name);
-#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
- Record.push_back(static_cast<unsigned>(DiagOpts.get##Name()));
-#include "clang/Basic/DiagnosticOptions.def"
- 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);
-
// File system options.
Record.clear();
const FileSystemOptions &FSOpts =
@@ -1623,7 +1676,6 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
PP.getHeaderSearchInfo().getHeaderSearchOpts(),
PP.getLangOpts().Modules);
Stream.ExitBlock();
- return Signature;
}
namespace {
@@ -1986,6 +2038,30 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
free(const_cast<char *>(SavedStrings[I]));
}
+static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,
+ unsigned SLocBufferBlobCompressedAbbrv,
+ unsigned SLocBufferBlobAbbrv) {
+ typedef ASTWriter::RecordData::value_type RecordDataType;
+
+ // Compress the buffer if possible. We expect that almost all PCM
+ // consumers will not want its contents.
+ SmallString<0> CompressedBuffer;
+ if (llvm::zlib::isAvailable()) {
+ llvm::Error E = llvm::zlib::compress(Blob.drop_back(1), CompressedBuffer);
+ if (!E) {
+ RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED,
+ Blob.size() - 1};
+ Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,
+ CompressedBuffer);
+ return;
+ }
+ llvm::consumeError(std::move(E));
+ }
+
+ RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB};
+ Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);
+}
+
/// \brief Writes the block containing the serialized form of the
/// source manager.
///
@@ -2094,20 +2170,8 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
const llvm::MemoryBuffer *Buffer =
Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1);
-
- // Compress the buffer if possible. We expect that almost all PCM
- // consumers will not want its contents.
- SmallString<0> CompressedBuffer;
- if (llvm::zlib::compress(Blob.drop_back(1), CompressedBuffer) ==
- llvm::zlib::StatusOK) {
- RecordData::value_type Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED,
- Blob.size() - 1};
- Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,
- CompressedBuffer);
- } else {
- RecordData::value_type Record[] = {SM_SLOC_BUFFER_BLOB};
- Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);
- }
+ emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv,
+ SLocBufferBlobAbbrv);
}
} else {
// The source location entry is a macro expansion.
@@ -2516,7 +2580,8 @@ unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
auto *Top = Mod->getTopLevelModule();
if (Top != WritingModule &&
- !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule)))
+ (getLangOpts().CompilingPCH ||
+ !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule))))
return 0;
return SubmoduleIDs[Mod] = NextSubmoduleID++;
@@ -2650,11 +2715,17 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
// Emit the definition of the block.
{
- RecordData::value_type Record[] = {
- SUBMODULE_DEFINITION, ID, ParentID, Mod->IsFramework, Mod->IsExplicit,
- Mod->IsSystem, Mod->IsExternC, Mod->InferSubmodules,
- Mod->InferExplicitSubmodules, Mod->InferExportWildcard,
- Mod->ConfigMacrosExhaustive};
+ RecordData::value_type Record[] = {SUBMODULE_DEFINITION,
+ ID,
+ ParentID,
+ Mod->IsFramework,
+ Mod->IsExplicit,
+ Mod->IsSystem,
+ Mod->IsExternC,
+ Mod->InferSubmodules,
+ Mod->InferExplicitSubmodules,
+ Mod->InferExportWildcard,
+ Mod->ConfigMacrosExhaustive};
Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
}
@@ -2789,43 +2860,68 @@ ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) {
void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
bool isModule) {
- // Make sure set diagnostic pragmas don't affect the translation unit that
- // imports the module.
- // FIXME: Make diagnostic pragma sections work properly with modules.
- if (isModule)
- return;
-
llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64>
DiagStateIDMap;
unsigned CurrID = 0;
- DiagStateIDMap[&Diag.DiagStates.front()] = ++CurrID; // the command-line one.
RecordData Record;
- for (DiagnosticsEngine::DiagStatePointsTy::const_iterator
- I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end();
- I != E; ++I) {
- const DiagnosticsEngine::DiagStatePoint &point = *I;
- if (point.Loc.isInvalid())
- continue;
- AddSourceLocation(point.Loc, Record);
- unsigned &DiagStateID = DiagStateIDMap[point.State];
+ auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State,
+ bool IncludeNonPragmaStates) {
+ unsigned &DiagStateID = DiagStateIDMap[State];
Record.push_back(DiagStateID);
-
+
if (DiagStateID == 0) {
DiagStateID = ++CurrID;
- for (const auto &I : *(point.State)) {
- if (I.second.isPragma()) {
+
+ // Add a placeholder for the number of mappings.
+ auto SizeIdx = Record.size();
+ Record.emplace_back();
+ for (const auto &I : *State) {
+ if (I.second.isPragma() || IncludeNonPragmaStates) {
Record.push_back(I.first);
- Record.push_back((unsigned)I.second.getSeverity());
+ Record.push_back(I.second.serializeBits());
}
}
- Record.push_back(-1); // mark the end of the diag/map pairs for this
- // location.
+ // Update the placeholder.
+ Record[SizeIdx] = (Record.size() - SizeIdx) / 2;
+ }
+ };
+
+ AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule);
+
+ // Reserve a spot for the number of locations with state transitions.
+ auto NumLocationsIdx = Record.size();
+ Record.emplace_back();
+
+ // Emit the state transitions.
+ unsigned NumLocations = 0;
+ for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) {
+ if (!FileIDAndFile.first.isValid() ||
+ !FileIDAndFile.second.HasLocalTransitions)
+ continue;
+ ++NumLocations;
+ AddSourceLocation(Diag.SourceMgr->getLocForStartOfFile(FileIDAndFile.first),
+ Record);
+ Record.push_back(FileIDAndFile.second.StateTransitions.size());
+ for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {
+ Record.push_back(StatePoint.Offset);
+ AddDiagState(StatePoint.State, false);
}
}
- if (!Record.empty())
- Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
+ // Backpatch the number of locations.
+ Record[NumLocationsIdx] = NumLocations;
+
+ // Emit CurDiagStateLoc. Do it last in order to match source order.
+ //
+ // This also protects against a hypothetical corner case with simulating
+ // -Werror settings for implicit modules in the ASTReader, where reading
+ // CurDiagState out of context could change whether warning pragmas are
+ // treated as errors.
+ AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record);
+ AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false);
+
+ Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
}
//===----------------------------------------------------------------------===//
@@ -3559,6 +3655,7 @@ public:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXDeductionGuideName:
KeyLen += 4;
break;
case DeclarationName::CXXOperatorName:
@@ -3588,6 +3685,7 @@ public:
switch (Name.getKind()) {
case DeclarationName::Identifier:
case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXDeductionGuideName:
LE.write<uint32_t>(Writer.getIdentifierRef(Name.getIdentifier()));
return;
case DeclarationName::ObjCZeroArgSelector:
@@ -3931,7 +4029,7 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
/// \brief Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
void ASTWriter::WriteFPPragmaOptions(const FPOptions &Opts) {
- RecordData::value_type Record[] = {Opts.fp_contract};
+ RecordData::value_type Record[] = {Opts.getInt()};
Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}
@@ -4086,6 +4184,25 @@ void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {
Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record);
}
+/// \brief Write the state of 'pragma pack' at the end of the module.
+void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {
+ // Don't serialize pragma pack state for modules, since it should only take
+ // effect on a per-submodule basis.
+ if (WritingModule)
+ return;
+
+ RecordData Record;
+ Record.push_back(SemaRef.PackStack.CurrentValue);
+ AddSourceLocation(SemaRef.PackStack.CurrentPragmaLocation, Record);
+ Record.push_back(SemaRef.PackStack.Stack.size());
+ for (const auto &StackEntry : SemaRef.PackStack.Stack) {
+ Record.push_back(StackEntry.Value);
+ AddSourceLocation(StackEntry.PragmaLocation, Record);
+ AddString(StackEntry.StackSlotLabel, Record);
+ }
+ Stream.EmitRecord(PACK_PRAGMA_OPTIONS, Record);
+}
+
void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
ModuleFileExtensionWriter &Writer) {
// Enter the extension block.
@@ -4223,9 +4340,11 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
}
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
+ SmallVectorImpl<char> &Buffer, MemoryBufferCache &PCMCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps)
- : Stream(Stream), IncludeTimestamps(IncludeTimestamps) {
+ : Stream(Stream), Buffer(Buffer), PCMCache(PCMCache),
+ IncludeTimestamps(IncludeTimestamps) {
for (const auto &Ext : Extensions) {
if (auto Writer = Ext->createExtensionWriter(*this))
ModuleFileExtensionWriters.push_back(std::move(Writer));
@@ -4245,9 +4364,10 @@ time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const {
return IncludeTimestamps ? E->getModificationTime() : 0;
}
-uint64_t ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile,
- Module *WritingModule, StringRef isysroot,
- bool hasErrors) {
+ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef,
+ const std::string &OutputFile,
+ Module *WritingModule, StringRef isysroot,
+ bool hasErrors) {
WritingAST = true;
ASTHasCompilerErrors = hasErrors;
@@ -4271,6 +4391,12 @@ uint64_t ASTWriter::WriteAST(Sema &SemaRef, const std::string &OutputFile,
this->BaseDirectory.clear();
WritingAST = false;
+ if (SemaRef.Context.getLangOpts().ImplicitModules && WritingModule) {
+ // Construct MemoryBuffer and update buffer manager.
+ PCMCache.addBuffer(OutputFile,
+ llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(Buffer.begin(), Buffer.size())));
+ }
return Signature;
}
@@ -4283,9 +4409,9 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec,
}
}
-uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
- const std::string &OutputFile,
- Module *WritingModule) {
+ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
+ const std::string &OutputFile,
+ Module *WritingModule) {
using namespace llvm;
bool isModule = WritingModule != nullptr;
@@ -4433,7 +4559,7 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
}
// Write the control block
- uint64_t Signature = WriteControlBlock(PP, Context, isysroot, OutputFile);
+ WriteControlBlock(PP, Context, isysroot, OutputFile);
// Write the remaining AST contents.
Stream.EnterSubblock(AST_BLOCK_ID, 5);
@@ -4573,10 +4699,10 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
SmallString<2048> Buffer;
{
llvm::raw_svector_ostream Out(Buffer);
- for (ModuleFile *M : Chain->ModuleMgr) {
+ 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());
@@ -4594,15 +4720,15 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// 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);
+ 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);
}
}
RecordData::value_type Record[] = {MODULE_OFFSET_MAP};
@@ -4650,7 +4776,6 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteOpenCLExtensionTypes(SemaRef);
WriteOpenCLExtensionDecls(SemaRef);
WriteCUDAPragmas(SemaRef);
- WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
// If we're emitting a module, write out the submodule information.
if (WritingModule)
@@ -4662,6 +4787,9 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
if (!EagerlyDeserializedDecls.empty())
Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);
+ if (!ModularCodegenDecls.empty())
+ Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls);
+
// Write the record containing tentative definitions.
if (!TentativeDefinitions.empty())
Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);
@@ -4765,6 +4893,7 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteMSStructPragmaOptions(SemaRef);
WriteMSPointersToMembersPragmaOptions(SemaRef);
}
+ WritePackPragmaOptions(SemaRef);
// Some simple statistics
RecordData::value_type Record[] = {
@@ -4776,7 +4905,7 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
for (const auto &ExtWriter : ModuleFileExtensionWriters)
WriteModuleFileExtension(SemaRef, *ExtWriter);
- return Signature;
+ return writeUnhashedControlBlock(PP, Context);
}
void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
@@ -5229,6 +5358,10 @@ void ASTRecordWriter::AddDeclarationName(DeclarationName Name) {
AddTypeRef(Name.getCXXNameType());
break;
+ case DeclarationName::CXXDeductionGuideName:
+ AddDeclRef(Name.getCXXDeductionGuideTemplate());
+ break;
+
case DeclarationName::CXXOperatorName:
Record->push_back(Name.getCXXOverloadedOperator());
break;
@@ -5290,6 +5423,7 @@ void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
case DeclarationName::CXXUsingDirective:
+ case DeclarationName::CXXDeductionGuideName:
break;
}
}
@@ -5651,10 +5785,20 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Data.ComputedVisibleConversions);
Record->push_back(Data.UserProvidedDefaultConstructor);
Record->push_back(Data.DeclaredSpecialMembers);
- Record->push_back(Data.ImplicitCopyConstructorHasConstParam);
+ Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForVBase);
+ Record->push_back(Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase);
Record->push_back(Data.ImplicitCopyAssignmentHasConstParam);
Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam);
Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam);
+
+ // getODRHash will compute the ODRHash if it has not been previously computed.
+ Record->push_back(D->getODRHash());
+ bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo &&
+ Writer->WritingModule && !D->isDependentType();
+ Record->push_back(ModulesDebugInfo);
+ if (ModulesDebugInfo)
+ Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D));
+
// IsLambda bit is already saved.
Record->push_back(Data.NumBases);