diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-26 10:50:32 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-26 10:50:32 +0000 |
commit | ea7c1e24f33c554aeac07dc4f6dc7493dd98e272 (patch) | |
tree | 40ff151ca0fb89cb407b99d568831878a678c82b | |
parent | 2229d5731032617acc6aa30657ce03423fb02083 (diff) |
Don't assert when trying to diagnose why a class with a constructor template is
non-trivial.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151486 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 34 | ||||
-rw-r--r-- | test/CXX/class/class.union/p1.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-nontrivial-union.cpp | 4 |
3 files changed, 33 insertions, 9 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 05136b882b..f091d858b5 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index 54b256e3c2..f344ae5b01 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -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}} diff --git a/test/SemaCXX/cxx0x-nontrivial-union.cpp b/test/SemaCXX/cxx0x-nontrivial-union.cpp index 2bf7056521..e706d7346d 100644 --- a/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -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; }; |