[PATCH] D25942: Fix crash in implicit default constructor creation for a template record specialization that has a field declaration with an initializer expression

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 25 07:47:08 PDT 2016


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;
       }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25942.75697.patch
Type: text/x-patch
Size: 1171 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161025/44f114a5/attachment.bin>


More information about the cfe-commits mailing list