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