r216639 - [modules] Number anonymous declarations that are lexically within mergeable
Richard Smith
richard-llvm at metafoo.co.uk
Wed Aug 27 18:33:39 PDT 2014
Author: rsmith
Date: Wed Aug 27 20:33:39 2014
New Revision: 216639
URL: http://llvm.org/viewvc/llvm-project?rev=216639&view=rev
Log:
[modules] Number anonymous declarations that are lexically within mergeable
contexts, so that we can merge them when we merge the surrounding context.
Modified:
cfe/trunk/include/clang/AST/DeclarationName.h
cfe/trunk/include/clang/Serialization/ASTReader.h
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Serialization/ASTCommon.cpp
cfe/trunk/lib/Serialization/ASTCommon.h
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
cfe/trunk/test/Modules/Inputs/cxx-templates-common.h
cfe/trunk/test/Modules/cxx-templates.cpp
Modified: cfe/trunk/include/clang/AST/DeclarationName.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclarationName.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclarationName.h (original)
+++ cfe/trunk/include/clang/AST/DeclarationName.h Wed Aug 27 20:33:39 2014
@@ -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
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Wed Aug 27 20:33:39 2014
@@ -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;
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Wed Aug 27 20:33:39 2014
@@ -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);
Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Wed Aug 27 20:33:39 2014
@@ -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::isRedeclarableDeclKi
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);
+}
+
Modified: cfe/trunk/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.h (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.h Wed Aug 27 20:33:39 2014
@@ -80,6 +80,10 @@ const DeclContext *getDefinitiveDeclCont
/// \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
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Aug 27 20:33:39 2014
@@ -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));
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Aug 27 20:33:39 2014
@@ -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::VisitTranslationUnit
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::~Find
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(Name
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 ASTDec
// 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 ASTDec
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>
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Aug 27 20:33:39 2014
@@ -5121,6 +5121,30 @@ void ASTWriter::AddDeclarationName(Decla
}
}
+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()) {
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Wed Aug 27 20:33:39 2014
@@ -203,6 +203,8 @@ void ASTDeclWriter::VisitTranslationUnit
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(Typ
!D->isInvalidDecl() &&
!D->isTopLevelDeclInObjCContainer() &&
!D->isModulePrivate() &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier)
AbbrevToUse = Writer.getDeclTypedefAbbrev();
@@ -292,6 +295,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDe
!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(Reco
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->isTopLevelDeclInObjCContainer() &&
D->getAccess() == AS_none &&
!D->isModulePrivate() &&
+ !needsAnonymousDeclarationNumber(D) &&
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-a.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-a.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-a.h Wed Aug 27 20:33:39 2014
@@ -87,3 +87,4 @@ template<typename T> struct PartiallyIns
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); }
Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-b.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-b.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-b.h Wed Aug 27 20:33:39 2014
@@ -70,6 +70,9 @@ template<> struct MergeSpecializations<d
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) {
Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-common.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-common.h?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-common.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-common.h Wed Aug 27 20:33:39 2014
@@ -45,4 +45,11 @@ template<typename T> struct WithAliasTem
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"
Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=216639&r1=216638&r2=216639&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Wed Aug 27 20:33:39 2014
@@ -145,6 +145,11 @@ MergeSpecializations<bool>::explicitly_s
using AliasTemplateMergingTest = WithAliasTemplate<int>::X<char>;
+int AnonymousDeclsMergingTest(WithAnonymousDecls<int> WAD) {
+ return InstantiateWithAnonymousDeclsA(WAD) +
+ InstantiateWithAnonymousDeclsB(WAD);
+}
+
@import cxx_templates_common;
typedef SomeTemplate<int*> SomeTemplateIntPtr;
More information about the cfe-commits
mailing list