]> granicus.if.org Git - clang/commitdiff
Don't assert when trying to diagnose why a class with a constructor template is
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 26 Feb 2012 10:50:32 +0000 (10:50 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 26 Feb 2012 10:50:32 +0000 (10:50 +0000)
non-trivial.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151486 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/CXX/class/class.union/p1.cpp
test/SemaCXX/cxx0x-nontrivial-union.cpp

index 05136b882bd6f3cc04616cb16488a3adfedb0ded..f091d858b533398bfc1fcea75edfb15b927d45ef 100644 (file)
@@ -8935,6 +8935,19 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) {
   return false;
 }
 
+/// If the given constructor is user-provided, produce a diagnostic explaining
+/// that it makes the class non-trivial.
+static bool DiagnoseNontrivialUserProvidedCtor(Sema &S, QualType QT,
+                                               CXXConstructorDecl *CD,
+                                               Sema::CXXSpecialMember CSM) {
+  if (!CD->isUserProvided())
+    return false;
+
+  SourceLocation CtorLoc = CD->getLocation();
+  S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM;
+  return true;
+}
+
 /// DiagnoseNontrivial - Given that a class has a non-trivial
 /// special member, figure out why.
 void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
@@ -8949,17 +8962,20 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
   case CXXDefaultConstructor:
     if (RD->hasUserDeclaredConstructor()) {
       typedef CXXRecordDecl::ctor_iterator ctor_iter;
-      for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){
-        const FunctionDecl *body = 0;
-        ci->hasBody(body);
-        if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) {
-          SourceLocation CtorLoc = ci->getLocation();
-          Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member;
+      for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI)
+        if (DiagnoseNontrivialUserProvidedCtor(*this, QT, *CI, member))
           return;
-        }
-      }
 
-      llvm_unreachable("found no user-declared constructors");
+      // No user-provided constructors; look for constructor templates.
+      typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl>
+          tmpl_iter;
+      for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end());
+           TI != TE; ++TI) {
+        CXXConstructorDecl *CD =
+            dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl());
+        if (CD && DiagnoseNontrivialUserProvidedCtor(*this, QT, CD, member))
+          return;
+      }
     }
     break;
 
index 54b256e3c2158fdba11d2b9361e741f59c2585c5..f344ae5b01fb49b7ae88b96fca6cc996927484ee 100644 (file)
@@ -19,6 +19,9 @@ class Ctor {
 class Ctor2 {
   Ctor2(); // expected-note 3 {{because type 'Ctor2' has a user-declared constructor}}
 };
+class CtorTmpl {
+  template<typename T> CtorTmpl(); // expected-note {{because type 'CtorTmpl' has a user-declared constructor}}
+};
 
 class CopyCtor {
   CopyCtor(CopyCtor &cc) { abort(); } // expected-note 4 {{because type 'CopyCtor' has a user-declared copy constructor}}
@@ -38,6 +41,7 @@ union U1 {
   VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}}
   Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}}
   Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial constructor}}
+  CtorTmpl ctortmpl; // expected-error {{union member 'ctortmpl' has a non-trivial constructor}}
   CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
   CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
   Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
index 2bf7056521b7f819fdaffc065f02fc7a3a53c39b..e706d7346d9642e698adcc7261ab196cfe55b108 100644 (file)
@@ -25,3 +25,7 @@ struct s {
     non_trivial nt;
   };
 };
+
+// Don't crash on this.
+struct TemplateCtor { template<typename T> TemplateCtor(T); };
+union TemplateCtorMember { TemplateCtor s; };