<div dir="ltr"><div class="gmail_quote">On Fri, Feb 27, 2015 at 1:30 AM Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Feb 26 18:25:58 2015<br>
New Revision: 230712<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=230712&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=230712&view=rev</a><br>
Log:<br>
[modules] When loading in multiple canonical definitions of a template,<br>
accumulate the set of specializations rather than overwriting one list<br>
with another.<br>
<br>
Added:<br>
    cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/d.h<br>
Modified:<br>
    cfe/trunk/lib/Serialization/<u></u>ASTReaderDecl.cpp<br>
    cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/a.h<br>
    cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/merge-decl-<u></u>context.modulemap<br>
    cfe/trunk/test/Modules/merge-<u></u>decl-context.cpp<br>
<br>
Modified: cfe/trunk/lib/Serialization/<u></u>ASTReaderDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=230712&r1=230711&r2=230712&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/<u></u>Serialization/ASTReaderDecl.<u></u>cpp?rev=230712&r1=230711&r2=<u></u>230712&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/lib/Serialization/<u></u>ASTReaderDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<u></u>ASTReaderDecl.cpp Thu Feb 26 18:25:58 2015<br>
@@ -66,7 +66,12 @@ namespace clang {<br>
     serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {<br>
       return Reader.ReadDeclID(F, R, I);<br>
     }<br>
-<br>
+<br>
+    void ReadDeclIDList(<u></u>SmallVectorImpl<DeclID> &IDs) {<br>
+      for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)<br>
+        IDs.push_back(ReadDeclID(<u></u>Record, Idx));<br>
+    }<br>
+<br>
     Decl *ReadDecl(const RecordData &R, unsigned &I) {<br>
       return Reader.ReadDecl(F, R, I);<br>
     }<br>
@@ -398,7 +403,6 @@ void ASTDeclReader::Visit(Decl *D) {<br>
     // FunctionDecl's body was written last after all other Stmts/Exprs.<br>
     // We only read it if FD doesn't already have a body (e.g., from another<br>
     // module).<br>
-    // FIXME: Also consider = default and = delete.<br>
     // FIXME: Can we diagnose ODR violations somehow?<br>
     if (Record[Idx++]) {<br>
       Reader.PendingBodies[FD] = GetCurrentCursorOffset();<br>
@@ -1393,8 +1397,6 @@ void ASTDeclReader::<u></u>MergeDefinitionData(<br>
   }<br>
<br>
   // FIXME: Move this out into a .def file?<br>
-  // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than<br>
-  // asserting; this can happen in the case of an ODR violation.<br>
   bool DetectedOdrViolation = false;<br>
 #define OR_FIELD(Field) DD.Field |= MergeDD.Field;<br>
 #define MATCH_FIELD(Field) \<br>
@@ -1723,36 +1725,37 @@ ASTDeclReader::<u></u>VisitRedeclarableTemplate<br>
   return Redecl;<br>
 }<br>
<br>
+static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,<br>
+                             SmallVectorImpl<DeclID> &IDs) {<br>
+  assert(!IDs.empty() && "no IDs to add to list");<br>
+<br>
+  size_t OldCount = Old ? *Old : 0;<br>
+  size_t NewCount = OldCount + IDs.size();<br>
+  auto *Result = new (Context) DeclID[1 + NewCount];<br>
+  auto *Pos = Result;<br>
+  *Pos++ = NewCount;<br>
+  if (OldCount)<br>
+    Pos = std::copy(Old + 1, Old + 1 + OldCount, Pos);<br>
+  std::copy(IDs.begin(), IDs.end(), Pos);<br>
+  return Result;<br>
+}<br>
+<br>
 void ASTDeclReader::<u></u>VisitClassTemplateDecl(<u></u>ClassTemplateDecl *D) {<br>
   RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(<u></u>D);<br>
<br>
   if (ThisDeclID == Redecl.getFirstID()) {<br>
     // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of<br>
     // the specializations.<br>
-    SmallVector<serialization::<u></u>DeclID, 2> SpecIDs;<br>
-    SpecIDs.push_back(0);<br>
-<br>
+    SmallVector<serialization::<u></u>DeclID, 32> SpecIDs;<br>
     // Specializations.<br>
-    unsigned Size = Record[Idx++];<br>
-    SpecIDs[0] += Size;<br>
-    for (unsigned I = 0; I != Size; ++I)<br>
-      SpecIDs.push_back(ReadDeclID(<u></u>Record, Idx));<br>
-<br>
+    ReadDeclIDList(SpecIDs);<br>
     // Partial specializations.<br>
-    Size = Record[Idx++];<br>
-    SpecIDs[0] += Size;<br>
-    for (unsigned I = 0; I != Size; ++I)<br>
-      SpecIDs.push_back(ReadDeclID(<u></u>Record, Idx));<br>
-<br>
-    ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();<br>
-    if (SpecIDs[0]) {<br>
-      typedef serialization::DeclID DeclID;<br>
-<br>
-      // FIXME: Append specializations!<br>
-      CommonPtr->LazySpecializations<br>
-        = new (Reader.getContext()) DeclID [SpecIDs.size()];<br>
-      memcpy(CommonPtr-><u></u>LazySpecializations, SpecIDs.data(),<br>
-             SpecIDs.size() * sizeof(DeclID));<br>
+    ReadDeclIDList(SpecIDs);<br>
+<br>
+    if (!SpecIDs.empty()) {<br>
+      auto *CommonPtr = D->getCommonPtr();<br>
+      CommonPtr->LazySpecializations = newDeclIDList(<br>
+          Reader.getContext(), CommonPtr-><u></u>LazySpecializations, SpecIDs);<br>
     }<br>
   }<br>
<br>
@@ -1774,30 +1777,16 @@ void ASTDeclReader::<u></u>VisitVarTemplateDecl<br>
   if (ThisDeclID == Redecl.getFirstID()) {<br>
     // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of<br>
     // the specializations.<br>
-    SmallVector<serialization::<u></u>DeclID, 2> SpecIDs;<br>
-    SpecIDs.push_back(0);<br>
-<br>
+    SmallVector<serialization::<u></u>DeclID, 32> SpecIDs;<br>
     // Specializations.<br>
-    unsigned Size = Record[Idx++];<br>
-    SpecIDs[0] += Size;<br>
-    for (unsigned I = 0; I != Size; ++I)<br>
-      SpecIDs.push_back(ReadDeclID(<u></u>Record, Idx));<br>
-<br>
+    ReadDeclIDList(SpecIDs);<br>
     // Partial specializations.<br>
-    Size = Record[Idx++];<br>
-    SpecIDs[0] += Size;<br>
-    for (unsigned I = 0; I != Size; ++I)<br>
-      SpecIDs.push_back(ReadDeclID(<u></u>Record, Idx));<br>
-<br>
-    VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();<br>
-    if (SpecIDs[0]) {<br>
-      typedef serialization::DeclID DeclID;<br>
-<br>
-      // FIXME: Append specializations!<br>
-      CommonPtr->LazySpecializations =<br>
-          new (Reader.getContext()) DeclID[SpecIDs.size()];<br>
-      memcpy(CommonPtr-><u></u>LazySpecializations, SpecIDs.data(),<br>
-             SpecIDs.size() * sizeof(DeclID));<br>
+    ReadDeclIDList(SpecIDs);<br>
+<br>
+    if (!SpecIDs.empty()) {<br>
+      auto *CommonPtr = D->getCommonPtr();<br>
+      CommonPtr->LazySpecializations = newDeclIDList(<br>
+          Reader.getContext(), CommonPtr-><u></u>LazySpecializations, SpecIDs);<br>
     }<br>
   }<br>
 }<br></blockquote><div><br></div><div>This seems 100% identical to <span style="font-size:13.1999998092651px">VisitClassTempl</span><span style="font-size:13.1999998092651px">ateDecl now (unless I'm missing something).</span></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
@@ -1909,17 +1898,13 @@ void ASTDeclReader::<u></u>VisitFunctionTemplat<br>
<br>
   if (ThisDeclID == Redecl.getFirstID()) {<br>
     // This FunctionTemplateDecl owns a CommonPtr; read it.<br>
+    SmallVector<serialization::<u></u>DeclID, 32> SpecIDs;<br>
+    ReadDeclIDList(SpecIDs);<br>
<br>
-    // Read the function specialization declaration IDs. The specializations<br>
-    // themselves will be loaded if they're needed.<br>
-    if (unsigned NumSpecs = Record[Idx++]) {<br>
-      // FIXME: Append specializations!<br>
-      FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();<br>
-      CommonPtr->LazySpecializations = new (Reader.getContext())<br>
-          serialization::DeclID[NumSpecs + 1];<br>
-      CommonPtr-><u></u>LazySpecializations[0] = NumSpecs;<br>
-      for (unsigned I = 0; I != NumSpecs; ++I)<br>
-        CommonPtr-><u></u>LazySpecializations[I + 1] = ReadDeclID(Record, Idx);<br>
+    if (!SpecIDs.empty()) {<br>
+      auto *CommonPtr = D->getCommonPtr();<br>
+      CommonPtr->LazySpecializations = newDeclIDList(<br>
+          Reader.getContext(), CommonPtr-><u></u>LazySpecializations, SpecIDs);<br>
     }<br>
   }<br>
 }<br>
<br>
Modified: cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/a.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-decl-context/a.h?rev=230712&r1=230711&r2=230712&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/test/<u></u>Modules/Inputs/merge-decl-<u></u>context/a.h?rev=230712&r1=<u></u>230711&r2=230712&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/a.h (original)<br>
+++ cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/a.h Thu Feb 26 18:25:58 2015<br>
@@ -8,6 +8,8 @@ struct A {<br>
   }<br>
   A(double) {}<br>
   A(double, double) {}<br>
+  A(double, int) {}<br>
+  A(int, double) {}<br>
 };<br>
<br>
 template <typename T1, typename T2><br>
<br>
Added: cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/d.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-decl-context/d.h?rev=230712&view=auto" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/test/<u></u>Modules/Inputs/merge-decl-<u></u>context/d.h?rev=230712&view=<u></u>auto</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/d.h (added)<br>
+++ cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/d.h Thu Feb 26 18:25:58 2015<br>
@@ -0,0 +1,7 @@<br>
+#ifndef D_H<br>
+#define D_H<br>
+<br>
+#include "a.h"<br>
+#include "b.h"<br>
+<br>
+#endif<br>
<br>
Modified: cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/merge-decl-<u></u>context.modulemap<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap?rev=230712&r1=230711&r2=230712&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/test/<u></u>Modules/Inputs/merge-decl-<u></u>context/merge-decl-context.<u></u>modulemap?rev=230712&r1=<u></u>230711&r2=230712&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/merge-decl-<u></u>context.modulemap (original)<br>
+++ cfe/trunk/test/Modules/Inputs/<u></u>merge-decl-context/merge-decl-<u></u>context.modulemap Thu Feb 26 18:25:58 2015<br>
@@ -11,3 +11,8 @@ module "c" {<br>
   export *<br>
   header "c.h"<br>
 }<br>
+<br>
+module "d" {<br>
+  export *<br>
+  header "d.h"<br>
+}<br>
<br>
Modified: cfe/trunk/test/Modules/merge-<u></u>decl-context.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/merge-decl-context.cpp?rev=230712&r1=230711&r2=230712&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/test/<u></u>Modules/merge-decl-context.<u></u>cpp?rev=230712&r1=230711&r2=<u></u>230712&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- cfe/trunk/test/Modules/merge-<u></u>decl-context.cpp (original)<br>
+++ cfe/trunk/test/Modules/merge-<u></u>decl-context.cpp Thu Feb 26 18:25:58 2015<br>
@@ -4,21 +4,25 @@<br>
 // RUN:     -emit-module %S/Inputs/merge-decl-context/<u></u>merge-decl-context.modulemap -I%S/Inputs \<br>
 // RUN:     -I %S/Inputs/merge-decl-context<br>
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=c -o %t/c.pcm -fmodule-maps \<br>
-// RUN:     -fmodule-file=%t/b.pcm \<br>
+// RUN:     -fmodule-file=%t/b.pcm -fno-implicit-modules \<br>
+// RUN:     -emit-module %S/Inputs/merge-decl-context/<u></u>merge-decl-context.modulemap -I%S/Inputs \<br>
+// RUN:     -I %S/Inputs/merge-decl-context<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=d -o %t/d.pcm -fmodule-maps \<br>
+// RUN:     -fmodule-file=%t/b.pcm -fno-implicit-modules \<br>
 // RUN:     -emit-module %S/Inputs/merge-decl-context/<u></u>merge-decl-context.modulemap -I%S/Inputs \<br>
 // RUN:     -I %S/Inputs/merge-decl-context<br>
<br>
 // Use the two modules in a single compile.<br>
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%t/c.pcm -fmodule-file=%t/b.pcm \<br>
+// RUN:     -fmodule-file=%t/d.pcm -fno-implicit-modules \<br>
 // RUN:     -fmodule-map-file=%S/Inputs/<u></u>merge-decl-context/merge-decl-<u></u>context.modulemap -I%S/Inputs \<br>
 // RUN:     -emit-llvm -o %t/test.o %s<br>
<br>
 #include "Inputs/merge-decl-context/a.<u></u>h"<br>
 #include "Inputs/merge-decl-context/b.<u></u>h"<br>
 #include "Inputs/merge-decl-context/c.<u></u>h"<br>
+#include "Inputs/merge-decl-context/d.<u></u>h"<br>
<br>
 void t() {<br>
   ff(42);<br>
 }<br>
-<br>
-<br>
<br>
<br>
______________________________<u></u>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>