arphaman created this revision. arphaman added reviewers: rjmccall, rsmith. arphaman added a subscriber: cfe-commits. arphaman set the repository for this revision to rL LLVM.
This patch fixes a NULL pointer crash that happens when clang is trying to create an implicit default constructor for a specialization of a record template which is defined in a specialization of a parent record template and has a field declaration with an initializer expression. The following piece of code reproduces this problem: template<typename T> class A { public: template<int i> struct Inner; }; template<> template<int i> struct A<int>::Inner { int member = 42; }; int main(void) { return A<int>::Inner<0>().member; } The crash happens because `CXXRecordDecl::getTemplateInstantiationPattern` returns nil when instantiating `A<int>::Inner<0>`, because it tries to get the instantiation pattern from the declaration of `Inner` (which has no definition and thus no instantiation pattern), rather than the specialized definition of `Inner`. This patch fixes this by making sure that the instantiation pattern comes from the definition rather than the declaration of the record template. Repository: rL LLVM https://reviews.llvm.org/D25942 Files: lib/AST/DeclCXX.cpp test/CodeGenCXX/cxx11-crashes.cpp Index: test/CodeGenCXX/cxx11-crashes.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/cxx11-crashes.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 %s -o - | FileCheck %s + +namespace rd28886662 { + +template<typename T> +class A { +public: + template<int i> + struct Inner; +}; + +template<> +template<int i> +struct A<int>::Inner { + int member = 42; // should be ok +}; + +int foo(void) { + return A<int>::Inner<0>().member; +} + +// CHECK: _ZN10rd288866621AIiE5InnerILi0EEC2Ev +// CHECK: store i32 42, i32* %member + +} Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1347,7 +1347,8 @@ auto From = TD->getInstantiatedFrom(); if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) { while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) { - if (NewCTD->isMemberSpecialization()) + if (NewCTD->isMemberSpecialization() || + !NewCTD->isThisDeclarationADefinition()) break; CTD = NewCTD; }
Index: test/CodeGenCXX/cxx11-crashes.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/cxx11-crashes.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 %s -o - | FileCheck %s + +namespace rd28886662 { + +template<typename T> +class A { +public: + template<int i> + struct Inner; +}; + +template<> +template<int i> +struct A<int>::Inner { + int member = 42; // should be ok +}; + +int foo(void) { + return A<int>::Inner<0>().member; +} + +// CHECK: _ZN10rd288866621AIiE5InnerILi0EEC2Ev +// CHECK: store i32 42, i32* %member + +} Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1347,7 +1347,8 @@ auto From = TD->getInstantiatedFrom(); if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) { while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) { - if (NewCTD->isMemberSpecialization()) + if (NewCTD->isMemberSpecialization() || + !NewCTD->isThisDeclarationADefinition()) break; CTD = NewCTD; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits