diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8e3fbda67c5c..d5f93dce2805 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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/clang/test/SemaCXX/value-initialization.cpp b/clang/test/SemaCXX/value-initialization.cpp new file mode 100644 index 000000000000..6b992973614c --- /dev/null +++ b/clang/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'}} +}