|
|
|
@ -291,7 +291,11 @@ namespace clang {
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
|
|
|
|
RedeclarableResult &Redecl);
|
|
|
|
|
|
|
|
|
|
// FIXME: Reorder according to DeclNodes.td?
|
|
|
|
|
void VisitObjCMethodDecl(ObjCMethodDecl *D);
|
|
|
|
|
void VisitObjCContainerDecl(ObjCContainerDecl *D);
|
|
|
|
@ -363,9 +367,11 @@ void ASTDeclReader::VisitDecl(Decl *D) {
|
|
|
|
|
} else {
|
|
|
|
|
DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
|
|
|
|
|
DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx);
|
|
|
|
|
DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
|
|
|
|
|
// Avoid calling setLexicalDeclContext() directly because it uses
|
|
|
|
|
// Decl::getASTContext() internally which is unsafe during derialization.
|
|
|
|
|
D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext());
|
|
|
|
|
D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC,
|
|
|
|
|
Reader.getContext());
|
|
|
|
|
}
|
|
|
|
|
D->setLocation(Reader.ReadSourceLocation(F, RawLocation));
|
|
|
|
|
D->setInvalidDecl(Record[Idx++]);
|
|
|
|
@ -1230,7 +1236,8 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
|
|
|
|
RedeclarableResult Redecl = VisitRecordDeclImpl(D);
|
|
|
|
|
|
|
|
|
|
ASTContext &C = Reader.getContext();
|
|
|
|
|
if (Record[Idx++]) {
|
|
|
|
|
bool WasDefinition = Record[Idx++];
|
|
|
|
|
if (WasDefinition) {
|
|
|
|
|
// Determine whether this is a lambda closure type, so that we can
|
|
|
|
|
// allocate the appropriate DefinitionData structure.
|
|
|
|
|
bool IsLambda = Record[Idx++];
|
|
|
|
@ -1239,21 +1246,34 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
|
|
|
|
false);
|
|
|
|
|
else
|
|
|
|
|
D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
|
|
|
|
|
|
|
|
|
|
// Propagate the DefinitionData pointer to the canonical declaration, so
|
|
|
|
|
// that all other deserialized declarations will see it.
|
|
|
|
|
// FIXME: Complain if there already is a DefinitionData!
|
|
|
|
|
D->getCanonicalDecl()->DefinitionData = D->DefinitionData;
|
|
|
|
|
|
|
|
|
|
ReadCXXDefinitionData(*D->DefinitionData, Record, Idx);
|
|
|
|
|
|
|
|
|
|
// Note that we have deserialized a definition. Any declarations
|
|
|
|
|
// deserialized before this one will be be given the DefinitionData pointer
|
|
|
|
|
// at the end.
|
|
|
|
|
Reader.PendingDefinitions.insert(D);
|
|
|
|
|
CXXRecordDecl *Canon = D->getCanonicalDecl();
|
|
|
|
|
if (Canon == D) {
|
|
|
|
|
// Nothing to do.
|
|
|
|
|
} else if (!Canon->DefinitionData) {
|
|
|
|
|
Canon->DefinitionData = D->DefinitionData;
|
|
|
|
|
|
|
|
|
|
// Note that we have deserialized a definition. Any declarations
|
|
|
|
|
// deserialized before this one will be be given the DefinitionData
|
|
|
|
|
// pointer at the end.
|
|
|
|
|
Reader.PendingDefinitions.insert(D);
|
|
|
|
|
} else {
|
|
|
|
|
// We have already deserialized a definition of this record. This
|
|
|
|
|
// definition is no longer really a definition. Note that the pre-existing
|
|
|
|
|
// definition is the *real* definition.
|
|
|
|
|
// FIXME: Check DefinitionData for consistency with prior definition.
|
|
|
|
|
Reader.MergedDeclContexts.insert(
|
|
|
|
|
std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition));
|
|
|
|
|
D->IsCompleteDefinition = false;
|
|
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Propagate DefinitionData pointer from the canonical declaration.
|
|
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
|
|
|
|
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum CXXRecKind {
|
|
|
|
@ -1278,8 +1298,9 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
|
|
|
|
|
|
|
|
|
// Lazily load the key function to avoid deserializing every method so we can
|
|
|
|
|
// compute it.
|
|
|
|
|
if (D->IsCompleteDefinition) {
|
|
|
|
|
if (DeclID KeyFn = ReadDeclID(Record, Idx))
|
|
|
|
|
if (WasDefinition) {
|
|
|
|
|
DeclID KeyFn = ReadDeclID(Record, Idx);
|
|
|
|
|
if (KeyFn && D->IsCompleteDefinition)
|
|
|
|
|
C.KeyFunctions[D] = KeyFn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1502,16 +1523,6 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Explicit info.
|
|
|
|
|
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
|
|
|
|
|
ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
|
|
|
|
|
= new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
|
|
|
|
|
ExplicitInfo->TypeAsWritten = TyInfo;
|
|
|
|
|
ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
D->ExplicitInfo = ExplicitInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SmallVector<TemplateArgument, 8> TemplArgs;
|
|
|
|
|
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
|
|
|
|
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
|
|
|
|
@ -1523,16 +1534,48 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|
|
|
|
if (writtenAsCanonicalDecl) {
|
|
|
|
|
ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx);
|
|
|
|
|
if (D->isCanonicalDecl()) { // It's kept in the folding set.
|
|
|
|
|
// Set this as, or find, the canonical declaration for this specialization
|
|
|
|
|
ClassTemplateSpecializationDecl *CanonSpec;
|
|
|
|
|
if (ClassTemplatePartialSpecializationDecl *Partial =
|
|
|
|
|
dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
|
|
|
|
|
CanonPattern->getCommonPtr()->PartialSpecializations
|
|
|
|
|
CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations
|
|
|
|
|
.GetOrInsertNode(Partial);
|
|
|
|
|
} else {
|
|
|
|
|
CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
|
|
|
|
|
CanonSpec =
|
|
|
|
|
CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
|
|
|
|
|
}
|
|
|
|
|
// If there was already a canonical specialization, merge into it.
|
|
|
|
|
if (CanonSpec != D) {
|
|
|
|
|
mergeRedeclarable<TagDecl>(D, CanonSpec, Redecl);
|
|
|
|
|
|
|
|
|
|
// This declaration might be a definition. Merge with any existing
|
|
|
|
|
// definition.
|
|
|
|
|
if (D->DefinitionData) {
|
|
|
|
|
if (!CanonSpec->DefinitionData) {
|
|
|
|
|
CanonSpec->DefinitionData = D->DefinitionData;
|
|
|
|
|
} else {
|
|
|
|
|
// FIXME: Check DefinitionData for consistency with prior definition
|
|
|
|
|
Reader.PendingDefinitions.erase(D);
|
|
|
|
|
Reader.MergedDeclContexts.insert(
|
|
|
|
|
std::make_pair(D, CanonSpec->DefinitionData->Definition));
|
|
|
|
|
D->IsCompleteDefinition = false;
|
|
|
|
|
D->DefinitionData = CanonSpec->DefinitionData;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Explicit info.
|
|
|
|
|
if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
|
|
|
|
|
ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
|
|
|
|
|
= new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
|
|
|
|
|
ExplicitInfo->TypeAsWritten = TyInfo;
|
|
|
|
|
ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
|
|
|
|
|
D->ExplicitInfo = ExplicitInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Redecl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1765,59 +1808,65 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
|
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
|
/// of the same entity.
|
|
|
|
|
template<typename T>
|
|
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
|
|
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D,
|
|
|
|
|
RedeclarableResult &Redecl) {
|
|
|
|
|
// If modules are not available, there is no reason to perform this merge.
|
|
|
|
|
if (!Reader.getContext().getLangOpts().Modules)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) {
|
|
|
|
|
if (T *Existing = ExistingRes) {
|
|
|
|
|
T *ExistingCanon = Existing->getCanonicalDecl();
|
|
|
|
|
T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
|
|
|
|
|
if (ExistingCanon != DCanon) {
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
// When we merge a namespace, update its pointer to the first namespace.
|
|
|
|
|
if (NamespaceDecl *Namespace
|
|
|
|
|
= dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
|
|
|
|
|
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
|
|
|
|
|
static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't introduce DCanon into the set of pending declaration chains.
|
|
|
|
|
Redecl.suppress();
|
|
|
|
|
|
|
|
|
|
// Introduce ExistingCanon into the set of pending declaration chains,
|
|
|
|
|
// if in fact it came from a module file.
|
|
|
|
|
if (ExistingCanon->isFromASTFile()) {
|
|
|
|
|
GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
|
|
|
|
|
assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
|
|
|
|
|
if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
|
|
|
|
|
Reader.PendingDeclChains.push_back(ExistingCanonID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this declaration was the canonical declaration, make a note of
|
|
|
|
|
// that. We accept the linear algorithm here because the number of
|
|
|
|
|
// unique canonical declarations of an entity should always be tiny.
|
|
|
|
|
if (DCanon == static_cast<T*>(D)) {
|
|
|
|
|
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
|
|
|
|
|
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
|
|
|
|
|
== Merged.end())
|
|
|
|
|
Merged.push_back(Redecl.getFirstID());
|
|
|
|
|
|
|
|
|
|
// If ExistingCanon did not come from a module file, introduce the
|
|
|
|
|
// first declaration that *does* come from a module file to the
|
|
|
|
|
// set of pending declaration chains, so that we merge this
|
|
|
|
|
// declaration.
|
|
|
|
|
if (!ExistingCanon->isFromASTFile() &&
|
|
|
|
|
Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
|
|
|
|
|
Reader.PendingDeclChains.push_back(Merged[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
|
|
|
|
|
if (T *Existing = ExistingRes)
|
|
|
|
|
mergeRedeclarable(D, Existing, Redecl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// \brief Attempts to merge the given declaration (D) with another declaration
|
|
|
|
|
/// of the same entity.
|
|
|
|
|
template<typename T>
|
|
|
|
|
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing,
|
|
|
|
|
RedeclarableResult &Redecl) {
|
|
|
|
|
T *ExistingCanon = Existing->getCanonicalDecl();
|
|
|
|
|
T *DCanon = static_cast<T*>(D)->getCanonicalDecl();
|
|
|
|
|
if (ExistingCanon != DCanon) {
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
// When we merge a namespace, update its pointer to the first namespace.
|
|
|
|
|
if (NamespaceDecl *Namespace
|
|
|
|
|
= dyn_cast<NamespaceDecl>(static_cast<T*>(D))) {
|
|
|
|
|
Namespace->AnonOrFirstNamespaceAndInline.setPointer(
|
|
|
|
|
static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't introduce DCanon into the set of pending declaration chains.
|
|
|
|
|
Redecl.suppress();
|
|
|
|
|
|
|
|
|
|
// Introduce ExistingCanon into the set of pending declaration chains,
|
|
|
|
|
// if in fact it came from a module file.
|
|
|
|
|
if (ExistingCanon->isFromASTFile()) {
|
|
|
|
|
GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID();
|
|
|
|
|
assert(ExistingCanonID && "Unrecorded canonical declaration ID?");
|
|
|
|
|
if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID))
|
|
|
|
|
Reader.PendingDeclChains.push_back(ExistingCanonID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this declaration was the canonical declaration, make a note of
|
|
|
|
|
// that. We accept the linear algorithm here because the number of
|
|
|
|
|
// unique canonical declarations of an entity should always be tiny.
|
|
|
|
|
if (DCanon == static_cast<T*>(D)) {
|
|
|
|
|
SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon];
|
|
|
|
|
if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID())
|
|
|
|
|
== Merged.end())
|
|
|
|
|
Merged.push_back(Redecl.getFirstID());
|
|
|
|
|
|
|
|
|
|
// If ExistingCanon did not come from a module file, introduce the
|
|
|
|
|
// first declaration that *does* come from a module file to the
|
|
|
|
|
// set of pending declaration chains, so that we merge this
|
|
|
|
|
// declaration.
|
|
|
|
|
if (!ExistingCanon->isFromASTFile() &&
|
|
|
|
|
Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID()))
|
|
|
|
|
Reader.PendingDeclChains.push_back(Merged[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1992,12 +2041,11 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(X)) {
|
|
|
|
|
// FIXME: Deal with merging of template specializations.
|
|
|
|
|
// For now, don't merge these; we need to check more than just the name to
|
|
|
|
|
// determine if they refer to the same entity.
|
|
|
|
|
// No need to handle these here: we merge them when adding them to the
|
|
|
|
|
// template.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Compatible tags match.
|
|
|
|
|
if (TagDecl *TagX = dyn_cast<TagDecl>(X)) {
|
|
|
|
|
TagDecl *TagY = cast<TagDecl>(Y);
|
|
|
|
@ -2044,6 +2092,18 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Find the context in which we should search for previous declarations when
|
|
|
|
|
/// looking for declarations to merge.
|
|
|
|
|
static DeclContext *getPrimaryContextForMerging(DeclContext *DC) {
|
|
|
|
|
if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
|
|
|
|
|
return ND->getOriginalNamespace();
|
|
|
|
|
|
|
|
|
|
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
|
|
|
|
|
return RD->getDefinition();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASTDeclReader::FindExistingResult::~FindExistingResult() {
|
|
|
|
|
if (!AddResult || Existing)
|
|
|
|
|
return;
|
|
|
|
@ -2051,11 +2111,10 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() {
|
|
|
|
|
DeclContext *DC = New->getDeclContext()->getRedeclContext();
|
|
|
|
|
if (DC->isTranslationUnit() && Reader.SemaObj) {
|
|
|
|
|
Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName());
|
|
|
|
|
} else if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
|
|
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
|
|
|
|
|
// Add the declaration to its redeclaration context so later merging
|
|
|
|
|
// lookups will find it.
|
|
|
|
|
NS->getFirstDeclaration()->makeDeclVisibleInContextImpl(New,
|
|
|
|
|
/*Internal*/true);
|
|
|
|
|
MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2069,9 +2128,6 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeclContext *DC = D->getDeclContext()->getRedeclContext();
|
|
|
|
|
if (!DC->isFileContext())
|
|
|
|
|
return FindExistingResult(Reader);
|
|
|
|
|
|
|
|
|
|
if (DC->isTranslationUnit() && Reader.SemaObj) {
|
|
|
|
|
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
|
|
|
|
|
|
|
|
|
@ -2104,15 +2160,17 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
|
|
|
|
if (isSameEntity(*I, D))
|
|
|
|
|
return FindExistingResult(Reader, D, *I);
|
|
|
|
|
}
|
|
|
|
|
} else if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
|
|
|
|
|
DeclContext::lookup_result R = NS->getFirstDeclaration()->noload_lookup(Name);
|
|
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/0);
|
|
|
|
|
} else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
|
|
|
|
|
DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
|
|
|
|
|
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
|
|
|
|
|
if (isSameEntity(*I, D))
|
|
|
|
|
return FindExistingResult(Reader, D, *I);
|
|
|
|
|
}
|
|
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FindExistingResult(Reader, D, /*Existing=*/0);
|
|
|
|
|
|
|
|
|
|
return FindExistingResult(Reader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
|
|
|
|
|