From: Fariborz Jahanian Date: Tue, 27 Oct 2009 16:51:19 +0000 (+0000) Subject: Generate constructor for value-initialization cases, even if the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6c813e1cb719a328f01619c3d44910be4e79e4d5;p=clang Generate constructor for value-initialization cases, even if the implementation technique doesn't call the constructor at that point. DR302. Fixes pr5296. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85249 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8e3fbda67c..d5f93dce28 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -288,7 +288,20 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, << FullRange); assert(NumExprs == 0 && "Expected 0 expressions"); - + + if (const RecordType *Record = Ty->getAs()) { + if (!Record->getDecl()->isUnion()) { + // As clarified in C++ DR302, generate constructor for + // value-initialization cases, even if the implementation technique + // doesn't call the constructor at that point. + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + (void)PerformInitializationByConstructor(Ty, MultiExprArg(*this, 0, 0), + TypeRange.getBegin(), + TypeRange, DeclarationName(), + IK_Default, ConstructorArgs); + } + } + // C++ [expr.type.conv]p2: // The expression T(), where T is a simple-type-specifier for a non-array // complete object type or the (possibly cv-qualified) void type, creates an @@ -489,7 +502,21 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(StartLoc, diag::err_new_uninitialized_const) << TypeRange); } else if (NumConsArgs == 0) { - // Object is value-initialized. Do nothing. + // Object is value-initialized. + if (const RecordType *Record = AllocType->getAs()) { + if (!Record->getDecl()->isUnion()) { + // As clarified in C++ DR302, generate constructor for + // value-initialization cases, even if the implementation technique + // doesn't call the constructor at that point. + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); + (void)PerformInitializationByConstructor(AllocType, + MultiExprArg(*this, 0, 0), + TypeRange.getBegin(), + TypeRange, DeclarationName(), + IK_Default, + ConstructorArgs); + } + } } else if (NumConsArgs == 1) { // Object is direct-initialized. // FIXME: What DeclarationName do we pass in here? diff --git a/test/SemaCXX/value-initialization.cpp b/test/SemaCXX/value-initialization.cpp new file mode 100644 index 0000000000..6b99297361 --- /dev/null +++ b/test/SemaCXX/value-initialization.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +struct A { + ~A(); + const int i; // expected-note {{declared at}} +}; + +struct B { + // B is a non-POD with no user-written constructor. + // It has a nontrivial generated constructor. + const int i[12]; // expected-note {{declared at}} + A a; +}; + +int main () { + // Value-initializing a "B" doesn't call the default constructor for + // "B"; it value-initializes the members of B. Therefore it shouldn't + // cause an error on generation of the default constructor for the + // following: + new B(); // expected-error {{cannot define the implicit default constructor for 'struct B', because const member 'i'}} + (void)B(); + (void)A(); // expected-error {{cannot define the implicit default constructor for 'struct A', because const member 'i'}} +}