summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Serialization
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization')
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp155
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp102
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h4
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp146
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp132
6 files changed, 334 insertions, 206 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
index 85c574c..b1bf4a6 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTCommon.cpp
@@ -221,6 +221,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
// redeclarable.
case Decl::ImplicitParam:
case Decl::ParmVar:
+ case Decl::ObjCTypeParam:
return false;
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
index 48a898c..3045629 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp
@@ -845,7 +845,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
}
unsigned
-ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
+ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) {
llvm::FoldingSetNodeID ID;
ID.AddInteger(Key.Kind);
@@ -874,7 +874,7 @@ ASTDeclContextNameLookupTrait::ComputeHash(const DeclNameKey &Key) const {
ASTDeclContextNameLookupTrait::internal_key_type
ASTDeclContextNameLookupTrait::GetInternalKey(
- const external_key_type& Name) const {
+ const external_key_type& Name) {
DeclNameKey Key;
Key.Kind = Name.getNameKind();
switch (Name.getNameKind()) {
@@ -1644,6 +1644,7 @@ namespace {
/// \brief Visitor class used to look up identifirs in an AST file.
class IdentifierLookupVisitor {
StringRef Name;
+ unsigned NameHash;
unsigned PriorGeneration;
unsigned &NumIdentifierLookups;
unsigned &NumIdentifierLookupHits;
@@ -1653,7 +1654,8 @@ namespace {
IdentifierLookupVisitor(StringRef Name, unsigned PriorGeneration,
unsigned &NumIdentifierLookups,
unsigned &NumIdentifierLookupHits)
- : Name(Name), PriorGeneration(PriorGeneration),
+ : Name(Name), NameHash(ASTIdentifierLookupTrait::ComputeHash(Name)),
+ PriorGeneration(PriorGeneration),
NumIdentifierLookups(NumIdentifierLookups),
NumIdentifierLookupHits(NumIdentifierLookupHits),
Found()
@@ -1676,7 +1678,8 @@ namespace {
ASTIdentifierLookupTrait Trait(IdTable->getInfoObj().getReader(),
M, This->Found);
++This->NumIdentifierLookups;
- ASTIdentifierLookupTable::iterator Pos = IdTable->find(This->Name,&Trait);
+ ASTIdentifierLookupTable::iterator Pos =
+ IdTable->find_hashed(This->Name, This->NameHash, &Trait);
if (Pos == IdTable->end())
return false;
@@ -3976,8 +3979,7 @@ bool ASTReader::readASTFileControlBlock(
// Initialize the stream
llvm::BitstreamReader StreamFile;
- StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
- (const unsigned char *)(*Buffer)->getBufferEnd());
+ PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
BitstreamCursor Stream(StreamFile);
// Sniff for the signature.
@@ -5263,11 +5265,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
case TYPE_OBJC_OBJECT: {
unsigned Idx = 0;
QualType Base = readType(*Loc.F, Record, Idx);
+ unsigned NumTypeArgs = Record[Idx++];
+ SmallVector<QualType, 4> TypeArgs;
+ for (unsigned I = 0; I != NumTypeArgs; ++I)
+ TypeArgs.push_back(readType(*Loc.F, Record, Idx));
unsigned NumProtos = Record[Idx++];
SmallVector<ObjCProtocolDecl*, 4> Protos;
for (unsigned I = 0; I != NumProtos; ++I)
Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
- return Context.getObjCObjectType(Base, Protos.data(), NumProtos);
+ bool IsKindOf = Record[Idx++];
+ return Context.getObjCObjectType(Base, TypeArgs, Protos, IsKindOf);
}
case TYPE_OBJC_OBJECT_POINTER: {
@@ -5646,8 +5653,12 @@ void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
}
void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
TL.setHasBaseTypeAsWritten(Record[Idx++]);
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgsLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgsRAngleLoc(ReadSourceLocation(Record, Idx));
+ for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
+ TL.setTypeArgTInfo(i, Reader.GetTypeSourceInfo(F, Record, Idx));
+ TL.setProtocolLAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setProtocolRAngleLoc(ReadSourceLocation(Record, Idx));
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
}
@@ -5987,9 +5998,8 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
if (ID < NUM_PREDEF_DECL_IDS)
return false;
- GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(ID);
- assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
- return &M == I->second;
+ return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
+ ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls;
}
ModuleFile *ASTReader::getOwningModuleFile(const Decl *D) {
@@ -6063,7 +6073,7 @@ Decl *ASTReader::GetExistingDecl(DeclID ID) {
if (D) {
// Track that we have merged the declaration with ID \p ID into the
// pre-existing predefined declaration \p D.
- auto &Merged = MergedDecls[D->getCanonicalDecl()];
+ auto &Merged = KeyDecls[D->getCanonicalDecl()];
if (Merged.empty())
Merged.push_back(ID);
}
@@ -6288,6 +6298,27 @@ void ASTReader::FindFileRegionDecls(FileID File,
Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
}
+/// \brief Retrieve the "definitive" module file for the definition of the
+/// given declaration context, if there is one.
+///
+/// The "definitive" module file is the only place where we need to look to
+/// find information about the declarations within the given declaration
+/// context. For example, C++ and Objective-C classes, C structs/unions, and
+/// Objective-C protocols, categories, and extensions are all defined in a
+/// single place in the source code, so they have definitive module files
+/// associated with them. C++ namespaces, on the other hand, can have
+/// definitions in multiple different module files.
+///
+/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
+/// NDEBUG checking.
+static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
+ ASTReader &Reader) {
+ if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
+ return Reader.getOwningModuleFile(cast<Decl>(DefDC));
+
+ return nullptr;
+}
+
namespace {
/// \brief ModuleFile visitor used to perform name lookup into a
/// declaration context.
@@ -6295,18 +6326,38 @@ namespace {
ASTReader &Reader;
ArrayRef<const DeclContext *> Contexts;
DeclarationName Name;
+ ASTDeclContextNameLookupTrait::DeclNameKey NameKey;
+ unsigned NameHash;
SmallVectorImpl<NamedDecl *> &Decls;
llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet;
public:
DeclContextNameLookupVisitor(ASTReader &Reader,
- ArrayRef<const DeclContext *> Contexts,
DeclarationName Name,
SmallVectorImpl<NamedDecl *> &Decls,
llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet)
- : Reader(Reader), Contexts(Contexts), Name(Name), Decls(Decls),
- DeclSet(DeclSet) { }
+ : Reader(Reader), Name(Name),
+ NameKey(ASTDeclContextNameLookupTrait::GetInternalKey(Name)),
+ NameHash(ASTDeclContextNameLookupTrait::ComputeHash(NameKey)),
+ Decls(Decls), DeclSet(DeclSet) {}
+
+ void visitContexts(ArrayRef<const DeclContext*> Contexts) {
+ if (Contexts.empty())
+ return;
+ this->Contexts = Contexts;
+
+ // 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], Reader))) {
+ visit(*Definitive, this);
+ } else {
+ Reader.getModuleManager().visit(&visit, this);
+ }
+ }
+ private:
static bool visit(ModuleFile &M, void *UserData) {
DeclContextNameLookupVisitor *This
= static_cast<DeclContextNameLookupVisitor *>(UserData);
@@ -6331,7 +6382,7 @@ namespace {
ASTDeclContextNameLookupTable *LookupTable =
Info->second.NameLookupTableData;
ASTDeclContextNameLookupTable::iterator Pos
- = LookupTable->find(This->Name);
+ = LookupTable->find_hashed(This->NameKey, This->NameHash);
if (Pos == LookupTable->end())
return false;
@@ -6363,27 +6414,6 @@ namespace {
};
}
-/// \brief Retrieve the "definitive" module file for the definition of the
-/// given declaration context, if there is one.
-///
-/// The "definitive" module file is the only place where we need to look to
-/// find information about the declarations within the given declaration
-/// context. For example, C++ and Objective-C classes, C structs/unions, and
-/// Objective-C protocols, categories, and extensions are all defined in a
-/// single place in the source code, so they have definitive module files
-/// associated with them. C++ namespaces, on the other hand, can have
-/// definitions in multiple different module files.
-///
-/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's
-/// NDEBUG checking.
-static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC,
- ASTReader &Reader) {
- if (const DeclContext *DefDC = getDefinitiveDeclContext(DC))
- return Reader.getOwningModuleFile(cast<Decl>(DefDC));
-
- return nullptr;
-}
-
bool
ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
@@ -6405,28 +6435,15 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Contexts.push_back(DC);
if (DC->isNamespace()) {
- auto Merged = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Merged != MergedDecls.end()) {
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ auto Key = KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Key != KeyDecls.end()) {
+ for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
}
}
- auto LookUpInContexts = [&](ArrayRef<const DeclContext*> Contexts) {
- DeclContextNameLookupVisitor Visitor(*this, Contexts, Name, Decls, DeclSet);
-
- // 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);
+ DeclContextNameLookupVisitor Visitor(*this, Name, Decls, DeclSet);
+ Visitor.visitContexts(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
@@ -6437,7 +6454,7 @@ ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
if (Merged != MergedLookups.end()) {
for (unsigned I = 0; I != Merged->second.size(); ++I) {
const DeclContext *Context = Merged->second[I];
- LookUpInContexts(Context);
+ Visitor.visitContexts(Context);
// We might have just added some more merged lookups. If so, our
// iterator is now invalid, so grab a fresh one before continuing.
Merged = MergedLookups.find(DC);
@@ -6525,11 +6542,11 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
Contexts.push_back(DC);
if (DC->isNamespace()) {
- MergedDeclsMap::iterator Merged
- = MergedDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
- if (Merged != MergedDecls.end()) {
- for (unsigned I = 0, N = Merged->second.size(); I != N; ++I)
- Contexts.push_back(cast<DeclContext>(GetDecl(Merged->second[I])));
+ KeyDeclsMap::iterator Key =
+ KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC)));
+ if (Key != KeyDecls.end()) {
+ for (unsigned I = 0, N = Key->second.size(); I != N; ++I)
+ Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I])));
}
}
@@ -8389,6 +8406,11 @@ void ASTReader::diagnoseOdrViolations() {
}
}
+void ASTReader::StartedDeserializing() {
+ if (++NumCurrentElementsDeserializing == 1 && ReadTimer.get())
+ ReadTimer->startTimer();
+}
+
void ASTReader::FinishedDeserializing() {
assert(NumCurrentElementsDeserializing &&
"FinishedDeserializing not paired with StartedDeserializing");
@@ -8413,6 +8435,9 @@ void ASTReader::FinishedDeserializing() {
diagnoseOdrViolations();
+ if (ReadTimer)
+ ReadTimer->stopTimer();
+
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
if (Consumer)
@@ -8451,12 +8476,14 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context,
StringRef isysroot, bool DisableValidation,
bool AllowASTWithCompilerErrors,
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
- bool UseGlobalIndex)
+ bool UseGlobalIndex,
+ std::unique_ptr<llvm::Timer> ReadTimer)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()),
FileMgr(PP.getFileManager()), PCHContainerOps(PCHContainerOps),
Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context),
Consumer(nullptr), ModuleMgr(PP.getFileManager(), PCHContainerOps),
+ ReadTimer(std::move(ReadTimer)),
isysroot(isysroot), DisableValidation(DisableValidation),
AllowASTWithCompilerErrors(AllowASTWithCompilerErrors),
AllowConfigurationMismatch(AllowConfigurationMismatch),
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
index b23c33c..1a0c5b5 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -128,20 +128,22 @@ namespace clang {
GlobalDeclID FirstID;
Decl *MergeWith;
mutable bool Owning;
+ bool IsKeyDecl;
Decl::Kind DeclKind;
void operator=(RedeclarableResult &) = delete;
public:
RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
- Decl *MergeWith, Decl::Kind DeclKind)
+ Decl *MergeWith, Decl::Kind DeclKind,
+ bool IsKeyDecl)
: Reader(Reader), FirstID(FirstID), MergeWith(MergeWith),
- Owning(true), DeclKind(DeclKind) {}
+ Owning(true), IsKeyDecl(IsKeyDecl), DeclKind(DeclKind) {}
RedeclarableResult(RedeclarableResult &&Other)
: Reader(Other.Reader), FirstID(Other.FirstID),
MergeWith(Other.MergeWith), Owning(Other.Owning),
- DeclKind(Other.DeclKind) {
+ IsKeyDecl(Other.IsKeyDecl), DeclKind(Other.DeclKind) {
Other.Owning = false;
}
@@ -156,6 +158,9 @@ namespace clang {
/// \brief Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
+ /// \brief Is this declaration the key declaration?
+ bool isKeyDecl() const { return IsKeyDecl; }
+
/// \brief Get a known declaration that this should be merged with, if
/// any.
Decl *getKnownMergeTarget() const { return MergeWith; }
@@ -348,10 +353,13 @@ namespace clang {
void mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID);
+ DeclID DsID, bool IsKeyDecl);
+
+ ObjCTypeParamList *ReadObjCTypeParamList();
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
void VisitObjCIvarDecl(ObjCIvarDecl *D);
@@ -899,18 +907,49 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
}
+void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ VisitTypedefNameDecl(D);
+ D->Variance = Record[Idx++];
+ D->Index = Record[Idx++];
+ D->VarianceLoc = ReadSourceLocation(Record, Idx);
+ D->ColonLoc = ReadSourceLocation(Record, Idx);
+}
+
void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
VisitNamedDecl(CD);
CD->setAtStartLoc(ReadSourceLocation(Record, Idx));
CD->setAtEndRange(ReadSourceRange(Record, Idx));
}
+ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
+ unsigned numParams = Record[Idx++];
+ if (numParams == 0)
+ return nullptr;
+
+ SmallVector<ObjCTypeParamDecl *, 4> typeParams;
+ typeParams.reserve(numParams);
+ for (unsigned i = 0; i != numParams; ++i) {
+ auto typeParam = ReadDeclAs<ObjCTypeParamDecl>(Record, Idx);
+ if (!typeParam)
+ return nullptr;
+
+ typeParams.push_back(typeParam);
+ }
+
+ SourceLocation lAngleLoc = ReadSourceLocation(Record, Idx);
+ SourceLocation rAngleLoc = ReadSourceLocation(Record, Idx);
+
+ return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc,
+ typeParams, rAngleLoc);
+}
+
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
RedeclarableResult Redecl = VisitRedeclarable(ID);
VisitObjCContainerDecl(ID);
TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
mergeRedeclarable(ID, Redecl);
-
+
+ ID->TypeParamList = ReadObjCTypeParamList();
if (Record[Idx++]) {
// Read the definition.
ID->allocateDefinitionData();
@@ -922,8 +961,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
ObjCInterfaceDecl::DefinitionData &Data = ID->data();
// Read the superclass.
- Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
- Data.SuperClassLoc = ReadSourceLocation(Record, Idx);
+ Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx);
Data.EndLoc = ReadSourceLocation(Record, Idx);
Data.HasDesignatedInitializers = Record[Idx++];
@@ -1020,6 +1058,7 @@ void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
Reader.CategoriesDeserialized.insert(CD);
CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+ CD->TypeParamList = ReadObjCTypeParamList();
unsigned NumProtoRefs = Record[Idx++];
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
ProtoRefs.reserve(NumProtoRefs);
@@ -2139,12 +2178,16 @@ ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
DeclID FirstDeclID = ReadDeclID(Record, Idx);
Decl *MergeWith = nullptr;
+ bool IsKeyDecl = ThisDeclID == FirstDeclID;
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
- if (FirstDeclID == 0)
+ if (FirstDeclID == 0) {
FirstDeclID = ThisDeclID;
- else if (unsigned N = Record[Idx++]) {
+ IsKeyDecl = true;
+ } else if (unsigned N = Record[Idx++]) {
+ IsKeyDecl = false;
+
// We have some declarations that must be before us in our redeclaration
// chain. Read them now, and remember that we ought to merge with one of
// them.
@@ -2170,7 +2213,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// The result structure takes care to note that we need to load the
// other declaration chains for this ID.
return RedeclarableResult(Reader, FirstDeclID, MergeWith,
- static_cast<T *>(D)->getKind());
+ static_cast<T *>(D)->getKind(), IsKeyDecl);
}
/// \brief Attempts to merge the given declaration (D) with another declaration
@@ -2209,11 +2252,12 @@ template<typename T> static T assert_cast(...) {
/// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
RedeclarableTemplateDecl *Existing,
- DeclID DsID) {
+ DeclID DsID, bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
- /*MergeWith*/ExistingPattern, DPattern->getKind());
+ /*MergeWith*/ExistingPattern, DPattern->getKind(),
+ IsKeyDecl);
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
@@ -2276,11 +2320,11 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
mergeTemplatePattern(
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
- TemplatePatternID);
+ TemplatePatternID, Redecl.isKeyDecl());
- // If this declaration was the canonical declaration, make a note of that.
- if (DCanon == D) {
- Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
+ // If this declaration is a key declaration, make a note of that.
+ if (Redecl.isKeyDecl()) {
+ Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID());
if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
Reader.PendingDeclChains.push_back(ExistingCanon);
}
@@ -3259,6 +3303,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_EMPTY:
D = EmptyDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_OBJC_TYPE_PARAM:
+ D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
+ break;
}
assert(D && "Unknown declaration reading AST file");
@@ -3418,20 +3465,9 @@ namespace {
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap,
Compare);
if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
- Result->FirstID != ID) {
- // If we have a previously-canonical singleton declaration that was
- // merged into another redeclaration chain, create a trivial chain
- // for this single declaration so that it will get wired into the
- // complete redeclaration chain.
- if (GlobalID != CanonID &&
- GlobalID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
- GlobalID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls) {
- addToChain(Reader.GetDecl(GlobalID));
- }
-
+ Result->FirstID != ID)
return;
- }
-
+
// Dig out all of the redeclarations.
unsigned Offset = Result->Offset;
unsigned N = M.RedeclarationChains[Offset];
@@ -3472,8 +3508,6 @@ namespace {
// 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;
}
@@ -3494,9 +3528,9 @@ void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
GlobalDeclID CanonID = CanonDecl->getGlobalID();
if (CanonID)
SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first.
- MergedDeclsMap::iterator MergedPos = MergedDecls.find(CanonDecl);
- if (MergedPos != MergedDecls.end())
- SearchDecls.append(MergedPos->second.begin(), MergedPos->second.end());
+ KeyDeclsMap::iterator KeyPos = KeyDecls.find(CanonDecl);
+ if (KeyPos != KeyDecls.end())
+ SearchDecls.append(KeyPos->second.begin(), KeyPos->second.end());
// Build up the list of redeclarations.
RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
index d1b032b..5b1c4f4 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h
@@ -68,8 +68,8 @@ public:
return a.Kind == b.Kind && a.Data == b.Data;
}
- hash_value_type ComputeHash(const DeclNameKey &Key) const;
- internal_key_type GetInternalKey(const external_key_type& Name) const;
+ static hash_value_type ComputeHash(const DeclNameKey &Key);
+ static internal_key_type GetInternalKey(const external_key_type& Name);
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
index 0d15b17..8b68638 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp
@@ -421,9 +421,13 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
+ Record.push_back(T->getTypeArgsAsWritten().size());
+ for (auto TypeArg : T->getTypeArgsAsWritten())
+ Writer.AddTypeRef(TypeArg, Record);
Record.push_back(T->getNumProtocols());
for (const auto *I : T->quals())
Writer.AddDeclRef(I, Record);
+ Record.push_back(T->isKindOfTypeAsWritten());
Code = TYPE_OBJC_OBJECT;
}
@@ -648,8 +652,12 @@ void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
}
void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
Record.push_back(TL.hasBaseTypeAsWritten());
- Writer.AddSourceLocation(TL.getLAngleLoc(), Record);
- Writer.AddSourceLocation(TL.getRAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getTypeArgsLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getTypeArgsRAngleLoc(), Record);
+ for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
+ Writer.AddTypeSourceInfo(TL.getTypeArgTInfo(i), Record);
+ Writer.AddSourceLocation(TL.getProtocolLAngleLoc(), Record);
+ Writer.AddSourceLocation(TL.getProtocolRAngleLoc(), Record);
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);
}
@@ -3626,6 +3634,55 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
/// bitstream, or 0 if no block was written.
uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
DeclContext *DC) {
+ // If we imported a key declaration of this namespace, write the visible
+ // lookup results as an update record for it rather than including them
+ // on this declaration. We will only look at key declarations on reload.
+ if (isa<NamespaceDecl>(DC) && Chain &&
+ Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {
+ // Only do this once, for the first local declaration of the namespace.
+ for (NamespaceDecl *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;
+ Prev = Prev->getPreviousDecl())
+ if (!Prev->isFromASTFile())
+ return 0;
+
+ // Note that we need to emit an update record for the primary context.
+ UpdatedDeclContexts.insert(DC->getPrimaryContext());
+
+ // Make sure all visible decls are written. They will be recorded later. We
+ // do this using a side data structure so we can sort the names into
+ // a deterministic order.
+ StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup();
+ SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>
+ LookupResults;
+ if (Map) {
+ LookupResults.reserve(Map->size());
+ for (auto &Entry : *Map)
+ LookupResults.push_back(
+ std::make_pair(Entry.first, Entry.second.getLookupResult()));
+ }
+
+ std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
+ for (auto &NameAndResult : LookupResults) {
+ DeclarationName Name = NameAndResult.first;
+ DeclContext::lookup_result Result = NameAndResult.second;
+ if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
+ // We have to work around a name lookup bug here where negative lookup
+ // results for these names get cached in namespace lookup tables (these
+ // names should never be looked up in a namespace).
+ assert(Result.empty() && "Cannot have a constructor or conversion "
+ "function name in a namespace!");
+ continue;
+ }
+
+ for (NamedDecl *ND : Result)
+ if (!ND->isFromASTFile())
+ GetDeclRef(ND);
+ }
+
+ return 0;
+ }
+
if (DC->getPrimaryContext() != DC)
return 0;
@@ -3677,6 +3734,11 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
SmallString<4096> LookupTable;
uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable);
+ // If we're updating a namespace, select a key declaration as the key for the
+ // update record; those are the only ones that will be checked on reload.
+ if (isa<NamespaceDecl>(DC))
+ DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));
+
// Write the lookup table
RecordData Record;
Record.push_back(UPDATE_VISIBLE);
@@ -3709,11 +3771,17 @@ void ASTWriter::WriteRedeclarations() {
SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
- Decl *First = Redeclarations[I];
- assert(First->isFirstDecl() && "Not the first declaration?");
-
- Decl *MostRecent = First->getMostRecentDecl();
-
+ const Decl *Key = Redeclarations[I];
+ assert((Chain ? Chain->getKeyDeclaration(Key) == Key
+ : Key->isFirstDecl()) &&
+ "not the key declaration");
+
+ const Decl *First = Key->getCanonicalDecl();
+ const Decl *MostRecent = First->getMostRecentDecl();
+
+ assert((getDeclID(First) >= NUM_PREDEF_DECL_IDS || First == Key) &&
+ "should not have imported key decls for predefined decl");
+
// If we only have a single declaration, there is no point in storing
// a redeclaration chain.
if (First == MostRecent)
@@ -3722,34 +3790,34 @@ void ASTWriter::WriteRedeclarations() {
unsigned Offset = LocalRedeclChains.size();
unsigned Size = 0;
LocalRedeclChains.push_back(0); // Placeholder for the size.
-
+
// Collect the set of local redeclarations of this declaration.
- for (Decl *Prev = MostRecent; Prev != First;
+ for (const Decl *Prev = MostRecent; Prev;
Prev = Prev->getPreviousDecl()) {
- if (!Prev->isFromASTFile()) {
+ if (!Prev->isFromASTFile() && Prev != Key) {
AddDeclRef(Prev, LocalRedeclChains);
++Size;
}
}
LocalRedeclChains[Offset] = Size;
-
+
// Reverse the set of local redeclarations, so that we store them in
// order (since we found them in reverse order).
std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end());
-
+
// Add the mapping from the first ID from the AST to the set of local
// declarations.
- LocalRedeclarationsInfo Info = { getDeclID(First), Offset };
+ LocalRedeclarationsInfo Info = { getDeclID(Key), Offset };
LocalRedeclsMap.push_back(Info);
-
+
assert(N == Redeclarations.size() &&
"Deserialized a declaration we shouldn't have");
}
-
+
if (LocalRedeclChains.empty())
return;
-
+
// Sort the local redeclarations map by the first declaration ID,
// since the reader will be performing binary searches on this information.
llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
@@ -4045,25 +4113,27 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
Preprocessor &PP = SemaRef.PP;
// Set up predefined declaration IDs.
- DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID;
- if (Context.ObjCIdDecl)
- DeclIDs[Context.ObjCIdDecl] = PREDEF_DECL_OBJC_ID_ID;
- if (Context.ObjCSelDecl)
- DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID;
- if (Context.ObjCClassDecl)
- DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID;
- if (Context.ObjCProtocolClassDecl)
- DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID;
- if (Context.Int128Decl)
- DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID;
- if (Context.UInt128Decl)
- DeclIDs[Context.UInt128Decl] = PREDEF_DECL_UNSIGNED_INT_128_ID;
- if (Context.ObjCInstanceTypeDecl)
- DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID;
- if (Context.BuiltinVaListDecl)
- DeclIDs[Context.getBuiltinVaListDecl()] = PREDEF_DECL_BUILTIN_VA_LIST_ID;
- if (Context.ExternCContext)
- DeclIDs[Context.ExternCContext] = PREDEF_DECL_EXTERN_C_CONTEXT_ID;
+ auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
+ if (D) {
+ assert(D->isCanonicalDecl() && "predefined decl is not canonical");
+ DeclIDs[D] = ID;
+ if (D->getMostRecentDecl() != D)
+ Redeclarations.push_back(D);
+ }
+ };
+ RegisterPredefDecl(Context.getTranslationUnitDecl(),
+ PREDEF_DECL_TRANSLATION_UNIT_ID);
+ RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID);
+ RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID);
+ RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID);
+ RegisterPredefDecl(Context.ObjCProtocolClassDecl,
+ PREDEF_DECL_OBJC_PROTOCOL_ID);
+ RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID);
+ RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID);
+ RegisterPredefDecl(Context.ObjCInstanceTypeDecl,
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID);
+ RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);
+ RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
// Build a record containing all of the tentative definitions in this file, in
// TentativeDefinitions order. Generally, this record will be empty for
@@ -5667,7 +5737,7 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
if (!Chain) return;
- Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) {
+ Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
// If we don't already know the exception specification for this redecl
// chain, add an update record for it.
if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)
@@ -5681,7 +5751,7 @@ void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
assert(!WritingAST && "Already writing the AST!");
if (!Chain) return;
- Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) {
+ Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
DeclUpdates[D].push_back(
DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));
});
@@ -5692,7 +5762,7 @@ void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
assert(!WritingAST && "Already writing the AST!");
assert(Delete && "Not given an operator delete");
if (!Chain) return;
- Chain->forEachFormerlyCanonicalImportedDecl(DD, [&](const Decl *D) {
+ Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));
});
}
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
index 6c5bc5b..fd6708d 100644
--- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -117,6 +117,7 @@ namespace clang {
// FIXME: Put in the same order is DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
+ void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
void VisitObjCIvarDecl(ObjCIvarDecl *D);
@@ -131,6 +132,22 @@ namespace clang {
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+ /// Add an Objective-C type parameter list to the given record.
+ void AddObjCTypeParamList(ObjCTypeParamList *typeParams) {
+ // Empty type parameter list.
+ if (!typeParams) {
+ Record.push_back(0);
+ return;
+ }
+
+ Record.push_back(typeParams->size());
+ for (auto typeParam : *typeParams) {
+ Writer.AddDeclRef(typeParam, Record);
+ }
+ Writer.AddSourceLocation(typeParams->getLAngleLoc(), Record);
+ Writer.AddSourceLocation(typeParams->getRAngleLoc(), Record);
+ }
+
void AddFunctionDefinition(const FunctionDecl *FD) {
assert(FD->doesThisDeclarationHaveABody());
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
@@ -237,6 +254,8 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
//
// This happens when we instantiate a class with a friend declaration or a
// function with a local extern declaration, for instance.
+ //
+ // FIXME: Can we handle this in AddedVisibleDecl instead?
if (D->isOutOfLine()) {
auto *DC = D->getDeclContext();
while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) {
@@ -562,6 +581,16 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Code = serialization::DECL_OBJC_METHOD;
}
+void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
+ VisitTypedefNameDecl(D);
+ Record.push_back(D->Variance);
+ Record.push_back(D->Index);
+ Writer.AddSourceLocation(D->VarianceLoc, Record);
+ Writer.AddSourceLocation(D->ColonLoc, Record);
+
+ Code = serialization::DECL_OBJC_TYPE_PARAM;
+}
+
void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getAtStartLoc(), Record);
@@ -573,14 +602,14 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
VisitRedeclarable(D);
VisitObjCContainerDecl(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
+ AddObjCTypeParamList(D->TypeParamList);
Record.push_back(D->isThisDeclarationADefinition());
if (D->isThisDeclarationADefinition()) {
// Write the DefinitionData
ObjCInterfaceDecl::DefinitionData &Data = D->data();
- Writer.AddDeclRef(D->getSuperClass(), Record);
- Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
+ Writer.AddTypeSourceInfo(D->getSuperClassTInfo(), Record);
Writer.AddSourceLocation(D->getEndOfDefinitionLoc(), Record);
Record.push_back(Data.HasDesignatedInitializers);
@@ -660,6 +689,7 @@ void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
Writer.AddSourceLocation(D->getIvarLBraceLoc(), Record);
Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record);
Writer.AddDeclRef(D->getClassInterface(), Record);
+ AddObjCTypeParamList(D->TypeParamList);
Record.push_back(D->protocol_size());
for (const auto *I : D->protocols())
Writer.AddDeclRef(I, Record);
@@ -977,40 +1007,6 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
Code = serialization::DECL_NAMESPACE;
- if (Writer.hasChain() && !D->isOriginalNamespace() &&
- D->getOriginalNamespace()->isFromASTFile()) {
- NamespaceDecl *NS = D->getOriginalNamespace();
- Writer.UpdatedDeclContexts.insert(NS);
-
- // Make sure all visible decls are written. They will be recorded later. We
- // do this using a side data structure so we can sort the names into
- // a deterministic order.
- StoredDeclsMap *Map = NS->buildLookup();
- SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>
- LookupResults;
- LookupResults.reserve(Map->size());
- for (auto &Entry : *Map)
- LookupResults.push_back(
- std::make_pair(Entry.first, Entry.second.getLookupResult()));
-
- std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first());
- for (auto &NameAndResult : LookupResults) {
- DeclarationName Name = NameAndResult.first;
- DeclContext::lookup_result Result = NameAndResult.second;
- if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
- Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
- // We have to work around a name lookup bug here where negative lookup
- // results for these names get cached in namespace lookup tables.
- assert(Result.empty() && "Cannot have a constructor or conversion "
- "function name in a namespace!");
- continue;
- }
-
- for (NamedDecl *ND : Result)
- Writer.GetDeclRef(ND);
- }
- }
-
if (Writer.hasChain() && D->isAnonymousNamespace() &&
D == D->getMostRecentDecl()) {
// This is a most recent reopening of the anonymous namespace. If its parent
@@ -1482,6 +1478,17 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
Record.push_back(VisibleOffset);
}
+/// Determine whether D is the first declaration in its redeclaration chain that
+/// is not from an AST file.
+template <typename T>
+static bool isFirstLocalDecl(Redeclarable<T> *D) {
+ assert(D && !static_cast<T*>(D)->isFromASTFile());
+ do
+ D = D->getPreviousDecl();
+ while (D && static_cast<T*>(D)->isFromASTFile());
+ return !D;
+}
+
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
T *First = D->getFirstDecl();
@@ -1490,41 +1497,30 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) &&
"Not considered redeclarable?");
- // There is more than one declaration of this entity, so we will need to
- // write a redeclaration chain.
Writer.AddDeclRef(First, Record);
- Writer.Redeclarations.insert(First);
- auto *Previous = D->getPreviousDecl();
-
- // In a modules build, we can have imported declarations after a local
- // canonical declaration. If this is the first local declaration, emit
- // a list of all such imported declarations so that we can ensure they
- // are loaded before we are. This allows us to rebuild the redecl chain
- // in the right order on reload (all declarations imported by a module
- // should be before all declarations provided by that module).
- bool EmitImportedMergedCanonicalDecls = false;
+ // In a modules build, emit a list of all imported key declarations
+ // (excluding First, if it was imported), so that we can be sure that all
+ // redeclarations visible to this module are before D in the redecl chain.
+ unsigned I = Record.size();
+ Record.push_back(0);
if (Context.getLangOpts().Modules && Writer.Chain) {
- auto *PreviousLocal = Previous;
- while (PreviousLocal && PreviousLocal->isFromASTFile())
- PreviousLocal = PreviousLocal->getPreviousDecl();
- if (!PreviousLocal)
- EmitImportedMergedCanonicalDecls = true;
+ if (isFirstLocalDecl(D)) {
+ Writer.Chain->forEachImportedKeyDecl(First, [&](const Decl *D) {
+ if (D != First)
+ Writer.AddDeclRef(D, Record);
+ });
+ Record[I] = Record.size() - I - 1;
+
+ // Write a redeclaration chain, attached to the first key decl.
+ Writer.Redeclarations.push_back(Writer.Chain->getKeyDeclaration(First));
+ }
+ } else if (D == First || D->getPreviousDecl()->isFromASTFile()) {
+ assert(isFirstLocalDecl(D) && "imported decl after local decl");
+
+ // Write a redeclaration chain attached to the first decl.
+ Writer.Redeclarations.push_back(First);
}
- if (EmitImportedMergedCanonicalDecls) {
- llvm::SmallMapVector<ModuleFile*, Decl*, 16> FirstInModule;
- for (auto *Redecl = MostRecent; Redecl;
- Redecl = Redecl->getPreviousDecl())
- if (Redecl->isFromASTFile())
- FirstInModule[Writer.Chain->getOwningModuleFile(Redecl)] = Redecl;
- // FIXME: If FirstInModule has entries for modules A and B, and B imports
- // A (directly or indirectly), we don't need to write the entry for A.
- Record.push_back(FirstInModule.size());
- for (auto I = FirstInModule.rbegin(), E = FirstInModule.rend();
- I != E; ++I)
- Writer.AddDeclRef(I->second, Record);
- } else
- Record.push_back(0);
// Make sure that we serialize both the previous and the most-recent
// declarations, which (transitively) ensures that all declarations in the
@@ -1532,7 +1528,7 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
//
// FIXME: This is not correct; when we reach an imported declaration we
// won't emit its previous declaration.
- (void)Writer.GetDeclRef(Previous);
+ (void)Writer.GetDeclRef(D->getPreviousDecl());
(void)Writer.GetDeclRef(MostRecent);
} else {
// We use the sentinel value 0 to indicate an only declaration.
OpenPOWER on IntegriCloud