[modules] If we add an implicit special member to a class through an update
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 Jan 2015 03:50:31 +0000 (03:50 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 Jan 2015 03:50:31 +0000 (03:50 +0000)
record, and that class declaration is not the canonical definition of the
class, be sure to add the class to the list of classes that are consulted when
we look up a special member in the canonical definition.

llvm-svn: 226778

clang/lib/Serialization/ASTReaderDecl.cpp
clang/test/Modules/Inputs/merge-implicit-special-members/a.h [new file with mode: 0644]
clang/test/Modules/Inputs/merge-implicit-special-members/b.h [new file with mode: 0644]
clang/test/Modules/Inputs/merge-implicit-special-members/c.h [new file with mode: 0644]
clang/test/Modules/Inputs/merge-implicit-special-members/module.modulemap [new file with mode: 0644]
clang/test/Modules/merge-implicit-special-members.cpp [new file with mode: 0644]

index b82f987..d43f3ea 100644 (file)
@@ -3523,13 +3523,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
   while (Idx < Record.size()) {
     switch ((DeclUpdateKind)Record[Idx++]) {
     case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
+      auto *RD = cast<CXXRecordDecl>(D);
       // FIXME: If we also have an update record for instantiating the
       // definition of D, we need that to happen before we get here.
       Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
       assert(MD && "couldn't read decl from update record");
       // FIXME: We should call addHiddenDecl instead, to add the member
       // to its DeclContext.
-      cast<CXXRecordDecl>(D)->addedMember(MD);
+      RD->addedMember(MD);
+
+      // If we've added a new special member to a class definition that is not
+      // the canonical definition, then we need special member lookups in the
+      // canonical definition to also look into our class.
+      auto *DD = RD->DefinitionData.getNotUpdated();
+      if (DD && DD->Definition != RD) {
+        auto &Merged = Reader.MergedLookups[DD->Definition];
+        // FIXME: Avoid the linear-time scan here.
+        if (std::find(Merged.begin(), Merged.end(), RD) == Merged.end())
+          Merged.push_back(RD);
+      }
       break;
     }
 
diff --git a/clang/test/Modules/Inputs/merge-implicit-special-members/a.h b/clang/test/Modules/Inputs/merge-implicit-special-members/a.h
new file mode 100644 (file)
index 0000000..3029e4a
--- /dev/null
@@ -0,0 +1 @@
+struct pthread_mutex_t { int lock; };
diff --git a/clang/test/Modules/Inputs/merge-implicit-special-members/b.h b/clang/test/Modules/Inputs/merge-implicit-special-members/b.h
new file mode 100644 (file)
index 0000000..3029e4a
--- /dev/null
@@ -0,0 +1 @@
+struct pthread_mutex_t { int lock; };
diff --git a/clang/test/Modules/Inputs/merge-implicit-special-members/c.h b/clang/test/Modules/Inputs/merge-implicit-special-members/c.h
new file mode 100644 (file)
index 0000000..ee0bebb
--- /dev/null
@@ -0,0 +1,3 @@
+#include "a.h"
+#include "b.h"
+int k = pthread_mutex_t().lock;
diff --git a/clang/test/Modules/Inputs/merge-implicit-special-members/module.modulemap b/clang/test/Modules/Inputs/merge-implicit-special-members/module.modulemap
new file mode 100644 (file)
index 0000000..77e0a89
--- /dev/null
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
+module c { header "c.h" export * }
diff --git a/clang/test/Modules/merge-implicit-special-members.cpp b/clang/test/Modules/merge-implicit-special-members.cpp
new file mode 100644 (file)
index 0000000..a8b917c
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/merge-implicit-special-members -verify %s
+// expected-no-diagnostics
+#include "c.h"
+int n = pthread_mutex_t().lock;