[modules] Number anonymous declarations that are lexically within mergeable
contexts, so that we can merge them when we merge the surrounding context. llvm-svn: 216639
This commit is contained in:
parent
9fc9bf83a8
commit
d08aeb6b57
|
@ -59,6 +59,7 @@ public:
|
|||
CXXLiteralOperatorName,
|
||||
CXXUsingDirective
|
||||
};
|
||||
static const unsigned NumNameKinds = CXXUsingDirective + 1;
|
||||
|
||||
private:
|
||||
/// StoredNameKind - The kind of name that is actually stored in the
|
||||
|
|
|
@ -443,6 +443,11 @@ private:
|
|||
llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*>
|
||||
ImportedTypedefNamesForLinkage;
|
||||
|
||||
/// \brief Mergeable declaration contexts that have anonymous declarations
|
||||
/// within them, and those anonymous declarations.
|
||||
llvm::DenseMap<DeclContext*, llvm::SmallVector<NamedDecl*, 2>>
|
||||
AnonymousDeclarationsForMerging;
|
||||
|
||||
struct FileDeclsInfo {
|
||||
ModuleFile *Mod;
|
||||
ArrayRef<serialization::LocalDeclID> Decls;
|
||||
|
|
|
@ -283,6 +283,10 @@ private:
|
|||
llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID>
|
||||
MacroDefinitions;
|
||||
|
||||
/// \brief Cache of indices of anonymous declarations within their lexical
|
||||
/// contexts.
|
||||
llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers;
|
||||
|
||||
/// An update to a Decl.
|
||||
class DeclUpdate {
|
||||
/// A DeclUpdateKind.
|
||||
|
@ -639,6 +643,7 @@ public:
|
|||
DeclarationName Name, RecordDataImpl &Record);
|
||||
void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
|
||||
RecordDataImpl &Record);
|
||||
unsigned getAnonymousDeclarationNumber(const NamedDecl *D);
|
||||
|
||||
void AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ASTCommon.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||
|
@ -216,3 +217,10 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
|||
|
||||
llvm_unreachable("Unhandled declaration kind");
|
||||
}
|
||||
|
||||
bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
|
||||
if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
|
||||
return false;
|
||||
return isa<TagDecl>(D) || isa<FieldDecl>(D);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,10 @@ const DeclContext *getDefinitiveDeclContext(const DeclContext *DC);
|
|||
/// \brief Determine whether the given declaration kind is redeclarable.
|
||||
bool isRedeclarableDeclKind(unsigned Kind);
|
||||
|
||||
/// \brief Determine whether the given declaration needs an anonymous
|
||||
/// declaration number.
|
||||
bool needsAnonymousDeclarationNumber(const NamedDecl *D);
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} // namespace clang
|
||||
|
|
|
@ -8332,7 +8332,10 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (!Found) {
|
||||
D->setInvalidDecl();
|
||||
// The AST doesn't like TagDecls becoming invalid after they've been
|
||||
// completed. We only really need to mark FieldDecls as invalid here.
|
||||
if (!isa<TagDecl>(D))
|
||||
D->setInvalidDecl();
|
||||
|
||||
std::string CanonDefModule =
|
||||
getOwningModuleNameForDiagnostic(cast<Decl>(CanonDef));
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace clang {
|
|||
const RecordData &Record;
|
||||
unsigned &Idx;
|
||||
TypeID TypeIDForTypeDecl;
|
||||
unsigned AnonymousDeclNumber;
|
||||
|
||||
bool HasPendingBody;
|
||||
|
||||
|
@ -106,6 +107,12 @@ namespace clang {
|
|||
void MergeDefinitionData(CXXRecordDecl *D,
|
||||
struct CXXRecordDecl::DefinitionData &NewDD);
|
||||
|
||||
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
|
||||
DeclContext *DC,
|
||||
unsigned Index);
|
||||
static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
|
||||
unsigned Index, NamedDecl *D);
|
||||
|
||||
/// \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.
|
||||
|
@ -158,37 +165,41 @@ namespace clang {
|
|||
NamedDecl *New;
|
||||
NamedDecl *Existing;
|
||||
mutable bool AddResult;
|
||||
|
||||
unsigned AnonymousDeclNumber;
|
||||
|
||||
void operator=(FindExistingResult&) LLVM_DELETED_FUNCTION;
|
||||
|
||||
|
||||
public:
|
||||
FindExistingResult(ASTReader &Reader)
|
||||
: Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false) {}
|
||||
: Reader(Reader), New(nullptr), Existing(nullptr), AddResult(false),
|
||||
AnonymousDeclNumber(0) {}
|
||||
|
||||
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
|
||||
unsigned AnonymousDeclNumber = 0)
|
||||
: Reader(Reader), New(New), Existing(Existing), AddResult(true),
|
||||
AnonymousDeclNumber(AnonymousDeclNumber) {}
|
||||
|
||||
FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing)
|
||||
: Reader(Reader), New(New), Existing(Existing), AddResult(true) { }
|
||||
|
||||
FindExistingResult(const FindExistingResult &Other)
|
||||
: Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
|
||||
AddResult(Other.AddResult)
|
||||
{
|
||||
: Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
|
||||
AddResult(Other.AddResult),
|
||||
AnonymousDeclNumber(Other.AnonymousDeclNumber) {
|
||||
Other.AddResult = false;
|
||||
}
|
||||
|
||||
|
||||
~FindExistingResult();
|
||||
|
||||
|
||||
/// \brief Suppress the addition of this result into the known set of
|
||||
/// names.
|
||||
void suppress() { AddResult = false; }
|
||||
|
||||
|
||||
operator NamedDecl*() const { return Existing; }
|
||||
|
||||
|
||||
template<typename T>
|
||||
operator T*() const { return dyn_cast_or_null<T>(Existing); }
|
||||
};
|
||||
|
||||
|
||||
FindExistingResult findExisting(NamedDecl *D);
|
||||
|
||||
|
||||
public:
|
||||
ASTDeclReader(ASTReader &Reader, ModuleFile &F,
|
||||
DeclID thisDeclID,
|
||||
|
@ -447,6 +458,8 @@ 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++];
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
|
||||
|
@ -2457,6 +2470,10 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() {
|
|||
if (IsTypedefNameForLinkage) {
|
||||
Reader.ImportedTypedefNamesForLinkage.insert(
|
||||
std::make_pair(std::make_pair(DC, Name.getAsIdentifierInfo()), New));
|
||||
} else if (!Name) {
|
||||
assert(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)) {
|
||||
|
@ -2487,12 +2504,58 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
|
|||
return 0;
|
||||
}
|
||||
|
||||
NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
|
||||
DeclContext *DC,
|
||||
unsigned Index) {
|
||||
// If the lexical context has been merged, look into the now-canonical
|
||||
// definition.
|
||||
if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
|
||||
DC = Merged;
|
||||
|
||||
// If we've seen this before, return the canonical declaration.
|
||||
auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
|
||||
if (Index < Previous.size() && Previous[Index])
|
||||
return Previous[Index];
|
||||
|
||||
// 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)
|
||||
Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
|
||||
else
|
||||
Previous[Index] = cast<NamedDecl>(ND->getCanonicalDecl());
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
|
||||
return Index < Previous.size() ? Previous[Index] : nullptr;
|
||||
}
|
||||
|
||||
void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader,
|
||||
DeclContext *DC, unsigned Index,
|
||||
NamedDecl *D) {
|
||||
if (auto *Merged = Reader.MergedDeclContexts.lookup(DC))
|
||||
DC = Merged;
|
||||
|
||||
auto &Previous = Reader.AnonymousDeclarationsForMerging[DC];
|
||||
if (Index >= Previous.size())
|
||||
Previous.resize(Index + 1);
|
||||
if (!Previous[Index])
|
||||
Previous[Index] = D;
|
||||
}
|
||||
|
||||
ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
||||
bool IsTypedefNameForLinkage = false;
|
||||
DeclarationName Name = getNameForMerging(D, IsTypedefNameForLinkage);
|
||||
|
||||
if (!Name) {
|
||||
// Don't bother trying to find unnamed declarations.
|
||||
if (!Name && !needsAnonymousDeclarationNumber(D)) {
|
||||
// Don't bother trying to find unnamed declarations that are in
|
||||
// unmergeable contexts.
|
||||
FindExistingResult Result(Reader, D, /*Existing=*/nullptr);
|
||||
// FIXME: We may still need to pull in the redeclaration chain; there can
|
||||
// be redeclarations via 'decltype'.
|
||||
|
@ -2513,7 +2576,16 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
|||
// Go on to check in other places in case an existing typedef name
|
||||
// was not imported.
|
||||
}
|
||||
if (DC->isTranslationUnit() && Reader.SemaObj) {
|
||||
|
||||
if (!Name) {
|
||||
// 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);
|
||||
} else if (DC->isTranslationUnit() && Reader.SemaObj) {
|
||||
IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
|
||||
|
||||
// Temporarily consider the identifier to be up-to-date. We don't want to
|
||||
|
@ -2568,7 +2640,8 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
|
|||
MergedDCIt->second == D->getDeclContext())
|
||||
Reader.PendingOdrMergeChecks.push_back(D);
|
||||
|
||||
return FindExistingResult(Reader, D, /*Existing=*/nullptr);
|
||||
return FindExistingResult(Reader, D, /*Existing=*/nullptr,
|
||||
AnonymousDeclNumber);
|
||||
}
|
||||
|
||||
template<typename DeclT>
|
||||
|
|
|
@ -5121,6 +5121,30 @@ void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &Record)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {
|
||||
assert(needsAnonymousDeclarationNumber(D) &&
|
||||
"expected an anonymous declaration");
|
||||
|
||||
// Number the anonymous declarations within this context, if we've not
|
||||
// already done so.
|
||||
auto It = AnonymousDeclarationNumbers.find(D);
|
||||
if (It == AnonymousDeclarationNumbers.end()) {
|
||||
unsigned Index = 0;
|
||||
for (Decl *LexicalD : D->getLexicalDeclContext()->decls()) {
|
||||
auto *ND = dyn_cast<NamedDecl>(LexicalD);
|
||||
if (!ND || !needsAnonymousDeclarationNumber(ND))
|
||||
continue;
|
||||
AnonymousDeclarationNumbers[ND] = Index++;
|
||||
}
|
||||
|
||||
It = AnonymousDeclarationNumbers.find(D);
|
||||
assert(It != AnonymousDeclarationNumbers.end() &&
|
||||
"declaration not found within its lexical context");
|
||||
}
|
||||
|
||||
return It->second;
|
||||
}
|
||||
|
||||
void ASTWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
|
||||
DeclarationName Name, RecordDataImpl &Record) {
|
||||
switch (Name.getNameKind()) {
|
||||
|
|
|
@ -203,6 +203,8 @@ void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
|||
void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
|
||||
VisitDecl(D);
|
||||
Writer.AddDeclarationName(D->getDeclName(), Record);
|
||||
if (needsAnonymousDeclarationNumber(D))
|
||||
Record.push_back(Writer.getAnonymousDeclarationNumber(D));
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
|
||||
|
@ -228,6 +230,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isTopLevelDeclInObjCContainer() &&
|
||||
!D->isModulePrivate() &&
|
||||
!needsAnonymousDeclarationNumber(D) &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
AbbrevToUse = Writer.getDeclTypedefAbbrev();
|
||||
|
||||
|
@ -292,6 +295,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
|
|||
!CXXRecordDecl::classofKind(D->getKind()) &&
|
||||
!D->getIntegerTypeSourceInfo() &&
|
||||
!D->getMemberSpecializationInfo() &&
|
||||
!needsAnonymousDeclarationNumber(D) &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
AbbrevToUse = Writer.getDeclEnumAbbrev();
|
||||
|
||||
|
@ -316,6 +320,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
|
|||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
!CXXRecordDecl::classofKind(D->getKind()) &&
|
||||
!needsAnonymousDeclarationNumber(D) &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
AbbrevToUse = Writer.getDeclRecordAbbrev();
|
||||
|
||||
|
@ -751,6 +756,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
|
|||
!D->isTopLevelDeclInObjCContainer() &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
!needsAnonymousDeclarationNumber(D) &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
|
||||
!D->hasExtInfo() &&
|
||||
D->getFirstDecl() == D->getMostRecentDecl() &&
|
||||
|
|
|
@ -87,3 +87,4 @@ template<typename T> struct PartiallyInstantiatePartialSpec<T*> {
|
|||
typedef PartiallyInstantiatePartialSpec<int*> PartiallyInstantiatePartialSpecHelper;
|
||||
|
||||
void InstantiateWithAliasTemplate(WithAliasTemplate<int>::X<char>);
|
||||
inline int InstantiateWithAnonymousDeclsA(WithAnonymousDecls<int> x) { return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d); }
|
||||
|
|
|
@ -70,6 +70,9 @@ template<> struct MergeSpecializations<double> {
|
|||
template<typename U> using AliasTemplate = U;
|
||||
|
||||
void InstantiateWithAliasTemplate(WithAliasTemplate<int>::X<char>);
|
||||
inline int InstantiateWithAnonymousDeclsB(WithAnonymousDecls<int> x) {
|
||||
return (x.k ? x.a : x.b) + (x.k ? x.s.c : x.s.d);
|
||||
}
|
||||
|
||||
@import cxx_templates_a;
|
||||
template<typename T> void UseDefinedInBImplIndirectly(T &v) {
|
||||
|
|
|
@ -45,4 +45,11 @@ template<typename T> struct WithAliasTemplate {
|
|||
template<typename> using X = T;
|
||||
};
|
||||
|
||||
template<typename T> struct WithAnonymousDecls {
|
||||
struct { bool k; };
|
||||
union { int a, b; };
|
||||
struct { int c, d; } s;
|
||||
typedef int X;
|
||||
};
|
||||
|
||||
#include "cxx-templates-textual.h"
|
||||
|
|
|
@ -145,6 +145,11 @@ MergeSpecializations<bool>::explicitly_specialized_in_c spec_in_c_2;
|
|||
|
||||
using AliasTemplateMergingTest = WithAliasTemplate<int>::X<char>;
|
||||
|
||||
int AnonymousDeclsMergingTest(WithAnonymousDecls<int> WAD) {
|
||||
return InstantiateWithAnonymousDeclsA(WAD) +
|
||||
InstantiateWithAnonymousDeclsB(WAD);
|
||||
}
|
||||
|
||||
@import cxx_templates_common;
|
||||
|
||||
typedef SomeTemplate<int*> SomeTemplateIntPtr;
|
||||
|
|
Loading…
Reference in New Issue