[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:
Richard Smith 2014-08-28 01:33:39 +00:00
parent 9fc9bf83a8
commit d08aeb6b57
13 changed files with 165 additions and 20 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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));

View File

@ -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>

View File

@ -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()) {

View File

@ -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() &&

View File

@ -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); }

View File

@ -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) {

View File

@ -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"

View File

@ -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;