From: Eli Friedman Date: Mon, 9 Nov 2009 19:20:36 +0000 (+0000) Subject: Add additional note to mark the cause of synthesized constructors. Mark X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=80c30dad6c6fca077293125a96f464b6c8857171;p=clang Add additional note to mark the cause of synthesized constructors. Mark declaration invalid if the constructor can't be properly built. Addresses remaining review comments from Fariborz for r86500. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86579 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a87bb91122..b78c3994da 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -433,6 +433,8 @@ def err_implicit_object_parameter_init : Error< def note_field_decl : Note<"member is declared here">; def note_previous_class_decl : Note< "%0 declared here">; +def note_ctor_synthesized_at : Note< + "implicit default constructor for %0 first required here">; def err_missing_default_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{base class|member}2 %3 which does not have a default " diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 41f8aec815..dd1af0b64c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1186,7 +1186,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, NumArgs, C, IdLoc, RParenLoc); } -void +bool Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, @@ -1197,6 +1197,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, llvm::SmallVector AllToInit; llvm::DenseMap AllBaseFields; bool HasDependentBaseInit = false; + bool HadError = false; for (unsigned i = 0; i < NumInitializers; i++) { CXXBaseOrMemberInitializer *Member = Initializers[i]; @@ -1258,6 +1259,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, << 0 << VBase->getType(); Diag(VBaseDecl->getLocation(), diag::note_previous_class_decl) << Context.getTagDeclType(VBaseDecl); + HadError = true; continue; } @@ -1307,6 +1309,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, << 0 << Base->getType(); Diag(BaseDecl->getLocation(), diag::note_previous_class_decl) << Context.getTagDeclType(BaseDecl); + HadError = true; continue; } @@ -1378,6 +1381,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, Diag(Field->getLocation(), diag::note_field_decl); Diag(RT->getDecl()->getLocation(), diag::note_previous_class_decl) << Context.getTagDeclType(RT->getDecl()); + HadError = true; continue; } @@ -1399,6 +1403,7 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } } else if (FT->isReferenceType()) { @@ -1406,12 +1411,14 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } else if (FT.isConstQualified()) { Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); + HadError = true; } } @@ -1425,6 +1432,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) baseOrMemberInitializers[Idx] = AllToInit[Idx]; } + + return HadError; } static void *GetKeyForTopLevelField(FieldDecl *Field) { @@ -2957,9 +2966,17 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, !Constructor->isUsed()) && "DefineImplicitDefaultConstructor - call it for implicit default ctor"); - SetBaseOrMemberInitializers(Constructor, 0, 0, true); + CXXRecordDecl *ClassDecl + = cast(Constructor->getDeclContext()); + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - Constructor->setUsed(); + if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) { + Diag(CurrentLocation, diag::note_ctor_synthesized_at) + << Context.getTagDeclType(ClassDecl); + Constructor->setInvalidDecl(); + } else { + Constructor->setUsed(); + } return; } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp index 0b83a1fee0..ad0d506213 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -26,7 +26,7 @@ IntHolder &test_X_IntHolderInt(X xih) { xih.g(); // okay xih.f(); // expected-note{{instantiation}} - X::Inner inner; + X::Inner inner; // expected-note {{first required here}} return X::value; // expected-note{{instantiation}} } diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp index 48c9039863..6adcdca3e1 100644 --- a/test/SemaCXX/default-constructor-initializers.cpp +++ b/test/SemaCXX/default-constructor-initializers.cpp @@ -11,7 +11,7 @@ struct X2 : X1 { // expected-note {{'struct X2' declared here}} \ struct X3 : public X2 { // expected-error {{must explicitly initialize the base class 'struct X2'}} }; -X3 x3; +X3 x3; // expected-note {{first required here}} struct X4 { // expected-error {{must explicitly initialize the member 'x2'}} \ @@ -20,7 +20,7 @@ struct X4 { // expected-error {{must explicitly initialize the member 'x2'}} \ X2 & rx2; // expected-note {{declared at}} }; -X4 x4; +X4 x4; // expected-note {{first required here}} struct Y1 { // has no implicit default constructor @@ -52,5 +52,5 @@ struct Z1 { // expected-error {{must explicitly initialize the reference member volatile int v1; }; -Z1 z1; +Z1 z1; // expected-note {{first required here}} diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp index 3452883697..25d708494b 100644 --- a/test/SemaCXX/value-initialization.cpp +++ b/test/SemaCXX/value-initialization.cpp @@ -6,5 +6,5 @@ struct A { // expected-error {{implicit default constructor for 'struct A' must }; int main () { - (void)A(); + (void)A(); // expected-note {{first required here}} }