]> granicus.if.org Git - clang/commitdiff
[modules] When instantiating the contents of an imported CXXRecordDecl, we can
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 11 Aug 2015 22:00:24 +0000 (22:00 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 11 Aug 2015 22:00:24 +0000 (22:00 +0000)
emit lexical contents for a declaration for another module. Track which module
those contents came from, and ensure that we only grab the lexical contents
from a single such instantiation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244682 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReader.cpp
test/Modules/Inputs/templates-right.h
test/Modules/Inputs/templates-top.h
test/Modules/templates.mm

index 63bad2663e0bb0cdf91c150c03286a2f0f1ed1eb..cc53b8ceb0cc0c61bd87e0d31f948d5cb7fd5be9 100644 (file)
@@ -499,7 +499,8 @@ private:
   typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents;
 
   /// \brief Map from a DeclContext to its lexical contents.
-  llvm::DenseMap<const DeclContext*, LexicalContents> LexicalDecls;
+  llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
+      LexicalDecls;
 
   /// \brief Map from the TU to its lexical contents from each module file.
   std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
index ad528b0213ab93416e740f2204eb7739bbd5b96e..91dc4bdbc90e390a1bff79089746bd2b617e4079 100644 (file)
@@ -975,11 +975,18 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
 
   assert(!isa<TranslationUnitDecl>(DC) &&
          "expected a TU_UPDATE_LEXICAL record for TU");
-  // FIXME: Once we remove RewriteDecl, assert that we didn't already have
-  // lexical decls for this context.
-  LexicalDecls[DC] = llvm::makeArrayRef(
-      reinterpret_cast<const llvm::support::unaligned_uint32_t *>(Blob.data()),
-      Blob.size() / 4);
+  // If we are handling a C++ class template instantiation, we can see multiple
+  // lexical updates for the same record. It's important that we select only one
+  // of them, so that field numbering works properly. Just pick the first one we
+  // see.
+  auto &Lex = LexicalDecls[DC];
+  if (!Lex.first) {
+    Lex = std::make_pair(
+        &M, llvm::makeArrayRef(
+                reinterpret_cast<const llvm::support::unaligned_uint32_t *>(
+                    Blob.data()),
+                Blob.size() / 4));
+  }
   DC->setHasExternalLexicalStorage(true);
   return false;
 }
@@ -6253,7 +6260,7 @@ void ASTReader::FindExternalLexicalDecls(
   } else {
     auto I = LexicalDecls.find(DC);
     if (I != LexicalDecls.end())
-      Visit(getOwningModuleFile(cast<Decl>(DC)), I->second);
+      Visit(I->second.first, I->second.second);
   }
 
   ++NumLexicalDeclContextsRead;
index daea97b86b88477cb73c3e1c5fc2d734caf0efdc..32487c60c2692df66021dc61b58c02994bb45da2 100644 (file)
@@ -38,6 +38,10 @@ int defineListDoubleRight() {
   return ld.size;
 }
 
+inline void defineListLongRight() {
+  List<long> ll;
+}
+
 template<typename T> struct MergePatternDecl;
 
 void outOfLineInlineUseRightF(void (OutOfLineInline<int>::*)() = &OutOfLineInline<int>::f);
index 31f5e4199281990a9638698e6eb28e5a00a19aa0..a08268352399de3abb9cf26fe4763c977cc26d6a 100644 (file)
@@ -10,6 +10,7 @@ public:
 };
 
 extern List<double> *instantiateListDoubleDeclaration;
+extern List<long> *instantiateListLongDeclaration;
 
 namespace A {
   class Y {
index 4c6e4723a3bb380c7672e6765ee99f344e5d8a83..190084ad2b740457376364716db1c8986c89901c 100644 (file)
@@ -28,6 +28,8 @@ void testTemplateClasses() {
   N::Set<char> set_char;
   set_char.insert('A');
 
+  static_assert(sizeof(List<long>) == sizeof(List<short>), "");
+
   List<double> list_double;
   list_double.push_back(0.0);
 }