r212836 - [modules] When merging a class template, also merge the definition of its pattern.

Richard Smith richard-llvm at metafoo.co.uk
Fri Jul 11 11:22:58 PDT 2014


Author: rsmith
Date: Fri Jul 11 13:22:58 2014
New Revision: 212836

URL: http://llvm.org/viewvc/llvm-project?rev=212836&view=rev
Log:
[modules] When merging a class template, also merge the definition of its pattern.

Modified:
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
    cfe/trunk/test/Modules/Inputs/cxx-templates-c.h
    cfe/trunk/test/Modules/cxx-templates.cpp

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=212836&r1=212835&r2=212836&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Jul 11 13:22:58 2014
@@ -1758,11 +1758,11 @@ ASTDeclReader::VisitClassTemplateSpecial
             Reader.MergedDeclContexts.insert(
                 std::make_pair(D, CanonDD->Definition));
             D->IsCompleteDefinition = false;
-            D->DefinitionData = CanonSpec->DefinitionData;
           } else {
             CanonSpec->DefinitionData = D->DefinitionData;
           }
         }
+        D->DefinitionData = CanonSpec->DefinitionData;
       }
     }
   }
@@ -2037,10 +2037,27 @@ void ASTDeclReader::mergeTemplatePattern
   auto *DPattern = D->getTemplatedDecl();
   auto *ExistingPattern = Existing->getTemplatedDecl();
   RedeclarableResult Result(Reader, DsID, DPattern->getKind());
-  if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern))
-    // FIXME: Merge definitions here, if both declarations had definitions.
+  if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
+    // Merge with any existing definition.
+    // FIXME: This is duplicated in several places. Refactor.
+    auto *ExistingClass =
+        cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
+    if (auto *DDD = DClass->DefinitionData.getNotUpdated()) {
+      if (auto *ExistingDD = ExistingClass->DefinitionData.getNotUpdated()) {
+        MergeDefinitionData(ExistingClass, *DDD);
+        Reader.PendingDefinitions.erase(DClass);
+        Reader.MergedDeclContexts.insert(
+            std::make_pair(DClass, ExistingDD->Definition));
+        DClass->IsCompleteDefinition = false;
+      } else {
+        ExistingClass->DefinitionData = DClass->DefinitionData;
+      }
+    }
+    DClass->DefinitionData = ExistingClass->DefinitionData;
+
     return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
                              Result);
+  }
   if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
     return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
                              Result);

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-a.h?rev=212836&r1=212835&r2=212836&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-a.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-a.h Fri Jul 11 13:22:58 2014
@@ -67,3 +67,9 @@ template<> struct WithExplicitSpecializa
 template<typename T> template<typename U>
 constexpr int Outer<T>::Inner<U>::f() { return 1; }
 static_assert(Outer<int>::Inner<int>::f() == 1, "");
+
+template<typename T> struct MergeTemplateDefinitions {
+  static constexpr int f();
+  static constexpr int g();
+};
+template<typename T> constexpr int MergeTemplateDefinitions<T>::f() { return 1; }

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-c.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-c.h?rev=212836&r1=212835&r2=212836&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-c.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-c.h Fri Jul 11 13:22:58 2014
@@ -5,3 +5,9 @@ template<typename T> struct MergeSpecial
 template<> struct MergeSpecializations<bool> {
   typedef int explicitly_specialized_in_c;
 };
+
+template<typename T> struct MergeTemplateDefinitions {
+  static constexpr int f();
+  static constexpr int g();
+};
+template<typename T> constexpr int MergeTemplateDefinitions<T>::g() { return 2; }

Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=212836&r1=212835&r2=212836&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Fri Jul 11 13:22:58 2014
@@ -110,6 +110,9 @@ void g() {
 static_assert(Outer<int>::Inner<int>::f() == 1, "");
 static_assert(Outer<int>::Inner<int>::g() == 2, "");
 
+static_assert(MergeTemplateDefinitions<int>::f() == 1, "");
+static_assert(MergeTemplateDefinitions<int>::g() == 2, "");
+
 RedeclaredAsFriend<int> raf1;
 RedeclareTemplateAsFriend<double> rtaf;
 RedeclaredAsFriend<double> raf2;





More information about the cfe-commits mailing list