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