Looks good. Some comments below. - Thanks, Fariborz
On Nov 8, 2009, at 5:05 PM, Eli Friedman wrote: > Author: efriedma > Date: Sun Nov 8 19:05:47 2009 > New Revision: 86500 > > URL: http://llvm.org/viewvc/llvm-project?rev=86500&view=rev > Log: > Unify the codepaths used to verify base and member initializers for > explicitly > and implicitly defined constructors. This has a number of benefits: > > 1. Less code. > > 2. Explicit and implicit constructors get the same diagnostics. > > 3. The AST explicitly contains constructor calls from implicit default > constructors. This allows handing some cases that previously > weren't handled > correctly in IRGen without any additional code. Specifically, > implicit default > constructors containing calls to constructors with default arguments > are now > handled correctly. Please provide a test case for this situation. > > > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/lib/CodeGen/CGCXX.cpp > cfe/trunk/lib/Sema/Sema.h > cfe/trunk/lib/Sema/SemaDeclCXX.cpp > cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp > cfe/trunk/test/CodeGenCXX/virt.cpp > cfe/trunk/test/SemaCXX/constructor-initializer.cpp > cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp > cfe/trunk/test/SemaCXX/value-initialization.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Nov 8 > 19:05:47 2009 > @@ -430,9 +430,13 @@ > "cannot initialize object parameter of type %0 with an expression " > "of type %1">; > > -def err_missing_default_constructor : Error< > - "default constructor for %1 is missing in initialization of " > - "%select{base class|member}0">; > +def note_field_decl : Note<"member is declared here">; > +def note_previous_class_decl : Note< > + "%0 declared 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 " > + "constructor">; > def err_illegal_union_member : Error< > "union member %0 has a non-trivial %select{constructor|" > "copy constructor|copy assignment operator|destructor}1">; > @@ -763,27 +767,18 @@ > "default arguments cannot be added to an out-of-line definition of > a member " > "of a %select{class template|class template partial specialization| > nested " > "class in a template}0">; > -def note_field_decl : Note<"member is declared here">; > -def err_defining_default_ctor : Error< > - "cannot define the implicit default constructor for %0, because > %select{base class|member's type}1 " > - "%2 does not have any default constructor">; > -def note_previous_class_decl : Note< > - "%0 declared here">; > def err_uninitialized_member_for_assign : Error< > "cannot define the implicit default assignment operator for %0, > because " > "non-static %select{reference|const}1 member %2 can't use default " > "assignment operator">; > def note_first_required_here : Note< > "synthesized method is first required here">; > -def err_unintialized_member : Error< > - "cannot define the implicit default constructor for %0, because " > - "%select{reference|const}1 member %2 cannot be default- > initialized">; > def err_null_intialized_reference_member : Error< > "cannot initialize the member to null in default constructor > because " > "reference member %0 cannot be null-initialized">; > def err_unintialized_member_in_ctor : Error< > - "constructor for %0 must explicitly initialize the " > - "%select{reference|const}1 member %2 ">; > + "%select{|implicit default }0constructor for %1 must explicitly > initialize " > + "the %select{reference|const}2 member %3">; > > def err_use_of_default_argument_to_function_declared_later : Error< > "use of default argument to function %0 that is declared later in > class %1">; > > Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/lib/CodeGen/CGCXX.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun Nov 8 19:05:47 2009 > @@ -1483,64 +1483,6 @@ > PopCXXTemporary(); > } > > - if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) { > - // Nontrivial default constructor with no initializer list. It > may still > - // have bases classes and/or contain non-static data members > which require > - // construction. > - for (CXXRecordDecl::base_class_const_iterator Base = > - ClassDecl->bases_begin(); > - Base != ClassDecl->bases_end(); ++Base) { > - // FIXME. copy assignment of virtual base NYI > - if (Base->isVirtual()) > - continue; > - > - CXXRecordDecl *BaseClassDecl > - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()- > >getDecl()); > - if (BaseClassDecl->hasTrivialConstructor()) > - continue; > - if (CXXConstructorDecl *BaseCX = > - BaseClassDecl->getDefaultConstructor(getContext())) { > - LoadOfThis = LoadCXXThis(); > - llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, > ClassDecl, > - BaseClassDecl, > - / > *NullCheckValue=*/false); > - EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0); > - } > - } > - > - for (CXXRecordDecl::field_iterator Field = ClassDecl- > >field_begin(), > - FieldEnd = ClassDecl->field_end(); > - Field != FieldEnd; ++Field) { > - QualType FieldType = getContext().getCanonicalType((*Field)- > >getType()); > - const ConstantArrayType *Array = > - getContext().getAsConstantArrayType(FieldType); > - if (Array) > - FieldType = getContext().getBaseElementType(FieldType); > - if (!FieldType->getAs<RecordType>() || Field- > >isAnonymousStructOrUnion()) > - continue; > - const RecordType *ClassRec = FieldType->getAs<RecordType>(); > - CXXRecordDecl *MemberClassDecl = > - dyn_cast<CXXRecordDecl>(ClassRec->getDecl()); > - if (!MemberClassDecl || MemberClassDecl- > >hasTrivialConstructor()) > - continue; > - if (CXXConstructorDecl *MamberCX = > - MemberClassDecl->getDefaultConstructor(getContext())) { > - LoadOfThis = LoadCXXThis(); > - LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, > 0); > - if (Array) { > - const llvm::Type *BasePtr = ConvertType(FieldType); > - BasePtr = llvm::PointerType::getUnqual(BasePtr); > - llvm::Value *BaseAddrPtr = > - Builder.CreateBitCast(LHS.getAddress(), BasePtr); > - EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr); > - } > - else > - EmitCXXConstructorCall(MamberCX, Ctor_Complete, > LHS.getAddress(), > - 0, 0); > - } > - } > - } > - > // Initialize the vtable pointer > if (ClassDecl->isDynamicClass()) { > if (!LoadOfThis) > > Modified: cfe/trunk/lib/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/lib/Sema/Sema.h (original) > +++ cfe/trunk/lib/Sema/Sema.h Sun Nov 8 19:05:47 2009 > @@ -1747,11 +1747,6 @@ > const FunctionProtoType *Proto, > Expr **Args, unsigned NumArgs, > SourceLocation RParenLoc); > - void BuildBaseOrMemberInitializers(ASTContext &C, > - CXXConstructorDecl *Constructor, > - CXXBaseOrMemberInitializer > **Initializers, > - unsigned NumInitializers > - ); > > void DeconstructCallFunction(Expr *FnExpr, > NamedDecl *&Function, > @@ -2280,8 +2275,7 @@ > void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, > CXXBaseOrMemberInitializer > **Initializers, > unsigned NumInitializers, > - > llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, > - llvm::SmallVectorImpl<FieldDecl > *>&Members); > + bool IsImplicitConstructor); > > /// computeBaseOrMembersToDestroy - Compute information in current > /// destructor decl's AST of bases and non-static data members > which will be > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Nov 8 19:05:47 2009 > @@ -1190,8 +1190,7 @@ > Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, > CXXBaseOrMemberInitializer > **Initializers, > unsigned NumInitializers, > - > llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, > - llvm::SmallVectorImpl<FieldDecl > *>&Fields) { > + bool IsImplicitConstructor) { > // We need to build the initializer AST according to order of > construction > // and not what user specified in the Initializers list. > CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor- > >getDeclContext()); > @@ -1254,7 +1253,11 @@ > assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl > null"); > CXXConstructorDecl *Ctor = VBaseDecl- > >getDefaultConstructor(Context); > if (!Ctor) { > - Bases.push_back(VBase); > + Diag(Constructor->getLocation(), > diag::err_missing_default_ctor) > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 0 << VBase->getType(); > + Diag(VBaseDecl->getLocation(), > diag::note_previous_class_decl) > + << Context.getTagDeclType(VBaseDecl); > continue; > } > > @@ -1299,7 +1302,11 @@ > assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl > null"); > CXXConstructorDecl *Ctor = BaseDecl- > >getDefaultConstructor(Context); > if (!Ctor) { > - Bases.push_back(Base); > + Diag(Constructor->getLocation(), > diag::err_missing_default_ctor) > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 0 << Base->getType(); > + Diag(BaseDecl->getLocation(), > diag::note_previous_class_decl) > + << Context.getTagDeclType(BaseDecl); > continue; > } > > @@ -1357,17 +1364,20 @@ > continue; > } > > - if ((*Field)->getType()->isDependentType()) { > - Fields.push_back(*Field); > + if ((*Field)->getType()->isDependentType()) > continue; > - } Yes. good point. > > > QualType FT = Context.getBaseElementType((*Field)->getType()); > if (const RecordType* RT = FT->getAs<RecordType>()) { > CXXConstructorDecl *Ctor = > cast<CXXRecordDecl>(RT->getDecl())- > >getDefaultConstructor(Context); > if (!Ctor) { > - Fields.push_back(*Field); > + Diag(Constructor->getLocation(), > diag::err_missing_default_ctor) > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 1 << (*Field)->getDeclName(); > + Diag(Field->getLocation(), diag::note_field_decl); > + Diag(RT->getDecl()->getLocation(), > diag::note_previous_class_decl) > + << Context.getTagDeclType(RT->getDecl()); > continue; > } > > @@ -1383,22 +1393,24 @@ > SourceLocation()); > > AllToInit.push_back(Member); > - if (Ctor) > - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); > - if (FT.isConstQualified() && (!Ctor || Ctor->isTrivial())) { > + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); > + if (FT.isConstQualified() && Ctor->isTrivial()) { > Diag(Constructor->getLocation(), > diag::err_unintialized_member_in_ctor) > - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)- > >getDeclName(); > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 1 << (*Field)->getDeclName(); > Diag((*Field)->getLocation(), diag::note_declared_at); > } > } > else if (FT->isReferenceType()) { > Diag(Constructor->getLocation(), > diag::err_unintialized_member_in_ctor) > - << Context.getTagDeclType(ClassDecl) << 0 << (*Field)- > >getDeclName(); > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 0 << (*Field)->getDeclName(); > Diag((*Field)->getLocation(), diag::note_declared_at); > } > else if (FT.isConstQualified()) { > Diag(Constructor->getLocation(), > diag::err_unintialized_member_in_ctor) > - << Context.getTagDeclType(ClassDecl) << 1 << (*Field)- > >getDeclName(); > + << (int)IsImplicitConstructor << > Context.getTagDeclType(ClassDecl) > + << 1 << (*Field)->getDeclName(); > Diag((*Field)->getLocation(), diag::note_declared_at); > } > } > @@ -1415,29 +1427,6 @@ > } > } > > -void > -Sema::BuildBaseOrMemberInitializers(ASTContext &C, > - CXXConstructorDecl *Constructor, > - CXXBaseOrMemberInitializer > **Initializers, > - unsigned NumInitializers > - ) { > - llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; > - llvm::SmallVector<FieldDecl *, 4> Members; > - > - SetBaseOrMemberInitializers(Constructor, > - Initializers, NumInitializers, Bases, > Members); > - for (unsigned int i = 0; i < Bases.size(); i++) { > - if (!Bases[i]->getType()->isDependentType()) > - Diag(Bases[i]->getSourceRange().getBegin(), > - diag::err_missing_default_constructor) << 0 << Bases[i]- > >getType(); > - } > - for (unsigned int i = 0; i < Members.size(); i++) { > - if (!Members[i]->getType()->isDependentType()) > - Diag(Members[i]->getLocation(), > diag::err_missing_default_constructor) > - << 1 << Members[i]->getType(); > - } > -} > - > static void *GetKeyForTopLevelField(FieldDecl *Field) { > // For anonymous unions, use the class declaration as the key. > if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { > @@ -1462,7 +1451,7 @@ > if (Member->isMemberInitializer()) { > FieldDecl *Field = Member->getMember(); > > - // After BuildBaseOrMemberInitializers call, Field is the > anonymous union > + // After SetBaseOrMemberInitializers call, Field is the > anonymous union > // data member of the class. Data member used in the initializer > list is > // in AnonUnionMember field. > if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) > @@ -1527,9 +1516,9 @@ > return; > } > > - BuildBaseOrMemberInitializers(Context, Constructor, > + SetBaseOrMemberInitializers(Constructor, > reinterpret_cast<CXXBaseOrMemberInitializer > **>(MemInits), > - NumMemInits); > + NumMemInits, false); > > if (Constructor->isDependentContext()) > return; > @@ -1694,9 +1683,7 @@ > > if (CXXConstructorDecl *Constructor > = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) > - BuildBaseOrMemberInitializers(Context, > - Constructor, > - (CXXBaseOrMemberInitializer > **)0, 0); > + SetBaseOrMemberInitializers(Constructor, 0, 0, false); > } > > namespace { > @@ -2973,67 +2960,11 @@ > CXXRecordDecl *ClassDecl > = cast<CXXRecordDecl>(Constructor->getDeclContext()); > assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid > constructor"); > - // Before the implicitly-declared default constructor for a class > is > - // implicitly defined, all the implicitly-declared default > constructors > - // for its base class and its non-static data members shall have > been > - // implicitly defined. > - bool err = false; > - for (CXXRecordDecl::base_class_iterator Base = ClassDecl- > >bases_begin(), > - E = ClassDecl->bases_end(); Base != E; ++Base) { > - CXXRecordDecl *BaseClassDecl > - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()- > >getDecl()); > - if (!BaseClassDecl->hasTrivialConstructor()) { > - if (CXXConstructorDecl *BaseCtor = > - BaseClassDecl->getDefaultConstructor(Context)) > - MarkDeclarationReferenced(CurrentLocation, BaseCtor); > - else { > - Diag(CurrentLocation, diag::err_defining_default_ctor) > - << Context.getTagDeclType(ClassDecl) << 0 > - << Context.getTagDeclType(BaseClassDecl); > - Diag(BaseClassDecl->getLocation(), > diag::note_previous_class_decl) > - << Context.getTagDeclType(BaseClassDecl); > - err = true; > - } > - } > - } > - for (CXXRecordDecl::field_iterator Field = ClassDecl- > >field_begin(), > - E = ClassDecl->field_end(); Field != E; ++Field) { > - QualType FieldType = Context.getCanonicalType((*Field)- > >getType()); > - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) > - FieldType = Array->getElementType(); > - if (const RecordType *FieldClassType = FieldType- > >getAs<RecordType>()) { > - CXXRecordDecl *FieldClassDecl > - = cast<CXXRecordDecl>(FieldClassType->getDecl()); > - if (!FieldClassDecl->hasTrivialConstructor()) { > - if (CXXConstructorDecl *FieldCtor = > - FieldClassDecl->getDefaultConstructor(Context)) > - MarkDeclarationReferenced(CurrentLocation, FieldCtor); > - else { > - Diag(CurrentLocation, diag::err_defining_default_ctor) > - << Context.getTagDeclType(ClassDecl) << 1 << > - Context.getTagDeclType(FieldClassDecl); > - Diag((*Field)->getLocation(), diag::note_field_decl); > - Diag(FieldClassDecl->getLocation(), > diag::note_previous_class_decl) > - << Context.getTagDeclType(FieldClassDecl); > - err = true; > - } > - } > - } else if (FieldType->isReferenceType()) { > - Diag(CurrentLocation, diag::err_unintialized_member) > - << Context.getTagDeclType(ClassDecl) << 0 << Field- > >getDeclName(); > - Diag((*Field)->getLocation(), diag::note_declared_at); > - err = true; > - } else if (FieldType.isConstQualified()) { > - Diag(CurrentLocation, diag::err_unintialized_member) > - << Context.getTagDeclType(ClassDecl) << 1 << Field- > >getDeclName(); > - Diag((*Field)->getLocation(), diag::note_declared_at); > - err = true; > - } > - } > - if (!err) > - Constructor->setUsed(); > - else > - Constructor->setInvalidDecl(); > + We need to make the Constructor invalid. This changes that. > > + SetBaseOrMemberInitializers(Constructor, 0, 0, true); > + > + Constructor->setUsed(); > + return; > } > > void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, > > Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp (original) > +++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp Sun Nov > 8 19:05:47 2009 > @@ -12,7 +12,7 @@ > > void g() { } > > - struct Inner { > + struct Inner { // expected-error{{implicit default}} > T value; // expected-note {{member is declared here}} > }; > > @@ -26,8 +26,7 @@ > xih.g(); // okay > xih.f(); // expected-note{{instantiation}} > > - // FIXME: diagnostic here has incorrect reason (PR5154) > - X<IntHolder, int>::Inner inner; // expected-error{{implicit > default}} > + X<IntHolder, int>::Inner inner; > > return X<IntHolder, int>::value; // expected-note{{instantiation}} > } > > Modified: cfe/trunk/test/CodeGenCXX/virt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virt.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/CodeGenCXX/virt.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/virt.cpp Sun Nov 8 19:05:47 2009 > @@ -4,6 +4,7 @@ > // RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -emit-llvm > %s -o %t-64.ll > // RUN: FileCheck -check-prefix LPLL64 --input-file=%t-64.ll %s > > +// XFAIL: * > > struct B { > virtual void bar1(); > > Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original) > +++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Sun Nov 8 > 19:05:47 2009 > @@ -99,7 +99,9 @@ > > // FIXME. This is bad message! > struct M { // expected-note {{candidate function}} \ > - // expected-note {{candidate function}} > + // expected-note {{candidate function}} \ > + // expected-note {{declared here}} \ > + // expected-note {{declared here}} > M(int i, int j); // expected-note {{candidate function}} \ > // // expected-note {{candidate function}} > }; > @@ -110,9 +112,10 @@ > M m1; > }; > > -struct P : M { // expected-error {{default constructor for 'struct > M' is missing in initialization of base class}} > - P() { } > - M m; // expected-error {{default constructor for 'struct M' is > missing in initialization of member}} > +struct P : M { > + P() { } // expected-error {{base class 'struct M'}} \ > + // expected-error {{member 'm'}} > + M m; // expected-note {{member is declared here}} > }; > > struct Q { > > Modified: cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp > (original) > +++ cfe/trunk/test/SemaCXX/default-constructor-initializers.cpp Sun > Nov 8 19:05:47 2009 > @@ -9,18 +9,18 @@ > X2(int); > }; > > -struct X3 : public X2 { > +struct X3 : public X2 { // expected-error {{must explicitly > initialize the base class 'struct X2'}} > }; > -X3 x3; // expected-error {{cannot define the implicit default > constructor for 'struct X3', because base class 'struct X2' does not > have any default constructor}} > +X3 x3; > > > -struct X4 { > +struct X4 { // expected-error {{must explicitly initialize the > member 'x2'}} \ > + // expected-error {{must explicitly initialize the > reference member 'rx2'}} > X2 x2; // expected-note {{member is declared here}} > X2 & rx2; // expected-note {{declared at}} > }; > > -X4 x4; // expected-error {{cannot define the implicit default > constructor for 'struct X4', because member's type 'struct X2' does > not have any default constructor}} \ > - // expected-error {{cannot define the implicit default > constructor for 'struct X4', because reference member 'rx2' cannot > be default-initialized}} > +X4 x4; This is important omission of diagnostics at point of declarations which prompted error on constructor synthesis. Please restore them. - Thanks, Fariborz > > > > struct Y1 { // has no implicit default constructor > @@ -45,12 +45,12 @@ > // More tests > > > -struct Z1 { > +struct Z1 { // expected-error {{must explicitly initialize the > reference member 'z'}} \ > + // expected-error {{must explicitly initialize the > const member 'c1'}} > int& z; // expected-note {{declared at}} > const int c1; // expected-note {{declared at}} > volatile int v1; > }; > > -Z1 z1; // expected-error {{cannot define the implicit default > constructor for 'struct Z1', because reference member 'z' cannot be > default-initialized}} \ > - // expected-error {{cannot define the implicit default > constructor for 'struct Z1', because const member 'c1' cannot be > default-initialized}} > +Z1 z1; > > > Modified: cfe/trunk/test/SemaCXX/value-initialization.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/value-initialization.cpp?rev=86500&r1=86499&r2=86500&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- cfe/trunk/test/SemaCXX/value-initialization.cpp (original) > +++ cfe/trunk/test/SemaCXX/value-initialization.cpp Sun Nov 8 > 19:05:47 2009 > @@ -1,10 +1,10 @@ > // RUN: clang-cc -fsyntax-only -verify %s -std=c++0x > > -struct A { > +struct A { // expected-error {{implicit default constructor for > 'struct A' must explicitly initialize the const member 'i'}} > const int i; // expected-note {{declared at}} > virtual void f() { } > }; > > int main () { > - (void)A(); // expected-error {{cannot define the implicit > default constructor for 'struct A', because const member 'i' cannot > be default-initialized}} > + (void)A(); > } > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
