Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 405488c..e4b5cdb 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclLookups.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
@@ -45,6 +46,7 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -113,6 +115,12 @@
Code = TYPE_DECAYED;
}
+void ASTTypeWriter::VisitAdjustedType(const AdjustedType *T) {
+ Writer.AddTypeRef(T->getOriginalType(), Record);
+ Writer.AddTypeRef(T->getAdjustedType(), Record);
+ Code = TYPE_ADJUSTED;
+}
+
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Code = TYPE_BLOCK_POINTER;
@@ -173,7 +181,7 @@
}
void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
- Writer.AddTypeRef(T->getResultType(), Record);
+ Writer.AddTypeRef(T->getReturnType(), Record);
FunctionType::ExtInfo C = T->getExtInfo();
Record.push_back(C.getNoReturn());
Record.push_back(C.getHasRegParm());
@@ -188,15 +196,8 @@
Code = TYPE_FUNCTION_NO_PROTO;
}
-void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
- VisitFunctionType(T);
- Record.push_back(T->getNumArgs());
- for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
- Writer.AddTypeRef(T->getArgType(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()));
+static void addExceptionSpec(ASTWriter &Writer, const FunctionProtoType *T,
+ ASTWriter::RecordDataImpl &Record) {
Record.push_back(T->getExceptionSpecType());
if (T->getExceptionSpecType() == EST_Dynamic) {
Record.push_back(T->getNumExceptions());
@@ -210,6 +211,18 @@
} else if (T->getExceptionSpecType() == EST_Unevaluated) {
Writer.AddDeclRef(T->getExceptionSpecDecl(), Record);
}
+}
+
+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);
Code = TYPE_FUNCTION_PROTO;
}
@@ -395,9 +408,8 @@
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
Record.push_back(T->getNumProtocols());
- for (ObjCObjectType::qual_iterator I = T->qual_begin(),
- E = T->qual_end(); I != E; ++I)
- Writer.AddDeclRef(*I, Record);
+ for (const auto *I : T->quals())
+ Writer.AddDeclRef(I, Record);
Code = TYPE_OBJC_OBJECT;
}
@@ -455,6 +467,9 @@
void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
}
@@ -503,8 +518,8 @@
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
Writer.AddSourceLocation(TL.getLocalRangeEnd(), Record);
- for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- Writer.AddDeclRef(TL.getArg(i), Record);
+ for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)
+ Writer.AddDeclRef(TL.getParam(i), Record);
}
void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
@@ -764,10 +779,8 @@
RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);
RECORD(EXPR_CXX_UNRESOLVED_MEMBER);
RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);
- RECORD(EXPR_CXX_UNARY_TYPE_TRAIT);
RECORD(EXPR_CXX_NOEXCEPT);
RECORD(EXPR_OPAQUE_VALUE);
- RECORD(EXPR_BINARY_TYPE_TRAIT);
RECORD(EXPR_PACK_EXPANSION);
RECORD(EXPR_SIZEOF_PACK);
RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
@@ -806,7 +819,7 @@
RECORD(DECL_OFFSET);
RECORD(IDENTIFIER_OFFSET);
RECORD(IDENTIFIER_TABLE);
- RECORD(EXTERNAL_DEFINITIONS);
+ RECORD(EAGERLY_DESERIALIZED_DECLS);
RECORD(SPECIAL_TYPES);
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
@@ -1040,7 +1053,6 @@
// Imports
if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager();
- SmallVector<char, 128> ModulePaths;
Record.clear();
for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();
@@ -1097,7 +1109,6 @@
AddString(TargetOpts.Triple, Record);
AddString(TargetOpts.CPU, Record);
AddString(TargetOpts.ABI, Record);
- AddString(TargetOpts.CXXABI, Record);
AddString(TargetOpts.LinkerVersion, Record);
Record.push_back(TargetOpts.FeaturesAsWritten.size());
for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
@@ -1156,6 +1167,7 @@
AddString(HSOpts.ResourceDir, Record);
AddString(HSOpts.ModuleCachePath, Record);
+ AddString(HSOpts.ModuleUserBuildPath, Record);
Record.push_back(HSOpts.DisableModuleHash);
Record.push_back(HSOpts.UseBuiltinIncludes);
Record.push_back(HSOpts.UseStandardSystemIncludes);
@@ -1294,33 +1306,6 @@
SortedFiles.push_front(Entry);
}
- // If we have an isysroot for a Darwin SDK, include its SDKSettings.plist in
- // the set of (non-system) input files. This is simple heuristic for
- // detecting whether the system headers may have changed, because it is too
- // expensive to stat() all of the system headers.
- FileManager &FileMgr = SourceMgr.getFileManager();
- if (!HSOpts.Sysroot.empty() && !Chain) {
- llvm::SmallString<128> SDKSettingsFileName(HSOpts.Sysroot);
- llvm::sys::path::append(SDKSettingsFileName, "SDKSettings.plist");
- if (const FileEntry *SDKSettingsFile = FileMgr.getFile(SDKSettingsFileName)) {
- InputFileEntry Entry = { SDKSettingsFile, false, false };
- SortedFiles.push_front(Entry);
- }
- }
-
- // Add the compiler's own module.map in the set of (non-system) input files.
- // This is a simple heuristic for detecting whether the compiler's headers
- // have changed, because we don't want to stat() all of them.
- if (Modules && !Chain) {
- SmallString<128> P = StringRef(HSOpts.ResourceDir);
- llvm::sys::path::append(P, "include");
- llvm::sys::path::append(P, "module.map");
- if (const FileEntry *ModuleMapFile = FileMgr.getFile(P)) {
- InputFileEntry Entry = { ModuleMapFile, false, false };
- SortedFiles.push_front(Entry);
- }
- }
-
unsigned UserFilesNum = 0;
// Write out all of the input files.
std::vector<uint32_t> InputFileOffsets;
@@ -1357,7 +1342,7 @@
// Ask the file manager to fixup the relative path for us. This will
// honor the working directory.
- FileMgr.FixupRelativePath(FilePath);
+ SourceMgr.getFileManager().FixupRelativePath(FilePath);
// FIXME: This call to make_absolute shouldn't be necessary, the
// call to FixupRelativePath should always return an absolute path.
@@ -1481,26 +1466,31 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
+ using namespace llvm::support;
+ endian::Writer<little> Writer(Out);
unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
- clang::io::Emit16(Out, KeyLen);
+ Writer.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
if (Data.isModuleHeader)
DataLen += 4;
- clang::io::Emit8(Out, DataLen);
+ Writer.write<uint8_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
- clang::io::Emit64(Out, key.FE->getSize());
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint64_t>(key.FE->getSize());
KeyLen -= 8;
- clang::io::Emit64(Out, key.FE->getModificationTime());
+ LE.write<uint64_t>(key.FE->getModificationTime());
KeyLen -= 8;
Out.write(key.Filename, KeyLen);
}
void EmitData(raw_ostream &Out, key_type_ref key,
data_type_ref Data, unsigned DataLen) {
- using namespace clang::io;
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
unsigned char Flags = (Data.HeaderRole << 6)
@@ -1509,13 +1499,13 @@
| (Data.DirInfo << 2)
| (Data.Resolved << 1)
| Data.IndexHeaderMapHeader;
- Emit8(Out, (uint8_t)Flags);
- Emit16(Out, (uint16_t) Data.NumIncludes);
+ LE.write<uint8_t>(Flags);
+ LE.write<uint16_t>(Data.NumIncludes);
if (!Data.ControllingMacro)
- Emit32(Out, (uint32_t)Data.ControllingMacroID);
+ LE.write<uint32_t>(Data.ControllingMacroID);
else
- Emit32(Out, (uint32_t)Writer.getIdentifierRef(Data.ControllingMacro));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Data.ControllingMacro));
unsigned Offset = 0;
if (!Data.Framework.empty()) {
@@ -1532,11 +1522,11 @@
} else
Offset = Pos->second;
}
- Emit32(Out, Offset);
+ LE.write<uint32_t>(Offset);
if (Data.isModuleHeader) {
Module *Mod = HS.findModuleForHeader(key.FE).getModule();
- Emit32(Out, Writer.getExistingSubmoduleID(Mod));
+ LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod));
}
assert(Out.tell() - Start == DataLen && "Wrong data length");
@@ -1568,10 +1558,10 @@
// Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
// from the external source if it was not provided already.
- const HeaderFileInfo &HFI = HS.getFileInfo(File);
- if (HFI.External && Chain)
- continue;
- if (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)
+ HeaderFileInfo HFI;
+ if (!HS.tryGetFileInfo(File, HFI) ||
+ (HFI.External && Chain) ||
+ (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
continue;
// Turn the file name into an absolute path, if it isn't already.
@@ -1594,9 +1584,10 @@
SmallString<4096> TableData;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
llvm::raw_svector_ostream Out(TableData);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, GeneratorTrait);
}
@@ -1851,12 +1842,14 @@
}
static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
- clang::io::Emit32(Out, Key);
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(Key);
}
static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data,
unsigned) {
- clang::io::Emit32(Out, Data.MacroDirectivesOffset);
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(Data.MacroDirectivesOffset);
}
};
} // end anonymous namespace
@@ -1946,8 +1939,6 @@
// Emit the macro directives in reverse source order.
for (; MD; MD = MD->getPrevious()) {
- if (MD->isHidden())
- continue;
if (shouldIgnoreMacro(MD, IsModule, PP))
continue;
@@ -2054,9 +2045,10 @@
SmallString<4096> MacroTable;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
llvm::raw_svector_ostream Out(MacroTable);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out);
}
@@ -2227,9 +2219,7 @@
// other consumers of this information.
SourceManager &SrcMgr = PP->getSourceManager();
ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
- for (ASTContext::import_iterator I = Context->local_import_begin(),
- IEnd = Context->local_import_end();
- I != IEnd; ++I) {
+ for (const auto *I : Context->local_imports()) {
if (Module *ImportedFrom
= ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),
SrcMgr))) {
@@ -2248,7 +2238,8 @@
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
@@ -2336,6 +2327,7 @@
Record.push_back(Mod->IsFramework);
Record.push_back(Mod->IsExplicit);
Record.push_back(Mod->IsSystem);
+ Record.push_back(Mod->IsExternC);
Record.push_back(Mod->InferSubmodules);
Record.push_back(Mod->InferExplicitSubmodules);
Record.push_back(Mod->InferExportWildcard);
@@ -2618,9 +2610,8 @@
RecordData Record;
Record.push_back(DECL_CONTEXT_LEXICAL);
SmallVector<KindDeclIDPair, 64> Decls;
- for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
- D != DEnd; ++D)
- Decls.push_back(std::make_pair((*D)->getKind(), GetDeclRef(*D)));
+ for (const auto *D : DC->decls())
+ Decls.push_back(std::make_pair(D->getKind(), GetDeclRef(D)));
++NumLexicalDeclContexts;
Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, data(Decls));
@@ -2728,8 +2719,10 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, Selector Sel,
data_type_ref Methods) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
@@ -2739,27 +2732,31 @@
Method = Method->getNext())
if (Method->Method)
DataLen += 4;
- clang::io::Emit16(Out, DataLen);
+ LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell();
assert((Start >> 32) == 0 && "Selector key offset too large");
Writer.SetSelectorOffset(Sel, Start);
unsigned N = Sel.getNumArgs();
- clang::io::Emit16(Out, N);
+ LE.write<uint16_t>(N);
if (N == 0)
N = 1;
for (unsigned I = 0; I != N; ++I)
- clang::io::Emit32(Out,
- Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
+ LE.write<uint32_t>(
+ Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
}
void EmitData(raw_ostream& Out, key_type_ref,
data_type_ref Methods, unsigned DataLen) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- clang::io::Emit32(Out, Methods.ID);
+ LE.write<uint32_t>(Methods.ID);
unsigned NumInstanceMethods = 0;
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
@@ -2779,16 +2776,16 @@
unsigned FactoryBits = Methods.Factory.getBits();
assert(FactoryBits < 4);
unsigned NumFactoryMethodsAndBits = (NumFactoryMethods << 2) | FactoryBits;
- clang::io::Emit16(Out, NumInstanceMethodsAndBits);
- clang::io::Emit16(Out, NumFactoryMethodsAndBits);
+ LE.write<uint16_t>(NumInstanceMethodsAndBits);
+ LE.write<uint16_t>(NumFactoryMethodsAndBits);
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (Method->Method)
- clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+ LE.write<uint32_t>(Writer.getDeclID(Method->Method));
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (Method->Method)
- clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
+ LE.write<uint32_t>(Writer.getDeclID(Method->Method));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
@@ -2857,10 +2854,11 @@
SmallString<4096> MethodPool;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
ASTMethodPoolTrait Trait(*this);
llvm::raw_svector_ostream Out(MethodPool);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -2959,83 +2957,101 @@
return false;
}
- DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList;
+
+ MacroDirective *
+ getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) {
ModID = 0;
- if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ llvm::SmallVector<SubmoduleID, 1> Overridden;
+ if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
- DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD,
- SubmoduleID &ModID) {
- if (DefMacroDirective *
- DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ MacroDirective *
+ getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID,
+ OverriddenList &Overridden) {
+ if (MacroDirective *NextMD =
+ getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
/// \brief Traverses the macro directives history and returns the latest
- /// macro that is public and not undefined in the same submodule.
- /// A macro that is defined in submodule A and undefined in submodule B,
+ /// public macro definition or undefinition that is not in ModID.
+ /// A macro that is defined in submodule A and undefined in submodule B
/// will still be considered as defined/exported from submodule A.
- DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ /// 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) {
if (!MD)
return 0;
+ Overridden.clear();
SubmoduleID OrigModID = ModID;
- bool isUndefined = false;
- Optional<bool> isPublic;
+ Optional<bool> IsPublic;
for (; MD; MD = MD->getPrevious()) {
- if (MD->isHidden())
- continue;
-
SubmoduleID ThisModID = getSubmoduleID(MD);
if (ThisModID == 0) {
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
continue;
}
- if (ThisModID != ModID){
+ if (ThisModID != ModID) {
ModID = ThisModID;
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
}
+
+ // 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);
+ }
+
// 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)
continue;
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue()))
- return DefMD;
- 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.
+ return MD;
}
-
- if (isa<UndefMacroDirective>(MD)) {
- isUndefined = true;
- continue;
- }
-
- VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
- if (!isPublic.hasValue())
- isPublic = VisMD->isPublic();
}
return 0;
}
SubmoduleID getSubmoduleID(MacroDirective *MD) {
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- MacroInfo *MI = DefMD->getInfo();
- if (unsigned ID = MI->getOwningModuleID())
- return ID;
- return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
- }
return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
}
@@ -3066,11 +3082,18 @@
DataLen += 4; // MacroDirectives offset.
if (IsModule) {
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- DataLen += 4; // MacroInfo ID.
+ 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());
+ DataLen += 4; // MacroInfo ID or ModuleID.
}
+ // Previous macro's overrides.
+ if (!Overridden.empty())
+ DataLen += 4 * (1 + Overridden.size());
DataLen += 4;
}
}
@@ -3080,11 +3103,14 @@
D != DEnd; ++D)
DataLen += sizeof(DeclID);
}
- clang::io::Emit16(Out, DataLen);
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+
+ LE.write<uint16_t>(DataLen);
// We emit the key length after the data length so that every
// string is preceded by a 16-bit length. This matches the PTH
// format for storing identifiers.
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -3096,18 +3122,31 @@
Out.write(II->getNameStart(), KeyLen);
}
+ static void emitMacroOverrides(raw_ostream &Out,
+ llvm::ArrayRef<SubmoduleID> Overridden) {
+ if (!Overridden.empty()) {
+ 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)
+ LE.write<uint32_t>(Overridden[I]);
+ }
+ }
+
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
MacroDirective *Macro = 0;
if (!isInterestingIdentifier(II, Macro)) {
- clang::io::Emit32(Out, ID << 1);
+ LE.write<uint32_t>(ID << 1);
return;
}
- clang::io::Emit32(Out, (ID << 1) | 0x01);
+ LE.write<uint32_t>((ID << 1) | 0x01);
uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID();
assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
- clang::io::Emit16(Out, Bits);
+ LE.write<uint16_t>(Bits);
Bits = 0;
bool HadMacroDefinition = hadMacroDefinition(II, Macro);
Bits = (Bits << 1) | unsigned(HadMacroDefinition);
@@ -3116,21 +3155,30 @@
Bits = (Bits << 1) | unsigned(II->isPoisoned());
Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
- clang::io::Emit16(Out, Bits);
+ LE.write<uint16_t>(Bits);
if (HadMacroDefinition) {
- clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II));
+ LE.write<uint32_t>(Writer.getMacroDirectivesOffset(II));
if (IsModule) {
// Write the IDs of macros coming from different submodules.
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
- assert(InfoID);
- clang::io::Emit32(Out, InfoID);
+ llvm::SmallVector<SubmoduleID, 4> Overridden;
+ for (MacroDirective *
+ MD = getFirstPublicSubmoduleMacro(Macro, ModID);
+ MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
+ MacroID InfoID = 0;
+ emitMacroOverrides(Out, Overridden);
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ 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);
+ }
}
- clang::io::Emit32(Out, 0);
+ emitMacroOverrides(Out, Overridden);
+ LE.write<uint32_t>(0);
}
}
@@ -3145,7 +3193,7 @@
for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(),
DEnd = Decls.rend();
D != DEnd; ++D)
- clang::io::Emit32(Out, Writer.getDeclID(getMostRecentLocalDecl(*D)));
+ LE.write<uint32_t>(Writer.getDeclID(getMostRecentLocalDecl(*D)));
}
/// \brief Returns the most recent local decl or the given decl if there are
@@ -3214,10 +3262,11 @@
SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
{
+ using namespace llvm::support;
ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
+ endian::Writer<little>(Out).write<uint32_t>(0);
BucketOffset = Generator.Emit(Out, Trait);
}
@@ -3306,6 +3355,8 @@
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, DeclarationName Name,
data_type_ref Lookup) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
unsigned KeyLen = 1;
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
@@ -3324,35 +3375,35 @@
case DeclarationName::CXXUsingDirective:
break;
}
- clang::io::Emit16(Out, KeyLen);
+ LE.write<uint16_t>(KeyLen);
// 2 bytes for num of decls and 4 for each DeclID.
unsigned DataLen = 2 + 4 * Lookup.size();
- clang::io::Emit16(Out, DataLen);
+ LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
void EmitKey(raw_ostream& Out, DeclarationName Name, unsigned) {
- using namespace clang::io;
-
- Emit8(Out, Name.getNameKind());
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
+ LE.write<uint8_t>(Name.getNameKind());
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
- Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
return;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
- Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector()));
+ LE.write<uint32_t>(Writer.getSelectorRef(Name.getObjCSelector()));
return;
case DeclarationName::CXXOperatorName:
assert(Name.getCXXOverloadedOperator() < NUM_OVERLOADED_OPERATORS &&
"Invalid operator?");
- Emit8(Out, Name.getCXXOverloadedOperator());
+ LE.write<uint8_t>(Name.getCXXOverloadedOperator());
return;
case DeclarationName::CXXLiteralOperatorName:
- Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
+ LE.write<uint32_t>(Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
return;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
@@ -3366,17 +3417,110 @@
void EmitData(raw_ostream& Out, key_type_ref,
data_type Lookup, unsigned DataLen) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- clang::io::Emit16(Out, Lookup.size());
+ LE.write<uint16_t>(Lookup.size());
for (DeclContext::lookup_iterator I = Lookup.begin(), E = Lookup.end();
I != E; ++I)
- clang::io::Emit32(Out, Writer.GetDeclRef(*I));
+ LE.write<uint32_t>(Writer.GetDeclRef(*I));
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
} // end anonymous namespace
+uint32_t
+ASTWriter::GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable) {
+ assert(!DC->LookupPtr.getInt() && "must call buildLookups first");
+ assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");
+
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the on-disk hash table representation.
+ DeclarationName ConstructorName;
+ DeclarationName ConversionName;
+ SmallVector<NamedDecl *, 8> ConstructorDecls;
+ SmallVector<NamedDecl *, 4> ConversionDecls;
+
+ auto AddLookupResult = [&](DeclarationName Name,
+ DeclContext::lookup_result Result) {
+ if (Result.empty())
+ return;
+
+ // Different DeclarationName values of certain kinds are mapped to
+ // identical serialized keys, because we don't want to use type
+ // identifiers in the keys (since type ids are local to the module).
+ switch (Name.getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ // There may be different CXXConstructorName DeclarationName values
+ // in a DeclContext because a UsingDecl that inherits constructors
+ // has the DeclarationName of the inherited constructors.
+ if (!ConstructorName)
+ ConstructorName = Name;
+ ConstructorDecls.append(Result.begin(), Result.end());
+ return;
+ case DeclarationName::CXXConversionFunctionName:
+ if (!ConversionName)
+ ConversionName = Name;
+ ConversionDecls.append(Result.begin(), Result.end());
+ return;
+ default:
+ break;
+ }
+
+ Generator.insert(Name, Result, Trait);
+ };
+
+ SmallVector<DeclarationName, 16> ExternalNames;
+ for (auto &Lookup : *DC->getLookupPtr()) {
+ if (Lookup.second.hasExternalDecls() ||
+ DC->NeedToReconcileExternalVisibleStorage) {
+ // We don't know for sure what declarations are found by this name,
+ // because the external source might have a different set from the set
+ // that are in the lookup map, and we can't update it now without
+ // risking invalidating our lookup iterator. So add it to a queue to
+ // deal with later.
+ ExternalNames.push_back(Lookup.first);
+ continue;
+ }
+
+ AddLookupResult(Lookup.first, Lookup.second.getLookupResult());
+ }
+
+ // Add the names we needed to defer. Note, this shouldn't add any new decls
+ // to the list we need to serialize: any new declarations we find here should
+ // be imported from an external source.
+ // FIXME: What if the external source isn't an ASTReader?
+ for (const auto &Name : ExternalNames)
+ // FIXME: const_cast since OnDiskHashTable wants a non-const lookup result.
+ AddLookupResult(Name, const_cast<DeclContext*>(DC)->lookup(Name));
+
+ // Add the constructors.
+ if (!ConstructorDecls.empty()) {
+ Generator.insert(ConstructorName,
+ DeclContext::lookup_result(ConstructorDecls.begin(),
+ ConstructorDecls.end()),
+ Trait);
+ }
+ // Add the conversion functions.
+ if (!ConversionDecls.empty()) {
+ Generator.insert(ConversionName,
+ DeclContext::lookup_result(ConversionDecls.begin(),
+ ConversionDecls.end()),
+ Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ using namespace llvm::support;
+ endian::Writer<little>(Out).write<uint32_t>(0);
+ return Generator.Emit(Out, Trait);
+}
+
/// \brief Write the block containing all of the declaration IDs
/// visible from the given DeclContext.
///
@@ -3407,50 +3551,9 @@
if (!Map || Map->empty())
return 0;
- OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
-
- // Create the on-disk hash table representation.
- DeclarationName ConversionName;
- SmallVector<NamedDecl *, 4> ConversionDecls;
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- DeclarationName Name = D->first;
- DeclContext::lookup_result Result = D->second.getLookupResult();
- if (!Result.empty()) {
- if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
- // Hash all conversion function names to the same name. The actual
- // type information in conversion function name is not used in the
- // key (since such type information is not stable across different
- // modules), so the intended effect is to coalesce all of the conversion
- // functions under a single key.
- if (!ConversionName)
- ConversionName = Name;
- ConversionDecls.append(Result.begin(), Result.end());
- continue;
- }
-
- Generator.insert(Name, Result, Trait);
- }
- }
-
- // Add the conversion functions
- if (!ConversionDecls.empty()) {
- Generator.insert(ConversionName,
- DeclContext::lookup_result(ConversionDecls.begin(),
- ConversionDecls.end()),
- Trait);
- }
-
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset;
- {
- llvm::raw_svector_ostream Out(LookupTable);
- // Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
- BucketOffset = Generator.Emit(Out, Trait);
- }
+ uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
// Write the lookup table
RecordData Record;
@@ -3471,33 +3574,13 @@
/// (in C++), for namespaces, and for classes with forward-declared unscoped
/// enumeration members (in C++11).
void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
- StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ StoredDeclsMap *Map = DC->getLookupPtr();
if (!Map || Map->empty())
return;
- OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
- ASTDeclContextNameLookupTrait Trait(*this);
-
- // Create the hash table.
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- DeclarationName Name = D->first;
- DeclContext::lookup_result Result = D->second.getLookupResult();
- // For any name that appears in this table, the results are complete, i.e.
- // they overwrite results from previous PCHs. Merging is always a mess.
- if (!Result.empty())
- Generator.insert(Name, Result, Trait);
- }
-
// Create the on-disk hash table in a buffer.
SmallString<4096> LookupTable;
- uint32_t BucketOffset;
- {
- llvm::raw_svector_ostream Out(LookupTable);
- // Make sure that no bucket is at offset 0
- clang::io::Emit32(Out, 0);
- BucketOffset = Generator.Emit(Out, Trait);
- }
+ uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
// Write the lookup table
RecordData Record;
@@ -3799,9 +3882,7 @@
}
ASTWriter::~ASTWriter() {
- for (FileDeclIDsTy::iterator
- I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(FileDeclIDs);
}
void ASTWriter::WriteAST(Sema &SemaRef,
@@ -4032,11 +4113,9 @@
// translation unit that do not come from other AST files.
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
SmallVector<KindDeclIDPair, 64> NewGlobalDecls;
- for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
- E = TU->noload_decls_end();
- I != E; ++I) {
- if (!(*I)->isFromASTFile())
- NewGlobalDecls.push_back(std::make_pair((*I)->getKind(), GetDeclRef(*I)));
+ for (const auto *I : TU->noload_decls()) {
+ if (!I->isFromASTFile())
+ NewGlobalDecls.push_back(std::make_pair(I->getKind(), GetDeclRef(I)));
}
llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
@@ -4059,14 +4138,25 @@
// If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block.
+ // FIXME: Why do we not do this if there's already an update block?
if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {
ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
- if (Record.empty()) {
- Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
- Record.push_back(reinterpret_cast<uint64_t>(NS));
- }
+ if (Record.empty())
+ Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS));
}
+ // Add update records for all mangling numbers and static local numbers.
+ // These aren't really update records, but this is a convenient way of
+ // tagging this rare extra data onto the declarations.
+ for (const auto &Number : Context.MangleNumbers)
+ if (!Number.first->isFromASTFile())
+ DeclUpdates[Number.first].push_back(DeclUpdate(UPD_MANGLING_NUMBER,
+ Number.second));
+ for (const auto &Number : Context.StaticLocalNumbers)
+ if (!Number.first->isFromASTFile())
+ DeclUpdates[Number.first].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER,
+ Number.second));
+
// Make sure visible decls, added to DeclContexts previously loaded from
// an AST file, are registered for serialization.
for (SmallVectorImpl<const Decl *>::iterator
@@ -4090,9 +4180,6 @@
}
}
- // Resolve any declaration pointers within the declaration updates block.
- ResolveDeclUpdatesBlocks();
-
// Form the record of special types.
RecordData SpecialTypes;
AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes);
@@ -4104,30 +4191,6 @@
AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes);
AddTypeRef(Context.getucontext_tType(), SpecialTypes);
- // Keep writing types and declarations until all types and
- // declarations have been written.
- Stream.EnterSubblock(DECLTYPES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
- WriteDeclsBlockAbbrevs();
- for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
- E = DeclsToRewrite.end();
- I != E; ++I)
- DeclTypesToEmit.push(const_cast<Decl*>(*I));
- while (!DeclTypesToEmit.empty()) {
- DeclOrType DOT = DeclTypesToEmit.front();
- DeclTypesToEmit.pop();
- if (DOT.isType())
- WriteType(DOT.getType());
- else
- WriteDecl(Context, DOT.getDecl());
- }
- Stream.ExitBlock();
-
- DoneWritingDeclsAndTypes = true;
-
- WriteFileDeclIDsMap();
- WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
- WriteComments();
-
if (Chain) {
// Write the mapping information describing our module dependencies and how
// each of those modules were mapped into our own offset/ID space, so that
@@ -4154,17 +4217,19 @@
for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(),
MEnd = Chain->ModuleMgr.end();
M != MEnd; ++M) {
+ using namespace llvm::support;
+ endian::Writer<little> LE(Out);
StringRef FileName = (*M)->FileName;
- io::Emit16(Out, FileName.size());
+ LE.write<uint16_t>(FileName.size());
Out.write(FileName.data(), FileName.size());
- io::Emit32(Out, (*M)->SLocEntryBaseOffset);
- io::Emit32(Out, (*M)->BaseIdentifierID);
- io::Emit32(Out, (*M)->BaseMacroID);
- io::Emit32(Out, (*M)->BasePreprocessedEntityID);
- io::Emit32(Out, (*M)->BaseSubmoduleID);
- io::Emit32(Out, (*M)->BaseSelectorID);
- io::Emit32(Out, (*M)->BaseDeclID);
- io::Emit32(Out, (*M)->BaseTypeIndex);
+ 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);
}
}
Record.clear();
@@ -4172,6 +4237,41 @@
Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
Buffer.data(), Buffer.size());
}
+
+ RecordData DeclUpdatesOffsetsRecord;
+
+ // 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();
+ for (DeclsToRewriteTy::iterator I = DeclsToRewrite.begin(),
+ E = DeclsToRewrite.end();
+ I != E; ++I)
+ DeclTypesToEmit.push(const_cast<Decl*>(*I));
+ do {
+ WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);
+ while (!DeclTypesToEmit.empty()) {
+ DeclOrType DOT = DeclTypesToEmit.front();
+ DeclTypesToEmit.pop();
+ if (DOT.isType())
+ WriteType(DOT.getType());
+ else
+ WriteDecl(Context, DOT.getDecl());
+ }
+ } while (!DeclUpdates.empty());
+ Stream.ExitBlock();
+
+ DoneWritingDeclsAndTypes = true;
+
+ // These things can only be done once we've written out decls and types.
+ WriteTypeDeclOffsets();
+ if (!DeclUpdatesOffsetsRecord.empty())
+ Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
+ WriteCXXBaseSpecifiersOffsets();
+ WriteFileDeclIDsMap();
+ WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
+
+ WriteComments();
WritePreprocessor(PP, isModule);
WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
WriteSelectors(SemaRef);
@@ -4179,12 +4279,8 @@
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);
-
- WriteTypeDeclOffsets();
WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
- WriteCXXBaseSpecifiersOffsets();
-
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
@@ -4192,8 +4288,8 @@
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
// Write the record containing external, unnamed definitions.
- if (!ExternalDefinitions.empty())
- Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+ if (!EagerlyDeserializedDecls.empty())
+ Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);
// Write the record containing tentative definitions.
if (!TentativeDefinitions.empty())
@@ -4258,27 +4354,41 @@
if (!WritingModule) {
// Write the submodules that were imported, if any.
- RecordData ImportedModules;
- for (ASTContext::import_iterator I = Context.local_import_begin(),
- IEnd = Context.local_import_end();
- I != IEnd; ++I) {
+ struct ModuleInfo {
+ uint64_t ID;
+ Module *M;
+ ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {}
+ };
+ llvm::SmallVector<ModuleInfo, 64> Imports;
+ for (const auto *I : Context.local_imports()) {
assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
- ImportedModules.push_back(SubmoduleIDs[I->getImportedModule()]);
+ Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()],
+ I->getImportedModule()));
}
- if (!ImportedModules.empty()) {
- // Sort module IDs.
- llvm::array_pod_sort(ImportedModules.begin(), ImportedModules.end());
-
- // Unique module IDs.
- ImportedModules.erase(std::unique(ImportedModules.begin(),
- ImportedModules.end()),
- ImportedModules.end());
-
+
+ if (!Imports.empty()) {
+ auto Cmp = [](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.end());
+
+ RecordData ImportedModules;
+ for (const auto &Import : Imports) {
+ ImportedModules.push_back(Import.ID);
+ // FIXME: If the module has macros imported then later has declarations
+ // imported, this location won't be the right one as a location for the
+ // declaration imports.
+ AddSourceLocation(Import.M->MacroVisibilityLoc, ImportedModules);
+ }
+
Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);
}
}
- WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
WriteRedeclarations();
WriteMergedDecls();
@@ -4295,64 +4405,79 @@
Stream.ExitBlock();
}
-/// \brief Go through the declaration update blocks and resolve declaration
-/// pointers into declaration IDs.
-void ASTWriter::ResolveDeclUpdatesBlocks() {
- for (DeclUpdateMap::iterator
- I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
- const Decl *D = I->first;
- UpdateRecord &URec = I->second;
-
- if (isRewritten(D))
- continue; // The decl will be written completely
-
- unsigned Idx = 0, N = URec.size();
- while (Idx < N) {
- switch ((DeclUpdateKind)URec[Idx++]) {
- case UPD_CXX_ADDED_IMPLICIT_MEMBER:
- case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
- case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
- URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
- ++Idx;
- break;
-
- case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
- case UPD_DECL_MARKED_USED:
- ++Idx;
- break;
-
- case UPD_CXX_DEDUCED_RETURN_TYPE:
- URec[Idx] = GetOrCreateTypeID(
- QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx])));
- ++Idx;
- break;
- }
- }
- }
-}
-
-void ASTWriter::WriteDeclUpdatesBlocks() {
+void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
if (DeclUpdates.empty())
return;
- RecordData OffsetsRecord;
- Stream.EnterSubblock(DECL_UPDATES_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
- for (DeclUpdateMap::iterator
- I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
- const Decl *D = I->first;
- UpdateRecord &URec = I->second;
+ DeclUpdateMap LocalUpdates;
+ LocalUpdates.swap(DeclUpdates);
+ for (auto &DeclUpdate : LocalUpdates) {
+ const Decl *D = DeclUpdate.first;
if (isRewritten(D))
continue; // The decl will be written completely,no need to store updates.
- uint64_t Offset = Stream.GetCurrentBitNo();
- Stream.EmitRecord(DECL_UPDATES, URec);
-
OffsetsRecord.push_back(GetDeclRef(D));
- OffsetsRecord.push_back(Offset);
+ OffsetsRecord.push_back(Stream.GetCurrentBitNo());
+
+ bool HasUpdatedBody = false;
+ RecordData Record;
+ for (auto &Update : DeclUpdate.second) {
+ DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind();
+
+ Record.push_back(Kind);
+ switch (Kind) {
+ case UPD_CXX_ADDED_IMPLICIT_MEMBER:
+ case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
+ case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
+ 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:
+ // 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_RESOLVED_EXCEPTION_SPEC:
+ addExceptionSpec(
+ *this,
+ cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>(),
+ Record);
+ break;
+
+ case UPD_CXX_DEDUCED_RETURN_TYPE:
+ Record.push_back(GetOrCreateTypeID(Update.getType()));
+ break;
+
+ case UPD_DECL_MARKED_USED:
+ break;
+
+ case UPD_MANGLING_NUMBER:
+ case UPD_STATIC_LOCAL_NUMBER:
+ Record.push_back(Update.getNumber());
+ break;
+ }
+ }
+
+ if (HasUpdatedBody) {
+ const FunctionDecl *Def = cast<FunctionDecl>(D);
+ Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION);
+ Record.push_back(Def->isInlined());
+ AddSourceLocation(Def->getInnerLocStart(), Record);
+ AddFunctionDefinition(Def, Record);
+ }
+
+ Stream.EmitRecord(DECL_UPDATES, Record);
+
+ // Flush any statements that were written as part of this update record.
+ FlushStmts();
}
- Stream.ExitBlock();
- Stream.EmitRecord(DECL_UPDATE_OFFSETS, OffsetsRecord);
}
void ASTWriter::WriteDeclReplacementsBlock() {
@@ -4648,7 +4773,7 @@
assert(SM.isLocalSourceLocation(FileLoc));
FileID FID;
unsigned Offset;
- llvm::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
+ std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
if (FID.isInvalid())
return;
assert(SM.getSLocEntry(FID).isFile());
@@ -5084,6 +5209,7 @@
Record.push_back(Data.HasProtectedFields);
Record.push_back(Data.HasPublicFields);
Record.push_back(Data.HasMutableFields);
+ Record.push_back(Data.HasVariantMembers);
Record.push_back(Data.HasOnlyCMembers);
Record.push_back(Data.HasInClassInitializer);
Record.push_back(Data.HasUninitializedReferenceMember);
@@ -5266,9 +5392,7 @@
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
- UpdateRecord &Record = DeclUpdates[RD];
- Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
@@ -5279,9 +5403,8 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
}
void ASTWriter::AddedCXXTemplateSpecialization(
@@ -5292,9 +5415,8 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
@@ -5305,9 +5427,17 @@
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
+ D));
+}
+
+void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
+ assert(!WritingAST && "Already writing the AST!");
+ FD = FD->getCanonicalDecl();
+ if (!FD->isFromASTFile())
+ return; // Not a function declared in PCH and defined outside.
+
+ DeclUpdates[FD].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);
}
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
@@ -5316,9 +5446,7 @@
if (!FD->isFromASTFile())
return; // Not a function declared in PCH and defined outside.
- UpdateRecord &Record = DeclUpdates[FD];
- Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE);
- Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr()));
+ DeclUpdates[FD].push_back(DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
@@ -5331,6 +5459,17 @@
RewriteDecl(D);
}
+void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ 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));
+}
+
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
@@ -5338,10 +5477,9 @@
// Since the actual instantiation is delayed, this really means that we need
// to update the instantiation location.
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER);
- AddSourceLocation(
- D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record);
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+ D->getMemberSpecializationInfo()->getPointOfInstantiation()));
}
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
@@ -5375,6 +5513,5 @@
if (!D->isFromASTFile())
return;
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_DECL_MARKED_USED);
+ DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED));
}