]> granicus.if.org Git - clang/commitdiff
[modules] When loading in multiple canonical definitions of a template,
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 27 Feb 2015 00:25:58 +0000 (00:25 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 27 Feb 2015 00:25:58 +0000 (00:25 +0000)
accumulate the set of specializations rather than overwriting one list
with another.

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

lib/Serialization/ASTReaderDecl.cpp
test/Modules/Inputs/merge-decl-context/a.h
test/Modules/Inputs/merge-decl-context/d.h [new file with mode: 0644]
test/Modules/Inputs/merge-decl-context/merge-decl-context.modulemap
test/Modules/merge-decl-context.cpp

index 339d0b87c250c10dbef754bd64bafd83507e729f..a10ae1edf94237b4d9f8de391b805ee1205fdba0 100644 (file)
@@ -66,7 +66,12 @@ namespace clang {
     serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
       return Reader.ReadDeclID(F, R, I);
     }
-    
+
+    void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
+      for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
+        IDs.push_back(ReadDeclID(Record, Idx));
+    }
+
     Decl *ReadDecl(const RecordData &R, unsigned &I) {
       return Reader.ReadDecl(F, R, I);
     }
@@ -398,7 +403,6 @@ void ASTDeclReader::Visit(Decl *D) {
     // FunctionDecl's body was written last after all other Stmts/Exprs.
     // We only read it if FD doesn't already have a body (e.g., from another
     // module).
-    // FIXME: Also consider = default and = delete.
     // FIXME: Can we diagnose ODR violations somehow?
     if (Record[Idx++]) {
       Reader.PendingBodies[FD] = GetCurrentCursorOffset();
@@ -1393,8 +1397,6 @@ void ASTDeclReader::MergeDefinitionData(
   }
 
   // FIXME: Move this out into a .def file?
-  // FIXME: Issue a diagnostic on a mismatched MATCH_FIELD, rather than
-  // asserting; this can happen in the case of an ODR violation.
   bool DetectedOdrViolation = false;
 #define OR_FIELD(Field) DD.Field |= MergeDD.Field;
 #define MATCH_FIELD(Field) \
@@ -1723,36 +1725,37 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
   return Redecl;
 }
 
+static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
+                             SmallVectorImpl<DeclID> &IDs) {
+  assert(!IDs.empty() && "no IDs to add to list");
+
+  size_t OldCount = Old ? *Old : 0;
+  size_t NewCount = OldCount + IDs.size();
+  auto *Result = new (Context) DeclID[1 + NewCount];
+  auto *Pos = Result;
+  *Pos++ = NewCount;
+  if (OldCount)
+    Pos = std::copy(Old + 1, Old + 1 + OldCount, Pos);
+  std::copy(IDs.begin(), IDs.end(), Pos);
+  return Result;
+}
+
 void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
   if (ThisDeclID == Redecl.getFirstID()) {
     // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
     // the specializations.
-    SmallVector<serialization::DeclID, 2> SpecIDs;
-    SpecIDs.push_back(0);
-    
+    SmallVector<serialization::DeclID, 32> SpecIDs;
     // Specializations.
-    unsigned Size = Record[Idx++];
-    SpecIDs[0] += Size;
-    for (unsigned I = 0; I != Size; ++I)
-      SpecIDs.push_back(ReadDeclID(Record, Idx));
-
+    ReadDeclIDList(SpecIDs);
     // Partial specializations.
-    Size = Record[Idx++];
-    SpecIDs[0] += Size;
-    for (unsigned I = 0; I != Size; ++I)
-      SpecIDs.push_back(ReadDeclID(Record, Idx));
-
-    ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
-    if (SpecIDs[0]) {
-      typedef serialization::DeclID DeclID;
-      
-      // FIXME: Append specializations!
-      CommonPtr->LazySpecializations
-        = new (Reader.getContext()) DeclID [SpecIDs.size()];
-      memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), 
-             SpecIDs.size() * sizeof(DeclID));
+    ReadDeclIDList(SpecIDs);
+
+    if (!SpecIDs.empty()) {
+      auto *CommonPtr = D->getCommonPtr();
+      CommonPtr->LazySpecializations = newDeclIDList(
+          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
     }
   }
 
@@ -1774,30 +1777,16 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
   if (ThisDeclID == Redecl.getFirstID()) {
     // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
     // the specializations.
-    SmallVector<serialization::DeclID, 2> SpecIDs;
-    SpecIDs.push_back(0);
-
+    SmallVector<serialization::DeclID, 32> SpecIDs;
     // Specializations.
-    unsigned Size = Record[Idx++];
-    SpecIDs[0] += Size;
-    for (unsigned I = 0; I != Size; ++I)
-      SpecIDs.push_back(ReadDeclID(Record, Idx));
-
+    ReadDeclIDList(SpecIDs);
     // Partial specializations.
-    Size = Record[Idx++];
-    SpecIDs[0] += Size;
-    for (unsigned I = 0; I != Size; ++I)
-      SpecIDs.push_back(ReadDeclID(Record, Idx));
-
-    VarTemplateDecl::Common *CommonPtr = D->getCommonPtr();
-    if (SpecIDs[0]) {
-      typedef serialization::DeclID DeclID;
-
-      // FIXME: Append specializations!
-      CommonPtr->LazySpecializations =
-          new (Reader.getContext()) DeclID[SpecIDs.size()];
-      memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
-             SpecIDs.size() * sizeof(DeclID));
+    ReadDeclIDList(SpecIDs);
+
+    if (!SpecIDs.empty()) {
+      auto *CommonPtr = D->getCommonPtr();
+      CommonPtr->LazySpecializations = newDeclIDList(
+          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
     }
   }
 }
@@ -1909,17 +1898,13 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
 
   if (ThisDeclID == Redecl.getFirstID()) {
     // This FunctionTemplateDecl owns a CommonPtr; read it.
+    SmallVector<serialization::DeclID, 32> SpecIDs;
+    ReadDeclIDList(SpecIDs);
 
-    // Read the function specialization declaration IDs. The specializations
-    // themselves will be loaded if they're needed.
-    if (unsigned NumSpecs = Record[Idx++]) {
-      // FIXME: Append specializations!
-      FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();
-      CommonPtr->LazySpecializations = new (Reader.getContext())
-          serialization::DeclID[NumSpecs + 1];
-      CommonPtr->LazySpecializations[0] = NumSpecs;
-      for (unsigned I = 0; I != NumSpecs; ++I)
-        CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx);
+    if (!SpecIDs.empty()) {
+      auto *CommonPtr = D->getCommonPtr();
+      CommonPtr->LazySpecializations = newDeclIDList(
+          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
     }
   }
 }
index bd08ecaf417aae81317d3419f034cf79676bc4b5..89cc7120fd17128ad30940c4f0167b4167fa3c39 100644 (file)
@@ -8,6 +8,8 @@ struct A {
   }
   A(double) {}
   A(double, double) {}
+  A(double, int) {}
+  A(int, double) {}
 };
 
 template <typename T1, typename T2>
diff --git a/test/Modules/Inputs/merge-decl-context/d.h b/test/Modules/Inputs/merge-decl-context/d.h
new file mode 100644 (file)
index 0000000..ccc7308
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef D_H
+#define D_H
+
+#include "a.h"
+#include "b.h"
+
+#endif
index fedc5dfbbe4a175c48434ab19dbbfe53fa44e448..46f69548bc6782566cad8b7035859a858d516b8d 100644 (file)
@@ -11,3 +11,8 @@ module "c" {
   export *
   header "c.h"
 }
+
+module "d" {
+  export *
+  header "d.h"
+}
index 90c234b66f57e7e180e34bd6698f1dc30d938f6f..208ba9212e8240fba9e543facba399acec8c6404 100644 (file)
@@ -4,21 +4,25 @@
 // RUN:     -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \
 // RUN:     -I %S/Inputs/merge-decl-context
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=c -o %t/c.pcm -fmodule-maps \
-// RUN:     -fmodule-file=%t/b.pcm \
+// RUN:     -fmodule-file=%t/b.pcm -fno-implicit-modules \
+// RUN:     -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \
+// RUN:     -I %S/Inputs/merge-decl-context
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-name=d -o %t/d.pcm -fmodule-maps \
+// RUN:     -fmodule-file=%t/b.pcm -fno-implicit-modules \
 // RUN:     -emit-module %S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \
 // RUN:     -I %S/Inputs/merge-decl-context
 
 // Use the two modules in a single compile.
 // RUN: %clang_cc1 -x c++ -std=c++11 -fmodules -fmodule-file=%t/c.pcm -fmodule-file=%t/b.pcm \
+// RUN:     -fmodule-file=%t/d.pcm -fno-implicit-modules \
 // RUN:     -fmodule-map-file=%S/Inputs/merge-decl-context/merge-decl-context.modulemap -I%S/Inputs \
 // RUN:     -emit-llvm -o %t/test.o %s
 
 #include "Inputs/merge-decl-context/a.h"
 #include "Inputs/merge-decl-context/b.h"
 #include "Inputs/merge-decl-context/c.h"
+#include "Inputs/merge-decl-context/d.h"
 
 void t() {
   ff(42);
 }
-
-