r215616 - [modules] Don't assert if the same imported class template specialization

Richard Smith richard-llvm at metafoo.co.uk
Wed Aug 13 20:30:27 PDT 2014


Author: rsmith
Date: Wed Aug 13 22:30:27 2014
New Revision: 215616

URL: http://llvm.org/viewvc/llvm-project?rev=215616&view=rev
Log:
[modules] Don't assert if the same imported class template specialization
declaration has its definition instantiated in two sibling modules and they use
a partial specialization.

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

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=215616&r1=215615&r2=215616&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Aug 13 22:30:27 2014
@@ -2391,8 +2391,14 @@ static DeclContext *getPrimaryContextFor
   if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
     return ND->getOriginalNamespace();
 
+  // There is one tricky case here: if DC is a class with no definition, then
+  // we're merging a declaration whose definition is added by an update record,
+  // but we've not yet loaded that update record. In this case, we use the
+  // canonical declaration for merging until we get a real definition.
+  // FIXME: When we add a definition, we may need to move the partial lookup
+  // information from the canonical declaration onto the chosen definition.
   if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
-    return RD->getDefinition();
+    return RD->getPrimaryContext();
 
   if (EnumDecl *ED = dyn_cast<EnumDecl>(DC))
     return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
@@ -3361,7 +3367,12 @@ void ASTDeclReader::UpdateDecl(Decl *D,
           Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
           auto *TemplArgList = TemplateArgumentList::CreateCopy(
               Reader.getContext(), TemplArgs.data(), TemplArgs.size());
-          Spec->setInstantiationOf(PartialSpec, TemplArgList);
+
+          // FIXME: If we already have a partial specialization set,
+          // check that it matches.
+          if (!Spec->getSpecializedTemplateOrPartial()
+                   .is<ClassTemplatePartialSpecializationDecl *>())
+            Spec->setInstantiationOf(PartialSpec, TemplArgList);
         }
       }
 

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=215616&r1=215615&r2=215616&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-a.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-a.h Wed Aug 13 22:30:27 2014
@@ -58,6 +58,7 @@ template<typename T> struct WithPartialS
   T &f() { static T t; return t; }
 };
 typedef WithPartialSpecializationUse::type WithPartialSpecializationInstantiate;
+typedef WithPartialSpecialization<void(int)>::type WithPartialSpecializationInstantiate2;
 
 template<> struct WithExplicitSpecialization<int> {
   int n;

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-b.h?rev=215616&r1=215615&r2=215616&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-b.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-b.h Wed Aug 13 22:30:27 2014
@@ -57,6 +57,8 @@ template<int> struct UseInt;
 template<typename T> void UseRedeclaredEnum(UseInt<T() + CommonTemplate<char>::a>);
 constexpr void (*UseRedeclaredEnumB)(UseInt<1>) = UseRedeclaredEnum<int>;
 
+typedef WithPartialSpecialization<void(int)>::type WithPartialSpecializationInstantiate3;
+
 template<typename> struct MergeSpecializations;
 template<typename T> struct MergeSpecializations<T&> {
   typedef int partially_specialized_in_b;
@@ -76,4 +78,5 @@ void TriggerInstantiation() {
   UseDefinedInBImpl<void>();
   Std::f<int>();
   PartiallyInstantiatePartialSpec<int*>::foo();
+  WithPartialSpecialization<void(int)>::type x;
 }

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-common.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-common.h?rev=215616&r1=215615&r2=215616&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-common.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-common.h Wed Aug 13 22:30:27 2014
@@ -32,7 +32,9 @@ template<typename T> struct Outer {
 };
 
 template<typename T> struct WithPartialSpecialization {};
+template<typename T> struct WithPartialSpecialization<void(T)> { typedef int type; };
 typedef WithPartialSpecialization<int*> WithPartialSpecializationUse;
+typedef WithPartialSpecialization<void(int)> WithPartialSpecializationUse2;
 
 template<typename T> struct WithExplicitSpecialization;
 typedef WithExplicitSpecialization<int> WithExplicitSpecializationUse;





More information about the cfe-commits mailing list