From 0128dc8835c73dac96aa100bd5664b426c95c0a6 Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
Date: Tue, 4 Aug 2015 02:05:09 +0000
Subject: [PATCH] [modules] Make IndirectFieldDecl mergeable to avoid lookup
 ambiguity when the same anonymous union is defined across multiple modules.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243940 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/AST/Decl.h                         | 6 +++++-
 lib/Serialization/ASTReaderDecl.cpp              | 9 +++++++++
 test/Modules/Inputs/submodules-merge-defs/defs.h | 8 ++++++++
 test/Modules/submodules-merge-defs.cpp           | 1 +
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 76c05852f72..76fda1c0915 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -2499,7 +2499,8 @@ public:
 /// IndirectFieldDecl - An instance of this class is created to represent a
 /// field injected from an anonymous union/struct into the parent scope.
 /// IndirectFieldDecl are always implicit.
-class IndirectFieldDecl : public ValueDecl {
+class IndirectFieldDecl : public ValueDecl,
+                          public Mergeable<IndirectFieldDecl> {
   void anchor() override;
   NamedDecl **Chaining;
   unsigned ChainingSize;
@@ -2537,6 +2538,9 @@ public:
     return dyn_cast<VarDecl>(*chain_begin());
   }
 
+  IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+  const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == IndirectField; }
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 45a3e45bbcf..0242e7eed07 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1178,6 +1178,8 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
 
   for (unsigned I = 0; I != FD->ChainingSize; ++I)
     FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
+
+  mergeMergeable(FD);
 }
 
 ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
@@ -2638,6 +2640,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
     return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
   }
 
+  // Indirect fields with the same target field match.
+  if (auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
+    auto *IFDY = cast<IndirectFieldDecl>(Y);
+    return IFDX->getAnonField()->getCanonicalDecl() ==
+           IFDY->getAnonField()->getCanonicalDecl();
+  }
+
   // Enumerators with the same name match.
   if (isa<EnumConstantDecl>(X))
     // FIXME: Also check the value is odr-equivalent.
diff --git a/test/Modules/Inputs/submodules-merge-defs/defs.h b/test/Modules/Inputs/submodules-merge-defs/defs.h
index e4c86d80ba6..670c400ae3b 100644
--- a/test/Modules/Inputs/submodules-merge-defs/defs.h
+++ b/test/Modules/Inputs/submodules-merge-defs/defs.h
@@ -103,3 +103,11 @@ namespace RedeclDifferentDeclKind {
   typedef X X;
   using RedeclDifferentDeclKind::X;
 }
+
+namespace Anon {
+  struct X {
+    union {
+      int n;
+    };
+  };
+}
diff --git a/test/Modules/submodules-merge-defs.cpp b/test/Modules/submodules-merge-defs.cpp
index 016b8a8f47a..62cbbd51098 100644
--- a/test/Modules/submodules-merge-defs.cpp
+++ b/test/Modules/submodules-merge-defs.cpp
@@ -104,6 +104,7 @@ template<typename T, int N, template<typename> class K> struct J;
 J<> post_j2;
 FriendDefArg::Y<int> friend_def_arg;
 FriendDefArg::D<> friend_def_arg_d;
+int post_anon_x_n = Anon::X().n;
 
 MergeFunctionTemplateSpecializations::X<int>::Q<char> xiqc;
 
-- 
GitLab