r216312 - [modules] When merging a tag declaration that has a typedef name for linkage

Richard Smith richard-llvm at metafoo.co.uk
Fri Aug 22 18:45:27 PDT 2014


Author: rsmith
Date: Fri Aug 22 20:45:27 2014
New Revision: 216312

URL: http://llvm.org/viewvc/llvm-project?rev=216312&view=rev
Log:
[modules] When merging a tag declaration that has a typedef name for linkage
purposes, look for other typedefs with that same name and merge into their
named tag declaration if there is one.

Modified:
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/cxx-decls-imported.h
    cfe/trunk/test/Modules/Inputs/cxx-decls-merged.h
    cfe/trunk/test/Modules/cxx-decls.cpp

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=216312&r1=216311&r2=216312&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Aug 22 20:45:27 2014
@@ -438,6 +438,11 @@ private:
   /// \brief Declarations that have been replaced in a later file in the chain.
   DeclReplacementMap ReplacedDecls;
 
+  /// \brief Declarations that have been imported and have typedef names for
+  /// linkage purposes.
+  llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*>
+      ImportedTypedefNamesForLinkage;
+
   struct FileDeclsInfo {
     ModuleFile *Mod;
     ArrayRef<serialization::LocalDeclID> Decls;

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=216312&r1=216311&r2=216312&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Aug 22 20:45:27 2014
@@ -2412,13 +2412,38 @@ static DeclContext *getPrimaryContextFor
   return nullptr;
 }
 
+static DeclarationName
+getNameForMerging(NamedDecl *D, bool &IsTypedefNameForLinkage) {
+  DeclarationName Name = D->getDeclName();
+
+  if (!Name) {
+    // If this declaration has a typedef name for linkage purposes,
+    // look that name up when merging. We may be able to find another
+    // typedef that names a matching TagDecl.
+    if (auto *TD = dyn_cast<TagDecl>(D)) {
+      if (auto *Typedef = TD->getTypedefNameForAnonDecl()) {
+        Name = Typedef->getDeclName();
+        IsTypedefNameForLinkage = true;
+      }
+    }
+  }
+
+  return Name;
+}
+
 ASTDeclReader::FindExistingResult::~FindExistingResult() {
   if (!AddResult || Existing)
     return;
 
+  bool IsTypedefNameForLinkage = false;
+  DeclarationName Name = getNameForMerging(New, IsTypedefNameForLinkage);
+
   DeclContext *DC = New->getDeclContext()->getRedeclContext();
-  if (DC->isTranslationUnit() && Reader.SemaObj) {
-    Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName());
+  if (IsTypedefNameForLinkage) {
+    Reader.ImportedTypedefNamesForLinkage.insert(
+        std::make_pair(std::make_pair(DC, Name.getAsIdentifierInfo()), New));
+  } else if (DC->isTranslationUnit() && Reader.SemaObj) {
+    Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, Name);
   } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) {
     // Add the declaration to its redeclaration context so later merging
     // lookups will find it.
@@ -2426,8 +2451,31 @@ ASTDeclReader::FindExistingResult::~Find
   }
 }
 
+/// Find the declaration that should be merged into, given the declaration found
+/// by name lookup. If we're merging an anonymous declaration within a typedef,
+/// we need a matching typedef, and we merge with the type inside it.
+static NamedDecl *getDeclForMerging(NamedDecl *Found,
+                                    bool IsTypedefNameForLinkage) {
+  if (!IsTypedefNameForLinkage)
+    return Found;
+
+  // If we found a typedef declaration that gives a name to some other
+  // declaration, then we want that inner declaration. Declarations from
+  // AST files are handled via ImportedTypedefNamesForLinkage.
+  if (Found->isFromASTFile()) return 0;
+  if (auto *TND = dyn_cast<TypedefNameDecl>(Found)) {
+    if (auto *TT = TND->getTypeSourceInfo()->getType()->getAs<TagType>())
+      if (TT->getDecl()->getTypedefNameForAnonDecl() == TND)
+        return TT->getDecl();
+  }
+
+  return 0;
+}
+
 ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
-  DeclarationName Name = D->getDeclName();
+  bool IsTypedefNameForLinkage = false;
+  DeclarationName Name = getNameForMerging(D, IsTypedefNameForLinkage);
+
   if (!Name) {
     // Don't bother trying to find unnamed declarations.
     FindExistingResult Result(Reader, D, /*Existing=*/nullptr);
@@ -2441,6 +2489,15 @@ ASTDeclReader::FindExistingResult ASTDec
   // necessary merging already.
 
   DeclContext *DC = D->getDeclContext()->getRedeclContext();
+  if (IsTypedefNameForLinkage) {
+    auto It = Reader.ImportedTypedefNamesForLinkage.find(
+        std::make_pair(DC, Name.getAsIdentifierInfo()));
+    if (It != Reader.ImportedTypedefNamesForLinkage.end())
+      if (isSameEntity(It->second, D))
+        return FindExistingResult(Reader, D, It->second);
+    // Go on to check in other places in case an existing typedef name
+    // was not imported.
+  }
   if (DC->isTranslationUnit() && Reader.SemaObj) {
     IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver;
 
@@ -2470,14 +2527,16 @@ ASTDeclReader::FindExistingResult ASTDec
     for (IdentifierResolver::iterator I = IdResolver.begin(Name), 
                                    IEnd = IdResolver.end();
          I != IEnd; ++I) {
-      if (isSameEntity(*I, D))
-        return FindExistingResult(Reader, D, *I);
+      if (NamedDecl *Existing = getDeclForMerging(*I, IsTypedefNameForLinkage))
+        if (isSameEntity(*I, D))
+          return FindExistingResult(Reader, D, Existing);
     }
   } 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);
+      if (NamedDecl *Existing = getDeclForMerging(*I, IsTypedefNameForLinkage))
+        if (isSameEntity(Existing, D))
+          return FindExistingResult(Reader, D, Existing);
     }
   } else {
     // Not in a mergeable context.

Modified: cfe/trunk/test/Modules/Inputs/cxx-decls-imported.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-decls-imported.h?rev=216312&r1=216311&r2=216312&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-decls-imported.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-decls-imported.h Fri Aug 22 20:45:27 2014
@@ -23,3 +23,8 @@ void *operator new[](__SIZE_TYPE__);
 
 extern int mergeUsedFlag;
 inline int getMergeUsedFlag() { return mergeUsedFlag; }
+
+typedef struct {
+  int n;
+  int m;
+} NameForLinkage;

Modified: cfe/trunk/test/Modules/Inputs/cxx-decls-merged.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-decls-merged.h?rev=216312&r1=216311&r2=216312&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-decls-merged.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-decls-merged.h Fri Aug 22 20:45:27 2014
@@ -1 +1,7 @@
 extern int mergeUsedFlag;
+
+typedef struct {
+  int n;
+  int m;
+} NameForLinkage;
+extern NameForLinkage name_for_linkage;

Modified: cfe/trunk/test/Modules/cxx-decls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-decls.cpp?rev=216312&r1=216311&r2=216312&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-decls.cpp (original)
+++ cfe/trunk/test/Modules/cxx-decls.cpp Fri Aug 22 20:45:27 2014
@@ -30,7 +30,13 @@ void use_implicit_new_again() { operator
 
 int importMergeUsedFlag = getMergeUsedFlag();
 
+int use_name_for_linkage(NameForLinkage &nfl) {
+  return nfl.n + nfl.m;
+}
+
 @import cxx_decls_merged;
 
+int name_for_linkage_test = use_name_for_linkage(name_for_linkage);
+
 // CHECK: VarDecl [[mergeUsedFlag:0x[0-9a-f]*]] {{.*}} in cxx_decls.imported used mergeUsedFlag
 // CHECK: VarDecl {{0x[0-9a-f]*}} prev [[mergeUsedFlag]] {{.*}} in cxx_decls_merged used mergeUsedFlag





More information about the cfe-commits mailing list