aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTReaderDecl.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
commit5e20cdd81c44a443562a09007668ffdf76c455af (patch)
treedbbd4047878da71c1a706e26ce05b4e7791b14cc /lib/Serialization/ASTReaderDecl.cpp
parentd5f23b0b7528b5c3caed1ba14f897cc4aaa9e3c3 (diff)
Notes
Diffstat (limited to 'lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp779
1 files changed, 480 insertions, 299 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index a783183d2ef6..02273ed229a5 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -66,7 +66,12 @@ namespace clang {
serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
return Reader.ReadDeclID(F, R, I);
}
-
+
+ void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
+ for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
+ IDs.push_back(ReadDeclID(Record, Idx));
+ }
+
Decl *ReadDecl(const RecordData &R, unsigned &I) {
return Reader.ReadDecl(F, R, I);
}
@@ -103,11 +108,11 @@ namespace clang {
return Reader.getSubmodule(readSubmoduleID(R, I));
}
- void ReadCXXRecordDefinition(CXXRecordDecl *D);
+ void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
const RecordData &R, unsigned &I);
void MergeDefinitionData(CXXRecordDecl *D,
- struct CXXRecordDecl::DefinitionData &NewDD);
+ struct CXXRecordDecl::DefinitionData &&NewDD);
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
@@ -118,43 +123,42 @@ namespace clang {
/// \brief RAII class used to capture the first ID within a redeclaration
/// chain and to introduce it into the list of pending redeclaration chains
/// on destruction.
- ///
- /// The caller can choose not to introduce this ID into the list of pending
- /// redeclaration chains by calling \c suppress().
class RedeclarableResult {
ASTReader &Reader;
GlobalDeclID FirstID;
+ Decl *MergeWith;
mutable bool Owning;
Decl::Kind DeclKind;
-
- void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION;
-
+
+ void operator=(RedeclarableResult &) = delete;
+
public:
RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID,
- Decl::Kind DeclKind)
- : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { }
-
- RedeclarableResult(const RedeclarableResult &Other)
- : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) ,
- DeclKind(Other.DeclKind)
- {
+ Decl *MergeWith, Decl::Kind DeclKind)
+ : Reader(Reader), FirstID(FirstID), MergeWith(MergeWith),
+ Owning(true), DeclKind(DeclKind) {}
+
+ RedeclarableResult(RedeclarableResult &&Other)
+ : Reader(Other.Reader), FirstID(Other.FirstID),
+ MergeWith(Other.MergeWith), Owning(Other.Owning),
+ DeclKind(Other.DeclKind) {
Other.Owning = false;
}
~RedeclarableResult() {
- if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) &&
- Reader.PendingDeclChainsKnown.insert(FirstID).second)
- Reader.PendingDeclChains.push_back(FirstID);
+ if (FirstID && Owning && isRedeclarableDeclKind(DeclKind)) {
+ auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl();
+ if (Reader.PendingDeclChainsKnown.insert(Canon).second)
+ Reader.PendingDeclChains.push_back(Canon);
+ }
}
-
+
/// \brief Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
-
- /// \brief Do not introduce this declaration ID into the set of pending
- /// declaration chains.
- void suppress() {
- Owning = false;
- }
+
+ /// \brief Get a known declaration that this should be merged with, if
+ /// any.
+ Decl *getKnownMergeTarget() const { return MergeWith; }
};
/// \brief Class used to capture the result of searching for an existing
@@ -171,7 +175,7 @@ namespace clang {
unsigned AnonymousDeclNumber;
IdentifierInfo *TypedefNameForLinkage;
- void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION;
+ void operator=(FindExistingResult&) = delete;
public:
FindExistingResult(ASTReader &Reader)
@@ -205,6 +209,8 @@ namespace clang {
operator T*() const { return dyn_cast_or_null<T>(Existing); }
};
+ static DeclContext *getPrimaryContextForMerging(ASTReader &Reader,
+ DeclContext *DC);
FindExistingResult findExisting(NamedDecl *D);
public:
@@ -216,10 +222,17 @@ namespace clang {
TypedefNameForLinkage(nullptr), HasPendingBody(false) {}
template <typename DeclT>
+ static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
+ static Decl *getMostRecentDeclImpl(...);
+ static Decl *getMostRecentDecl(Decl *D);
+
+ template <typename DeclT>
static void attachPreviousDeclImpl(ASTReader &Reader,
- Redeclarable<DeclT> *D, Decl *Previous);
+ Redeclarable<DeclT> *D, Decl *Previous,
+ Decl *Canon);
static void attachPreviousDeclImpl(ASTReader &Reader, ...);
- static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous);
+ static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous,
+ Decl *Canon);
template <typename DeclT>
static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
@@ -390,9 +403,14 @@ void ASTDeclReader::Visit(Decl *D) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
// We only read it if FD doesn't already have a body (e.g., from another
// module).
- // FIXME: Also consider = default and = delete.
// FIXME: Can we diagnose ODR violations somehow?
if (Record[Idx++]) {
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ CD->NumCtorInitializers = Record[Idx++];
+ if (CD->NumCtorInitializers)
+ CD->CtorInitializers =
+ Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
+ }
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
}
@@ -440,24 +458,28 @@ void ASTDeclReader::VisitDecl(Decl *D) {
D->FromASTFile = true;
D->setModulePrivate(Record[Idx++]);
D->Hidden = D->isModulePrivate();
-
+
// Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible.
if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
// Store the owning submodule ID in the declaration.
D->setOwningModuleID(SubmoduleID);
-
- // Module-private declarations are never visible, so there is no work to do.
- if (!D->isModulePrivate()) {
- if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
- if (Owner->NameVisibility != Module::AllVisible) {
- // The owning module is not visible. Mark this declaration as hidden.
- D->Hidden = true;
-
- // Note that this declaration was hidden because its owning module is
- // not yet visible.
- Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D);
- }
+
+ if (D->Hidden) {
+ // Module-private declarations are never visible, so there is no work to do.
+ } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ // If local visibility is being tracked, this declaration will become
+ // hidden and visible as the owning module does. Inform Sema that this
+ // declaration might not be visible.
+ D->Hidden = true;
+ } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
+ if (Owner->NameVisibility != Module::AllVisible) {
+ // The owning module is not visible. Mark this declaration as hidden.
+ D->Hidden = true;
+
+ // Note that this declaration was hidden because its owning module is
+ // not yet visible.
+ Reader.HiddenNamesMap[Owner].push_back(D);
}
}
}
@@ -470,8 +492,7 @@ void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
VisitDecl(ND);
ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
- if (needsAnonymousDeclarationNumber(ND))
- AnonymousDeclNumber = Record[Idx++];
+ AnonymousDeclNumber = Record[Idx++];
}
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
@@ -981,8 +1002,9 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
D->setHasNonZeroConstructors(Record[Idx++]);
D->setHasDestructors(Record[Idx++]);
- std::tie(D->IvarInitializers, D->NumIvarInitializers) =
- Reader.ReadCXXCtorInitializers(F, Record, Idx);
+ D->NumIvarInitializers = Record[Idx++];
+ if (D->NumIvarInitializers)
+ D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
}
@@ -1041,13 +1063,15 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
VD->VarDeclBits.TSCSpec = Record[Idx++];
VD->VarDeclBits.InitStyle = Record[Idx++];
- VD->VarDeclBits.ExceptionVar = Record[Idx++];
- VD->VarDeclBits.NRVOVariable = Record[Idx++];
- VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
- VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
- VD->VarDeclBits.IsConstexpr = Record[Idx++];
- VD->VarDeclBits.IsInitCapture = Record[Idx++];
- VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
+ if (!isa<ParmVarDecl>(VD)) {
+ VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++];
+ VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++];
+ VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++];
+ VD->NonParmVarDeclBits.ARCPseudoStrong = Record[Idx++];
+ VD->NonParmVarDeclBits.IsConstexpr = Record[Idx++];
+ VD->NonParmVarDeclBits.IsInitCapture = Record[Idx++];
+ VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
+ }
Linkage VarLinkage = Linkage(Record[Idx++]);
VD->setCachedLinkage(VarLinkage);
@@ -1189,13 +1213,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
D->LocStart = ReadSourceLocation(Record, Idx);
D->RBraceLoc = ReadSourceLocation(Record, Idx);
+ // Defer loading the anonymous namespace until we've finished merging
+ // this namespace; loading it might load a later declaration of the
+ // same namespace, and we have an invariant that older declarations
+ // get merged before newer ones try to merge.
+ GlobalDeclID AnonNamespace = 0;
if (Redecl.getFirstID() == ThisDeclID) {
- // Each module has its own anonymous namespace, which is disjoint from
- // any other module's anonymous namespaces, so don't attach the anonymous
- // namespace at all.
- NamespaceDecl *Anon = ReadDeclAs<NamespaceDecl>(Record, Idx);
- if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
- D->setAnonymousNamespace(Anon);
+ AnonNamespace = ReadDeclID(Record, Idx);
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
@@ -1203,6 +1227,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
}
mergeRedeclarable(D, Redecl);
+
+ if (AnonNamespace) {
+ // Each module has its own anonymous namespace, which is disjoint from
+ // any other module's anonymous namespaces, so don't attach the anonymous
+ // namespace at all.
+ NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
+ if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
+ D->setAnonymousNamespace(Anon);
+ }
}
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
@@ -1353,7 +1386,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
}
void ASTDeclReader::MergeDefinitionData(
- CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &MergeDD) {
+ CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) {
assert(D->DefinitionData.getNotUpdated() &&
"merging class definition into non-definition");
auto &DD = *D->DefinitionData.getNotUpdated();
@@ -1364,14 +1397,45 @@ void ASTDeclReader::MergeDefinitionData(
// FIXME: We only need to do this if the merged definition declares members
// that this definition did not declare, or if it defines members that this
// definition did not define.
- if (MergeDD.DeclaredSpecialMembers && DD.Definition != MergeDD.Definition) {
+ if (DD.Definition != MergeDD.Definition) {
Reader.MergedLookups[DD.Definition].push_back(MergeDD.Definition);
DD.Definition->setHasExternalVisibleStorage();
+
+ if (DD.Definition->isHidden()) {
+ // If MergeDD is visible or becomes visible, make the definition visible.
+ if (!MergeDD.Definition->isHidden())
+ DD.Definition->Hidden = false;
+ else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ Reader.getContext().mergeDefinitionIntoModule(
+ DD.Definition, MergeDD.Definition->getImportedOwningModule(),
+ /*NotifyListeners*/ false);
+ Reader.PendingMergedDefinitionsToDeduplicate.insert(DD.Definition);
+ } else {
+ auto SubmoduleID = MergeDD.Definition->getOwningModuleID();
+ assert(SubmoduleID && "hidden definition in no module");
+ Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)].push_back(
+ DD.Definition);
+ }
+ }
+ }
+
+ auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
+ if (PFDI != Reader.PendingFakeDefinitionData.end() &&
+ PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) {
+ // We faked up this definition data because we found a class for which we'd
+ // not yet loaded the definition. Replace it with the real thing now.
+ assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?");
+ PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded;
+
+ // Don't change which declaration is the definition; that is required
+ // to be invariant once we select it.
+ auto *Def = DD.Definition;
+ DD = std::move(MergeDD);
+ DD.Definition = Def;
+ return;
}
// FIXME: Move this out into a .def file?
- // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than
- // asserting; this can happen in the case of an ODR violation.
bool DetectedOdrViolation = false;
#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
#define MATCH_FIELD(Field) \
@@ -1442,7 +1506,7 @@ void ASTDeclReader::MergeDefinitionData(
Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition);
}
-void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
+void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
struct CXXRecordDecl::DefinitionData *DD;
ASTContext &C = Reader.getContext();
@@ -1457,19 +1521,29 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
ReadCXXDefinitionData(*DD, Record, Idx);
- // If we're reading an update record, we might already have a definition for
- // this record. If so, just merge into it.
- if (D->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(D, *DD);
+ // We might already have a definition for this record. This can happen either
+ // because we're reading an update record, or because we've already done some
+ // merging. Either way, just merge into it.
+ CXXRecordDecl *Canon = D->getCanonicalDecl();
+ if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
+ if (CanonDD->Definition != DD->Definition)
+ Reader.MergedDeclContexts.insert(
+ std::make_pair(DD->Definition, CanonDD->Definition));
+ MergeDefinitionData(Canon, std::move(*DD));
+ D->DefinitionData = Canon->DefinitionData;
return;
}
// Propagate the DefinitionData pointer to the canonical declaration, so
// that all other deserialized declarations will see it.
- CXXRecordDecl *Canon = D->getCanonicalDecl();
if (Canon == D) {
D->DefinitionData = DD;
D->IsCompleteDefinition = true;
+
+ // If this is an update record, we can have redeclarations already. Make a
+ // note that we need to propagate the DefinitionData pointer onto them.
+ if (Update)
+ Reader.PendingDefinitions.insert(D);
} else if (auto *CanonDD = Canon->DefinitionData.getNotUpdated()) {
// We have already deserialized a definition of this record. This
// definition is no longer really a definition. Note that the pre-existing
@@ -1478,7 +1552,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D) {
std::make_pair(D, CanonDD->Definition));
D->DefinitionData = Canon->DefinitionData;
D->IsCompleteDefinition = false;
- MergeDefinitionData(D, *DD);
+ MergeDefinitionData(D, std::move(*DD));
} else {
Canon->DefinitionData = DD;
D->DefinitionData = Canon->DefinitionData;
@@ -1535,7 +1609,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
bool WasDefinition = Record[Idx++];
if (WasDefinition)
- ReadCXXRecordDefinition(D);
+ ReadCXXRecordDefinition(D, /*Update*/false);
else
// Propagate DefinitionData pointer from the canonical declaration.
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
@@ -1576,17 +1650,20 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
if (auto *CD = ReadDeclAs<CXXConstructorDecl>(Record, Idx))
- D->setInheritedConstructor(CD);
+ if (D->isCanonicalDecl())
+ D->setInheritedConstructor(CD->getCanonicalDecl());
D->IsExplicitSpecified = Record[Idx++];
- // FIXME: We should defer loading this until we need the constructor's body.
- std::tie(D->CtorInitializers, D->NumCtorInitializers) =
- Reader.ReadCXXCtorInitializers(F, Record, Idx);
}
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx);
+ if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) {
+ auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!Canon->OperatorDelete)
+ Canon->OperatorDelete = OperatorDelete;
+ }
}
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
@@ -1690,36 +1767,34 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
return Redecl;
}
+static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
+ SmallVectorImpl<DeclID> &IDs) {
+ assert(!IDs.empty() && "no IDs to add to list");
+ if (Old) {
+ IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+ std::sort(IDs.begin(), IDs.end());
+ IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
+ }
+
+ auto *Result = new (Context) DeclID[1 + IDs.size()];
+ *Result = IDs.size();
+ std::copy(IDs.begin(), IDs.end(), Result + 1);
+ return Result;
+}
+
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (ThisDeclID == Redecl.getFirstID()) {
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 2> SpecIDs;
- SpecIDs.push_back(0);
-
- // Specializations.
- unsigned Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- // Partial specializations.
- Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- if (SpecIDs[0]) {
- typedef serialization::DeclID DeclID;
-
- // FIXME: Append specializations!
- CommonPtr->LazySpecializations
- = new (Reader.getContext()) DeclID [SpecIDs.size()];
- memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
- SpecIDs.size() * sizeof(DeclID));
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
+
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
@@ -1741,30 +1816,13 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
if (ThisDeclID == Redecl.getFirstID()) {
// This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations.
- SmallVector<serialization::DeclID, 2> SpecIDs;
- SpecIDs.push_back(0);
-
- // Specializations.
- unsigned Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- // Partial specializations.
- Size = Record[Idx++];
- SpecIDs[0] += Size;
- for (unsigned I = 0; I != Size; ++I)
- SpecIDs.push_back(ReadDeclID(Record, Idx));
-
- VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- if (SpecIDs[0]) {
- typedef serialization::DeclID DeclID;
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
- // FIXME: Append specializations!
- CommonPtr->LazySpecializations =
- new (Reader.getContext()) DeclID[SpecIDs.size()];
- memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
- SpecIDs.size() * sizeof(DeclID));
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
}
@@ -1823,7 +1881,7 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
// definition.
if (auto *DDD = D->DefinitionData.getNotUpdated()) {
if (auto *CanonDD = CanonSpec->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(CanonSpec, *DDD);
+ MergeDefinitionData(CanonSpec, std::move(*DDD));
Reader.PendingDefinitions.erase(D);
Reader.MergedDeclContexts.insert(
std::make_pair(D, CanonDD->Definition));
@@ -1876,17 +1934,13 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (ThisDeclID == Redecl.getFirstID()) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
+ SmallVector<serialization::DeclID, 32> SpecIDs;
+ ReadDeclIDList(SpecIDs);
- // Read the function specialization declaration IDs. The specializations
- // themselves will be loaded if they're needed.
- if (unsigned NumSpecs = Record[Idx++]) {
- // FIXME: Append specializations!
- FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();
- CommonPtr->LazySpecializations = new (Reader.getContext())
- serialization::DeclID[NumSpecs + 1];
- CommonPtr->LazySpecializations[0] = NumSpecs;
- for (unsigned I = 0; I != NumSpecs; ++I)
- CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx);
+ if (!SpecIDs.empty()) {
+ auto *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = newDeclIDList(
+ Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
}
}
}
@@ -2049,15 +2103,25 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
}
template <typename T>
-ASTDeclReader::RedeclarableResult
+ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
DeclID FirstDeclID = ReadDeclID(Record, Idx);
-
+ Decl *MergeWith = nullptr;
+
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
if (FirstDeclID == 0)
FirstDeclID = ThisDeclID;
-
+ else if (unsigned N = Record[Idx++]) {
+ // 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.
+ // FIXME: Provide a known merge target to the second and subsequent such
+ // declaration.
+ for (unsigned I = 0; I != N; ++I)
+ MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+ }
+
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
if (FirstDecl != D) {
// We delay loading of the redeclaration chain to avoid deeply nested calls.
@@ -2065,6 +2129,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// which is the one that matters and mark the real previous DeclID to be
// loaded & attached later on.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
+ D->First = FirstDecl->getCanonicalDecl();
}
// Note that this declaration has been deserialized.
@@ -2072,7 +2137,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,
+ return RedeclarableResult(Reader, FirstDeclID, MergeWith,
static_cast<T *>(D)->getKind());
}
@@ -2083,23 +2148,19 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
RedeclarableResult &Redecl,
DeclID TemplatePatternID) {
T *D = static_cast<T*>(DBase);
- T *DCanon = D->getCanonicalDecl();
- if (D != DCanon &&
- // IDs < NUM_PREDEF_DECL_IDS are not loaded from an AST file.
- Redecl.getFirstID() >= NUM_PREDEF_DECL_IDS &&
- (!Reader.getContext().getLangOpts().Modules ||
- Reader.getOwningModuleFile(DCanon) == Reader.getOwningModuleFile(D))) {
- // All redeclarations between this declaration and its originally-canonical
- // declaration get pulled in when we load DCanon; we don't need to
- // perform any more merging now.
- Redecl.suppress();
- }
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
- if (FindExistingResult ExistingRes = findExisting(D))
+ // If we're not the canonical declaration, we don't need to merge.
+ if (!DBase->isFirstDecl())
+ return;
+
+ if (auto *Existing = Redecl.getKnownMergeTarget())
+ // We already know of an existing declaration we should merge with.
+ mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
+ else if (FindExistingResult ExistingRes = findExisting(D))
if (T *Existing = ExistingRes)
mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
}
@@ -2120,7 +2181,8 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(),
- DPattern->getKind());
+ /*MergeWith*/ExistingPattern, DPattern->getKind());
+
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
// FIXME: This is duplicated in several places. Refactor.
@@ -2128,13 +2190,14 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) {
- MergeDefinitionData(ExistingClass, *DDD);
+ MergeDefinitionData(ExistingClass, std::move(*DDD));
Reader.PendingDefinitions.erase(DClass);
Reader.MergedDeclContexts.insert(
std::make_pair(DClass, ExistingDD->Definition));
DClass->IsCompleteDefinition = false;
} else {
ExistingClass->DefinitionData = DClass->DefinitionData;
+ Reader.PendingDefinitions.insert(DClass);
}
}
DClass->DefinitionData = ExistingClass->DefinitionData;
@@ -2163,14 +2226,18 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
T *ExistingCanon = Existing->getCanonicalDecl();
T *DCanon = D->getCanonicalDecl();
if (ExistingCanon != DCanon) {
- assert(DCanon->getGlobalID() == Redecl.getFirstID());
+ assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
+ "already merged this declaration");
// Have our redeclaration link point back at the canonical declaration
// of the existing declaration, so that this declaration has the
// appropriate canonical declaration.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
+ D->First = ExistingCanon;
// When we merge a namespace, update its pointer to the first namespace.
+ // We cannot have loaded any redeclarations of this declaration yet, so
+ // there's nothing else that needs to be updated.
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
assert_cast<NamespaceDecl*>(ExistingCanon));
@@ -2181,14 +2248,11 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
TemplatePatternID);
- // If this declaration was the canonical declaration, make a note of
- // that. We accept the linear algorithm here because the number of
- // unique canonical declarations of an entity should always be tiny.
+ // If this declaration was the canonical declaration, make a note of that.
if (DCanon == D) {
- SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
- if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
- == Merged.end())
- Merged.push_back(Redecl.getFirstID());
+ Reader.MergedDecls[ExistingCanon].push_back(Redecl.getFirstID());
+ if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
+ Reader.PendingDeclChains.push_back(ExistingCanon);
}
}
}
@@ -2529,42 +2593,71 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
/// Find the context in which we should search for previous declarations when
/// looking for declarations to merge.
-static DeclContext *getPrimaryContextForMerging(DeclContext *DC) {
+DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
+ DeclContext *DC) {
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
return ND->getOriginalNamespace();
- // There is one tricky case here: if DC is a class with no definition, then
- // we're merging a declaration whose definition is added by an update record,
- // but we've not yet loaded that update record. In this case, we use the
- // canonical declaration for merging until we get a real definition.
- // FIXME: When we add a definition, we may need to move the partial lookup
- // information from the canonical declaration onto the chosen definition.
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
- return RD->getPrimaryContext();
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ // Try to dig out the definition.
+ auto *DD = RD->DefinitionData.getNotUpdated();
+ if (!DD)
+ DD = RD->getCanonicalDecl()->DefinitionData.getNotUpdated();
+
+ // If there's no definition yet, then DC's definition is added by an update
+ // record, but we've not yet loaded that update record. In this case, we
+ // commit to DC being the canonical definition now, and will fix this when
+ // we load the update record.
+ if (!DD) {
+ DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD);
+ RD->IsCompleteDefinition = true;
+ RD->DefinitionData = DD;
+ RD->getCanonicalDecl()->DefinitionData = DD;
+
+ // Track that we did this horrible thing so that we can fix it later.
+ Reader.PendingFakeDefinitionData.insert(
+ std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
+ }
+
+ return DD->Definition;
+ }
if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
: nullptr;
+ // We can see the TU here only if we have no Sema object. In that case,
+ // there's no TU scope to look in, so using the DC alone is sufficient.
+ if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
+ return TU;
+
return nullptr;
}
ASTDeclReader::FindExistingResult::~FindExistingResult() {
+ // Record that we had a typedef name for linkage whether or not we merge
+ // with that declaration.
+ if (TypedefNameForLinkage) {
+ DeclContext *DC = New->getDeclContext()->getRedeclContext();
+ Reader.ImportedTypedefNamesForLinkage.insert(
+ std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
+ return;
+ }
+
if (!AddResult || Existing)
return;
DeclarationName Name = New->getDeclName();
DeclContext *DC = New->getDeclContext()->getRedeclContext();
- if (TypedefNameForLinkage) {
- Reader.ImportedTypedefNamesForLinkage.insert(
- std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
- } else if (!Name) {
- assert(needsAnonymousDeclarationNumber(New));
+ if (needsAnonymousDeclarationNumber(New)) {
setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
AnonymousDeclNumber, New);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
- Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name);
- } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
+ if (Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name))
+ Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()]
+ .push_back(New);
+ } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
// Add the declaration to its redeclaration context so later merging
// lookups will find it.
MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true);
@@ -2582,12 +2675,11 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
// If we found a typedef declaration that gives a name to some other
// declaration, then we want that inner declaration. Declarations from
// AST files are handled via ImportedTypedefNamesForLinkage.
- if (Found->isFromASTFile()) return 0;
- if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) {
- if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>())
- if (TT->getDecl()->getTypedefNameForAnonDecl() == TND)
- return TT->getDecl();
- }
+ if (Found->isFromASTFile())
+ return 0;
+
+ if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
+ return TND->getAnonDeclWithTypedefName();
return 0;
}
@@ -2608,17 +2700,12 @@ NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
// If this is the first time, but we have parsed a declaration of the context,
// build the anonymous declaration list from the parsed declaration.
if (!cast<Decl>(DC)->isFromASTFile()) {
- unsigned Index = 0;
- for (Decl *LexicalD : DC->decls()) {
- auto *ND = dyn_cast<NamedDecl>(LexicalD);
- if (!ND || !needsAnonymousDeclarationNumber(ND))
- continue;
- if (Previous.size() == Index)
+ numberAnonymousDeclsWithin(DC, [&](NamedDecl *ND, unsigned Number) {
+ if (Previous.size() == Number)
Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
else
- Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl());
- ++Index;
- }
+ Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl());
+ });
}
return Index < Previous.size() ? Previous[Index] : nullptr;
@@ -2646,8 +2733,6 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// unmergeable contexts.
FindExistingResult Result(Reader, D, /*Existing=*/nullptr,
AnonymousDeclNumber, TypedefNameForLinkage);
- // FIXME: We may still need to pull in the redeclaration chain; there can
- // be redeclarations via 'decltype'.
Result.suppress();
return Result;
}
@@ -2667,16 +2752,16 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
// was not imported.
}
- if (!Name) {
+ if (needsAnonymousDeclarationNumber(D)) {
// This is an anonymous declaration that we may need to merge. Look it up
// in its context by number.
- assert(needsAnonymousDeclarationNumber(D));
if (auto *Existing = getAnonymousDeclForMerging(
Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
if (isSameEntity(Existing, D))
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
- } else if (DC->isTranslationUnit() && Reader.SemaObj) {
+ } else if (DC->isTranslationUnit() && Reader.SemaObj &&
+ !Reader.getContext().getLangOpts().CPlusPlus) {
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
// Temporarily consider the identifier to be up-to-date. We don't want to
@@ -2710,7 +2795,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
TypedefNameForLinkage);
}
- } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
+ } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
@@ -2738,20 +2823,47 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
}
template<typename DeclT>
+Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) {
+ return D->RedeclLink.getLatestNotUpdated();
+}
+Decl *ASTDeclReader::getMostRecentDeclImpl(...) {
+ llvm_unreachable("getMostRecentDecl on non-redeclarable declaration");
+}
+
+Decl *ASTDeclReader::getMostRecentDecl(Decl *D) {
+ assert(D);
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(TYPE)
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ return getMostRecentDeclImpl(cast<TYPE##Decl>(D));
+#include "clang/AST/DeclNodes.inc"
+ }
+ llvm_unreachable("unknown decl kind");
+}
+
+Decl *ASTReader::getMostRecentExistingDecl(Decl *D) {
+ return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl());
+}
+
+template<typename DeclT>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<DeclT> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
D->RedeclLink.setPrevious(cast<DeclT>(Previous));
+ D->First = cast<DeclT>(Previous)->First;
}
namespace clang {
template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
FunctionDecl *FD = static_cast<FunctionDecl*>(D);
FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
FD->RedeclLink.setPrevious(PrevFD);
+ FD->First = PrevFD->First;
// If the previous declaration is an inline function declaration, then this
// declaration is too.
@@ -2774,16 +2886,17 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
FD->IsInline = true;
}
- // If this declaration has an unresolved exception specification but the
- // previous declaration had a resolved one, resolve the exception
- // specification now.
+ // If we need to propagate an exception specification along the redecl
+ // chain, make a note of that so that we can do so later.
auto *FPT = FD->getType()->getAs<FunctionProtoType>();
auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
- if (FPT && PrevFPT &&
- isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
- !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) {
- Reader.Context.adjustExceptionSpec(
- FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
+ if (FPT && PrevFPT) {
+ bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
+ bool WasUnresolved =
+ isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
+ if (IsUnresolved != WasUnresolved)
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(Canon, IsUnresolved ? PrevFD : FD));
}
}
}
@@ -2792,14 +2905,14 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
}
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
- Decl *Previous) {
+ Decl *Previous, Decl *Canon) {
assert(D && Previous);
switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
-#define DECL(TYPE, BASE) \
- case Decl::TYPE: \
- attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous); \
+#define DECL(TYPE, BASE) \
+ case Decl::TYPE: \
+ attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \
break;
#include "clang/AST/DeclNodes.inc"
}
@@ -2859,29 +2972,6 @@ void ASTReader::markIncompleteDeclChain(Decl *D) {
}
}
-ASTReader::MergedDeclsMap::iterator
-ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) {
- // If we don't have any stored merged declarations, just look in the
- // merged declarations set.
- StoredMergedDeclsMap::iterator StoredPos = StoredMergedDecls.find(CanonID);
- if (StoredPos == StoredMergedDecls.end())
- return MergedDecls.find(Canon);
-
- // Append the stored merged declarations to the merged declarations set.
- MergedDeclsMap::iterator Pos = MergedDecls.find(Canon);
- if (Pos == MergedDecls.end())
- Pos = MergedDecls.insert(std::make_pair(Canon,
- SmallVector<DeclID, 2>())).first;
- Pos->second.append(StoredPos->second.begin(), StoredPos->second.end());
- StoredMergedDecls.erase(StoredPos);
-
- // Sort and uniquify the set of merged declarations.
- llvm::array_pod_sort(Pos->second.begin(), Pos->second.end());
- Pos->second.erase(std::unique(Pos->second.begin(), Pos->second.end()),
- Pos->second.end());
- return Pos;
-}
-
/// \brief Read the declaration at the given offset from the AST file.
Decl *ASTReader::ReadDeclRecord(DeclID ID) {
unsigned Index = ID - NUM_PREDEF_DECL_IDS;
@@ -3086,6 +3176,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
return nullptr;
+ case DECL_CXX_CTOR_INITIALIZERS:
+ Error("attempt to read a C++ ctor initializer record as a declaration");
+ return nullptr;
case DECL_IMPORT:
// Note: last entry of the ImportDecl record is the number of stored source
// locations.
@@ -3199,47 +3292,55 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
}
namespace {
- /// \brief Module visitor class that finds all of the redeclarations of a
- ///
+ /// \brief Module visitor class that finds all of the redeclarations of a
+ /// redeclarable declaration.
class RedeclChainVisitor {
ASTReader &Reader;
SmallVectorImpl<DeclID> &SearchDecls;
llvm::SmallPtrSetImpl<Decl *> &Deserialized;
GlobalDeclID CanonID;
SmallVector<Decl *, 4> Chain;
-
+
public:
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID> &SearchDecls,
llvm::SmallPtrSetImpl<Decl *> &Deserialized,
GlobalDeclID CanonID)
: Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
- CanonID(CanonID) {
- for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
- addToChain(Reader.GetDecl(SearchDecls[I]));
+ CanonID(CanonID) {
+ // Ensure that the canonical ID goes at the start of the chain.
+ addToChain(Reader.GetDecl(CanonID));
}
-
- static bool visit(ModuleFile &M, bool Preorder, void *UserData) {
- if (Preorder)
- return false;
-
- return static_cast<RedeclChainVisitor *>(UserData)->visit(M);
+
+ static ModuleManager::DFSPreorderControl
+ visitPreorder(ModuleFile &M, void *UserData) {
+ return static_cast<RedeclChainVisitor *>(UserData)->visitPreorder(M);
}
-
+
+ static bool visitPostorder(ModuleFile &M, void *UserData) {
+ return static_cast<RedeclChainVisitor *>(UserData)->visitPostorder(M);
+ }
+
void addToChain(Decl *D) {
if (!D)
return;
-
+
if (Deserialized.erase(D))
Chain.push_back(D);
}
-
+
void searchForID(ModuleFile &M, GlobalDeclID GlobalID) {
// Map global ID of the first declaration down to the local ID
// used in this module file.
DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
if (!ID)
return;
-
+
+ // If the search decl was from this module, add it to the chain before any
+ // of its redeclarations in this module or users of it, and after any from
+ // imported modules.
+ if (CanonID != GlobalID && Reader.isDeclIDFromModule(GlobalID, M))
+ addToChain(Reader.GetDecl(GlobalID));
+
// Perform a binary search to find the local redeclarations for this
// declaration (if any).
const LocalRedeclarationsInfo Compare = { ID, 0 };
@@ -3269,8 +3370,36 @@ namespace {
for (unsigned I = 0; I != N; ++I)
addToChain(Reader.GetLocalDecl(M, M.RedeclarationChains[Offset++]));
}
-
- bool visit(ModuleFile &M) {
+
+ bool needsToVisitImports(ModuleFile &M, GlobalDeclID GlobalID) {
+ DeclID ID = Reader.mapGlobalIDToModuleFileGlobalID(M, GlobalID);
+ if (!ID)
+ return false;
+
+ const LocalRedeclarationsInfo Compare = {ID, 0};
+ const LocalRedeclarationsInfo *Result = std::lower_bound(
+ M.RedeclarationsMap,
+ M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
+ if (Result == M.RedeclarationsMap + M.LocalNumRedeclarationsInMap ||
+ Result->FirstID != ID) {
+ return true;
+ }
+ unsigned Offset = Result->Offset;
+ unsigned N = M.RedeclarationChains[Offset];
+ // We don't need to visit a module or any of its imports if we've already
+ // deserialized the redecls from this module.
+ return N != 0;
+ }
+
+ ModuleManager::DFSPreorderControl visitPreorder(ModuleFile &M) {
+ for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I) {
+ if (needsToVisitImports(M, SearchDecls[I]))
+ return ModuleManager::Continue;
+ }
+ return ModuleManager::SkipImports;
+ }
+
+ bool visitPostorder(ModuleFile &M) {
// Visit each of the declarations.
for (unsigned I = 0, N = SearchDecls.size(); I != N; ++I)
searchForID(M, SearchDecls[I]);
@@ -3285,41 +3414,46 @@ namespace {
};
}
-void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) {
- Decl *D = GetDecl(ID);
- Decl *CanonDecl = D->getCanonicalDecl();
-
+void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
+ // The decl might have been merged into something else after being added to
+ // our list. If it was, just skip it.
+ if (!CanonDecl->isCanonicalDecl())
+ return;
+
// Determine the set of declaration IDs we'll be searching for.
- SmallVector<DeclID, 1> SearchDecls;
- GlobalDeclID CanonID = 0;
- if (D == CanonDecl) {
- SearchDecls.push_back(ID); // Always first.
- CanonID = ID;
- }
- MergedDeclsMap::iterator MergedPos = combineStoredMergedDecls(CanonDecl, ID);
+ SmallVector<DeclID, 16> SearchDecls;
+ 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());
-
+
// Build up the list of redeclarations.
RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
- ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visit, &Visitor);
-
+ ModuleMgr.visitDepthFirst(&RedeclChainVisitor::visitPreorder,
+ &RedeclChainVisitor::visitPostorder, &Visitor);
+
// Retrieve the chains.
ArrayRef<Decl *> Chain = Visitor.getChain();
- if (Chain.empty())
+ if (Chain.empty() || (Chain.size() == 1 && Chain[0] == CanonDecl))
return;
-
+
// Hook up the chains.
- Decl *MostRecent = CanonDecl->getMostRecentDecl();
+ //
+ // FIXME: We have three different dispatches on decl kind here; maybe
+ // we should instead generate one loop per kind and dispatch up-front?
+ Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
+ if (!MostRecent)
+ MostRecent = CanonDecl;
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
if (Chain[I] == CanonDecl)
continue;
- ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent);
+ ASTDeclReader::attachPreviousDecl(*this, Chain[I], MostRecent, CanonDecl);
MostRecent = Chain[I];
}
-
- ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
+ ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
}
namespace {
@@ -3513,13 +3647,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
while (Idx < Record.size()) {
switch ((DeclUpdateKind)Record[Idx++]) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+ auto *RD = cast<CXXRecordDecl>(D);
// FIXME: If we also have an update record for instantiating the
// definition of D, we need that to happen before we get here.
Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
assert(MD && "couldn't read decl from update record");
// FIXME: We should call addHiddenDecl instead, to add the member
// to its DeclContext.
- cast<CXXRecordDecl>(D)->addedMember(MD);
+ RD->addedMember(MD);
+
+ // If we've added a new special member to a class definition that is not
+ // the canonical definition, then we need special member lookups in the
+ // canonical definition to also look into our class.
+ auto *DD = RD->DefinitionData.getNotUpdated();
+ if (DD && DD->Definition != RD) {
+ auto &Merged = Reader.MergedLookups[DD->Definition];
+ // FIXME: Avoid the linear-time scan here.
+ if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end())
+ Merged.push_back(RD);
+ }
break;
}
@@ -3567,13 +3713,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
});
}
FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
- if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
- std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
- Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
- if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
- // FIXME: Check consistency.
- DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile,
- Record, Idx));
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ CD->NumCtorInitializers = Record[Idx++];
+ if (CD->NumCtorInitializers)
+ CD->CtorInitializers =
+ Reader.ReadCXXCtorInitializersRef(F, Record, Idx);
+ }
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
@@ -3583,16 +3728,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
- bool HadDefinition = RD->getDefinition();
- ReadCXXRecordDefinition(RD);
+ auto *OldDD = RD->DefinitionData.getNotUpdated();
+ bool HadRealDefinition =
+ OldDD && (OldDD->Definition != RD ||
+ !Reader.PendingFakeDefinitionData.count(OldDD));
+ ReadCXXRecordDefinition(RD, /*Update*/true);
+
// Visible update is handled separately.
uint64_t LexicalOffset = Record[Idx++];
- if (!HadDefinition && LexicalOffset) {
+ if (!HadRealDefinition && LexicalOffset) {
RD->setHasExternalLexicalStorage(true);
Reader.ReadDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
- std::make_pair(LexicalOffset, 0),
- ModuleFile.DeclContextInfos[RD]);
- Reader.PendingDefinitions.insert(RD);
+ std::make_pair(LexicalOffset, 0),
+ ModuleFile.DeclContextInfos[RD]);
+ Reader.PendingFakeDefinitionData.erase(OldDD);
}
auto TSK = (TemplateSpecializationKind)Record[Idx++];
@@ -3636,24 +3785,36 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
break;
}
+ case UPD_CXX_RESOLVED_DTOR_DELETE: {
+ // Set the 'operator delete' directly to avoid emitting another update
+ // record.
+ auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
+ // FIXME: Check consistency if we have an old and new operator delete.
+ if (!First->OperatorDelete)
+ First->OperatorDelete = Del;
+ break;
+ }
+
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
- // FIXME: This doesn't send the right notifications if there are
- // ASTMutationListeners other than an ASTWriter.
FunctionProtoType::ExceptionSpecInfo ESI;
SmallVector<QualType, 8> ExceptionStorage;
Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
- for (auto *Redecl : merged_redecls(D)) {
- auto *FD = cast<FunctionDecl>(Redecl);
- auto *FPT = FD->getType()->castAs<FunctionProtoType>();
- if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
- // AST invariant: if any exception spec in the redecl chain is
- // resolved, all are resolved. We don't need to go any further.
- // FIXME: If the exception spec is resolved, check that it matches.
- break;
- }
+
+ // Update this declaration's exception specification, if needed.
+ auto *FD = cast<FunctionDecl>(D);
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ // FIXME: If the exception specification is already present, check that it
+ // matches.
+ if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
FD->setType(Reader.Context.getFunctionType(
FPT->getReturnType(), FPT->getParamTypes(),
FPT->getExtProtoInfo().withExceptionSpec(ESI)));
+
+ // When we get to the end of deserializing, see if there are other decls
+ // that we need to propagate this exception specification onto.
+ Reader.PendingExceptionSpecUpdates.insert(
+ std::make_pair(FD->getCanonicalDecl(), FD));
}
break;
}
@@ -3685,10 +3846,30 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_STATIC_LOCAL_NUMBER:
Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
break;
+
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
Reader.Context, ReadSourceRange(Record, Idx)));
break;
+
+ case UPD_DECL_EXPORTED:
+ unsigned SubmoduleID = readSubmoduleID(Record, Idx);
+ Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
+ if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
+ // FIXME: This doesn't send the right notifications if there are
+ // ASTMutationListeners other than an ASTWriter.
+ Reader.getContext().mergeDefinitionIntoModule(cast<NamedDecl>(D), Owner,
+ /*NotifyListeners*/false);
+ Reader.PendingMergedDefinitionsToDeduplicate.insert(cast<NamedDecl>(D));
+ } else if (Owner && Owner->NameVisibility != Module::AllVisible) {
+ // If Owner is made visible at some later point, make this declaration
+ // visible too.
+ Reader.HiddenNamesMap[Owner].push_back(D);
+ } else {
+ // The declaration is now visible.
+ D->Hidden = false;
+ }
+ break;
}
}
}