diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-16 10:58:10 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-16 10:58:10 +0000 |
commit | 5f688f4b15d02aa7ad159c46b1f78fe59d412f12 (patch) | |
tree | 8b67f7660948832957b76569958a3bda8d15fe75 /lib | |
parent | 13ca53473fd98520b236fb2dbfce228007ac4bed (diff) |
Make CXXNewExpr contain only a single initialier, and not hold the used constructor itself.
Holding the constructor directly makes no sense when list-initialized arrays come into play. The constructor is now held in a CXXConstructExpr, if construction is what is done. The new design can also distinguish properly between list-initialization and direct-initialization, as well as implicit default-initialization constructors and explicit value-initialization constructors. Finally, doing it this way removes redundance from the AST because CXXNewExpr doesn't try to handle both the allocation and the initialization responsibilities.
This breaks the static analysis of new expressions. I've filed PR12014 to track this.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150682 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 69 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 16 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 18 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 51 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 176 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 58 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 15 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 13 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 |
13 files changed, 218 insertions, 232 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index f9f7ba542c..4b19031852 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2041,10 +2041,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { if (isTypeDependent()) CT = CT_Dependent; else - CT = MergeCanThrow( - CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()), - CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(), - /*NullThrows*/false)); + CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index e09d88091b..718010b81e 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -45,30 +45,26 @@ SourceRange CXXScalarValueInitExpr::getSourceRange() const { // CXXNewExpr CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - Expr **placementArgs, unsigned numPlaceArgs, - SourceRange TypeIdParens, Expr *arraySize, - CXXConstructorDecl *constructor, bool initializer, - Expr **constructorArgs, unsigned numConsArgs, - bool HadMultipleCandidates, FunctionDecl *operatorDelete, - bool usualArrayDeleteWantsSize, QualType ty, - TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc, - SourceLocation constructorLParen, - SourceLocation constructorRParen) + bool usualArrayDeleteWantsSize, + Expr **placementArgs, unsigned numPlaceArgs, + SourceRange typeIdParens, Expr *arraySize, + InitializationStyle initializationStyle, + Expr *initializer, QualType ty, + TypeSourceInfo *allocatedTypeInfo, + SourceLocation startLoc, SourceRange directInitRange) : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), ty->isDependentType(), ty->isInstantiationDependentType(), ty->containsUnexpandedParameterPack()), - GlobalNew(globalNew), Initializer(initializer), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), - HadMultipleCandidates(HadMultipleCandidates), - SubExprs(0), OperatorNew(operatorNew), - OperatorDelete(operatorDelete), Constructor(constructor), - AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), - StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen), - ConstructorRParen(constructorRParen) { - AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); + GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), + SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), + AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), + StartLoc(startLoc), DirectInitRange(directInitRange) { + assert((initializer != 0 || initializationStyle == NoInit) && + "Only NoInit can have no initializer."); + StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; + AllocateArgsArray(C, arraySize != 0, numPlaceArgs, initializer != 0); unsigned i = 0; if (Array) { if (arraySize->isInstantiationDependent()) @@ -80,33 +76,33 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = arraySize; } - for (unsigned j = 0; j < NumPlacementArgs; ++j) { - if (placementArgs[j]->isInstantiationDependent()) + if (initializer) { + if (initializer->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (placementArgs[j]->containsUnexpandedParameterPack()) + + if (initializer->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = placementArgs[j]; + SubExprs[i++] = initializer; } - for (unsigned j = 0; j < NumConstructorArgs; ++j) { - if (constructorArgs[j]->isInstantiationDependent()) + for (unsigned j = 0; j < NumPlacementArgs; ++j) { + if (placementArgs[j]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (constructorArgs[j]->containsUnexpandedParameterPack()) + if (placementArgs[j]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = constructorArgs[j]; + SubExprs[i++] = placementArgs[j]; } } void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, - unsigned numPlaceArgs, unsigned numConsArgs){ + unsigned numPlaceArgs, bool hasInitializer){ assert(SubExprs == 0 && "SubExprs already allocated"); Array = isArray; NumPlacementArgs = numPlaceArgs; - NumConstructorArgs = numConsArgs; - - unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; + + unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; SubExprs = new (C) Stmt*[TotalSize]; } @@ -115,6 +111,17 @@ bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const { castAs<FunctionProtoType>()->isNothrow(Ctx); } +SourceLocation CXXNewExpr::getEndLoc() const { + switch (getInitializationStyle()) { + case NoInit: + return AllocatedTypeInfo->getTypeLoc().getEndLoc(); + case CallInit: + return DirectInitRange.getEnd(); + case ListInit: + return getInitializer()->getSourceRange().getEnd(); + } +} + // CXXDeleteExpr QualType CXXDeleteExpr::getDestroyedType() const { const Expr *Arg = getArgument(); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 7df8f6fc6b..4843716909 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2351,10 +2351,20 @@ recurse: Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { + // FIXME: Does this mean "parenthesized initializer"? Out << "pi"; - for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(), - E = New->constructor_arg_end(); I != E; ++I) - mangleExpression(*I); + const Expr *Init = New->getInitializer(); + if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) { + // Directly inline the initializers. + for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(), + E = CCE->arg_end(); + I != E; ++I) + mangleExpression(*I); + } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) { + for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) + mangleExpression(PLE->getExpr(i)); + } else + mangleExpression(Init); } Out << 'E'; break; diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 746049b166..c83bfad1c2 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1390,17 +1390,13 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << ")"; - if (E->hasInitializer()) { - OS << "("; - unsigned NumCons = E->getNumConstructorArgs(); - if (NumCons > 0) { - PrintExpr(E->getConstructorArg(0)); - for (unsigned i = 1; i < NumCons; ++i) { - OS << ", "; - PrintExpr(E->getConstructorArg(i)); - } - } - OS << ")"; + CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); + if (InitStyle) { + if (InitStyle == CXXNewExpr::CallInit) + OS << "("; + PrintExpr(E->getInitializer()); + if (InitStyle == CXXNewExpr::CallInit) + OS << ")"; } } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 1d58fd7b2b..fdd0c8502d 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -825,13 +825,11 @@ void StmtProfiler::VisitCXXNewExpr(const CXXNewExpr *S) { VisitType(S->getAllocatedType()); VisitDecl(S->getOperatorNew()); VisitDecl(S->getOperatorDelete()); - VisitDecl(S->getConstructor()); ID.AddBoolean(S->isArray()); ID.AddInteger(S->getNumPlacementArgs()); ID.AddBoolean(S->isGlobalNew()); ID.AddBoolean(S->isParenTypeId()); - ID.AddBoolean(S->hasInitializer()); - ID.AddInteger(S->getNumConstructorArgs()); + ID.AddInteger(S->getInitializationStyle()); } void diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 7b1ae1cc24..12bdc7e43f 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -743,11 +743,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E, llvm::Value *NewPtr) { - - assert(E->getNumConstructorArgs() == 1 && - "Can only have one argument to initializer of POD type."); - - const Expr *Init = E->getConstructorArg(0); + + const Expr *Init = E->getInitializer(); QualType AllocType = E->getAllocatedType(); CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType); @@ -773,9 +770,8 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Value *beginPtr, llvm::Value *numElements) { - // We have a POD type. - if (E->getNumConstructorArgs() == 0) - return; + if (!E->hasInitializer()) + return; // We have a POD type. // Check if the number of elements is constant. bool checkZero = true; @@ -858,13 +854,15 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, llvm::Value *NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie) { + const Expr *Init = E->getInitializer(); if (E->isArray()) { - if (CXXConstructorDecl *Ctor = E->getConstructor()) { + if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)){ + CXXConstructorDecl *Ctor = CCE->getConstructor(); bool RequiresZeroInitialization = false; if (Ctor->getParent()->hasTrivialDefaultConstructor()) { // If new expression did not specify value-initialization, then there // is no initialization. - if (!E->hasInitializer() || Ctor->getParent()->isEmpty()) + if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty()) return; if (CGF.CGM.getTypes().isZeroInitializable(ElementType)) { @@ -877,43 +875,38 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, RequiresZeroInitialization = true; } - CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, - E->constructor_arg_begin(), - E->constructor_arg_end(), + CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, + CCE->arg_begin(), CCE->arg_end(), RequiresZeroInitialization); return; - } else if (E->getNumConstructorArgs() == 1 && - isa<ImplicitValueInitExpr>(E->getConstructorArg(0)) && + } else if (Init && isa<ImplicitValueInitExpr>(Init) && CGF.CGM.getTypes().isZeroInitializable(ElementType)) { // Optimization: since zero initialization will just set the memory // to all zeroes, generate a single memset to do it in one shot. EmitZeroMemSet(CGF, ElementType, NewPtr, AllocSizeWithoutCookie); return; - } else { - CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements); - return; } + CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements); + return; } - if (CXXConstructorDecl *Ctor = E->getConstructor()) { + if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)) { + CXXConstructorDecl *Ctor = CCE->getConstructor(); // Per C++ [expr.new]p15, if we have an initializer, then we're performing // direct initialization. C++ [dcl.init]p5 requires that we // zero-initialize storage if there are no user-declared constructors. - if (E->hasInitializer() && - !Ctor->getParent()->hasUserDeclaredConstructor() && + if (!Ctor->getParent()->hasUserDeclaredConstructor() && !Ctor->getParent()->isEmpty()) CGF.EmitNullInitialization(NewPtr, ElementType); - - CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, - NewPtr, E->constructor_arg_begin(), - E->constructor_arg_end()); + CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false, + NewPtr, CCE->arg_begin(), CCE->arg_end()); return; } // We have a POD type. - if (E->getNumConstructorArgs() == 0) + if (!Init) return; - + StoreAnyExprIntoOneUnit(CGF, E, NewPtr); } @@ -1145,7 +1138,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // CXXNewExpr::shouldNullCheckAllocation()) and we have an // interesting initializer. bool nullCheck = allocatorType->isNothrow(getContext()) && - !(allocType.isPODType(getContext()) && !E->hasInitializer()); + (!allocType.isPODType(getContext()) || E->hasInitializer()); llvm::BasicBlock *nullCheckBB = 0; llvm::BasicBlock *contBB = 0; @@ -1211,7 +1204,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { DeactivateCleanupBlock(operatorDeleteCleanup, cleanupDominator); cleanupDominator->eraseFromParent(); } - + if (nullCheck) { conditional.end(*this); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 5996e2a264..7185e93a11 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2193,10 +2193,11 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return ExprError(); } - ExprVector ConstructorArgs(Actions); - SourceLocation ConstructorLParen, ConstructorRParen; + ExprResult Initializer; if (Tok.is(tok::l_paren)) { + SourceLocation ConstructorLParen, ConstructorRParen; + ExprVector ConstructorArgs(Actions); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); ConstructorLParen = T.getOpenLocation(); @@ -2213,19 +2214,20 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); } + Initializer = Actions.ActOnParenListExpr(ConstructorLParen, + ConstructorRParen, + move_arg(ConstructorArgs)); } else if (Tok.is(tok::l_brace) && getLang().CPlusPlus0x) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_generalized_initializer_lists); - ExprResult InitList = ParseBraceInitializer(); - if (InitList.isInvalid()) - return InitList; - ConstructorArgs.push_back(InitList.take()); + Initializer = ParseBraceInitializer(); } + if (Initializer.isInvalid()) + return Initializer; return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, move_arg(PlacementArgs), PlacementRParen, - TypeIdParens, DeclaratorInfo, ConstructorLParen, - move_arg(ConstructorArgs), ConstructorRParen); + TypeIdParens, DeclaratorInfo, Initializer.take()); } /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7fee518d2c..6b66a42ad3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10148,15 +10148,13 @@ namespace { } void VisitCXXNewExpr(CXXNewExpr *E) { - if (E->getConstructor()) - S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor()); if (E->getOperatorNew()) S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew()); if (E->getOperatorDelete()) S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); Inherited::VisitCXXNewExpr(E); } - + void VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (E->getOperatorDelete()) S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete()); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 4ffdb3e5c1..dfa2148fc3 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -914,9 +914,7 @@ ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, - Declarator &D, SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { + Declarator &D, Expr *Initializer) { bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; Expr *ArraySize = 0; @@ -961,6 +959,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (D.isInvalidType()) return ExprError(); + SourceRange DirectInitRange; + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) + DirectInitRange = List->getSourceRange(); + return BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), @@ -969,12 +971,27 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, AllocType, TInfo, ArraySize, - ConstructorLParen, - move(ConstructorArgs), - ConstructorRParen, + DirectInitRange, + Initializer, TypeContainsAuto); } +static bool isLegalArrayNewInitializer(Expr *Init) { + if (!Init) + return true; + if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) { + if (PLE->getNumExprs() != 1) + return PLE->getNumExprs() == 0; + Init = PLE->getExpr(0); + } + if (isa<ImplicitValueInitExpr>(Init)) + return true; + else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) + return !CCE->isListInitialization() && + CCE->getConstructor()->isDefaultConstructor(); + return false; +} + ExprResult Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, @@ -984,29 +1001,56 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen, + SourceRange DirectInitRange, + Expr *Initializer, bool TypeMayContainAuto) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); + CXXNewExpr::InitializationStyle initStyle; + if (DirectInitRange.isValid()) { + assert(Initializer && "Have parens but no initializer."); + initStyle = CXXNewExpr::CallInit; + } else if (Initializer && isa<InitListExpr>(Initializer)) + initStyle = CXXNewExpr::ListInit; + else { + assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || + isa<CXXConstructExpr>(Initializer)) && + "Initializer expression that cannot have been implicitly created."); + initStyle = CXXNewExpr::NoInit; + } + + Expr **Inits = &Initializer; + unsigned NumInits = Initializer ? 1 : 0; + if (initStyle == CXXNewExpr::CallInit) { + if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) { + Inits = List->getExprs(); + NumInits = List->getNumExprs(); + } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){ + if (!isa<CXXTemporaryObjectExpr>(CCE)) { + // Can happen in template instantiation. Since this is just an implicit + // construction, we just take it apart and rebuild it. + Inits = CCE->getArgs(); + NumInits = CCE->getNumArgs(); + } + } + } + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && AllocType->getContainedAutoType()) { - if (ConstructorArgs.size() == 0) + if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); - if (ConstructorArgs.size() != 1) { - Expr *FirstBad = ConstructorArgs.get()[1]; + if (initStyle == CXXNewExpr::ListInit) + return ExprError(Diag(Inits[0]->getSourceRange().getBegin(), + diag::err_auto_new_requires_parens) + << AllocType << TypeRange); + if (NumInits > 1) { + Expr *FirstBad = Inits[1]; return ExprError(Diag(FirstBad->getSourceRange().getBegin(), diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } - Expr *Deduce = ConstructorArgs.get()[0]; - if (ConstructorLParen.isInvalid()) { - return ExprError(Diag(Deduce->getSourceRange().getBegin(), - diag::err_auto_new_requires_parens) - << AllocType << TypeRange); - } + Expr *Deduce = Inits[0]; TypeSourceInfo *DeducedType = 0; if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed) @@ -1035,15 +1079,10 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) return ExprError(); - bool ListInitialization = ConstructorLParen.isInvalid() && - ConstructorArgs.size() > 0; - assert((!ListInitialization || (ConstructorArgs.size() == 1 && - isa<InitListExpr>(ConstructorArgs.get()[0]))) - && "List initialization means a braced-init-list for arguments."); - if (ListInitialization && isStdInitializerList(AllocType, 0)) { + if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) { Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(), diag::warn_dangling_std_initializer_list) - << /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange(); + << /*at end of FE*/0 << Inits[0]->getSourceRange(); } // In ARC, infer 'retaining' for the allocated @@ -1201,25 +1240,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0; - // --- Choosing a constructor --- - CXXConstructorDecl *Constructor = 0; - bool HadMultipleCandidates = false; - Expr **ConsArgs = (Expr**)ConstructorArgs.get(); - unsigned NumConsArgs = ConstructorArgs.size(); - ASTOwningVector<Expr*> ConvertedConstructorArgs(*this); - - // Array 'new' can't have any initializers. - if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) { - SourceRange InitRange(ConsArgs[0]->getLocStart(), - ConsArgs[NumConsArgs - 1]->getLocEnd()); + // Array 'new' can't have any initializers except empty parentheses. + if (!isLegalArrayNewInitializer(Initializer) && + (ResultType->isArrayType() || ArraySize)) { + SourceRange InitRange(Inits[0]->getLocStart(), + Inits[NumInits - 1]->getLocEnd()); Diag(StartLoc, diag::err_new_array_init_args) << InitRange; return ExprError(); } if (!AllocType->isDependentType() && - !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { + !Expr::hasAnyTypeDependentArguments(Inits, NumInits)) { // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: @@ -1227,49 +1259,31 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // - If the new-initializer is omitted, the object is default- // initialized (8.5); if no initialization is performed, // the object has indeterminate value - = !Init? InitializationKind::CreateDefault(TypeRange.getBegin()) + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) // - Otherwise, the new-initializer is interpreted according to the // initialization rules of 8.5 for direct-initialization. - : ListInitialization ? InitializationKind::CreateDirectList( - TypeRange.getBegin()) - : InitializationKind::CreateDirect( - TypeRange.getBegin(), - ConstructorLParen, - ConstructorRParen); + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); InitializedEntity Entity = InitializedEntity::InitializeNew(StartLoc, AllocType); - InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); + InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits); ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, - move(ConstructorArgs)); + MultiExprArg(Inits, NumInits)); if (FullInit.isInvalid()) return ExprError(); - // FullInit is our initializer; walk through it to determine if it's a - // constructor call, which CXXNewExpr handles directly. - if (Expr *FullInitExpr = (Expr *)FullInit.get()) { - if (CXXBindTemporaryExpr *Binder - = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr)) - FullInitExpr = Binder->getSubExpr(); - if (CXXConstructExpr *Construct - = dyn_cast<CXXConstructExpr>(FullInitExpr)) { - Constructor = Construct->getConstructor(); - HadMultipleCandidates = Construct->hadMultipleCandidates(); - for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), - AEnd = Construct->arg_end(); - A != AEnd; ++A) - ConvertedConstructorArgs.push_back(*A); - } else { - // Take the converted initializer. - ConvertedConstructorArgs.push_back(FullInit.release()); - } - } else { - // No initialization required. - } + // FullInit is our initializer; strip off CXXBindTemporaryExprs, because + // we don't want the initialized object to be destructed. + if (CXXBindTemporaryExpr *Binder = + dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get())) + FullInit = Owned(Binder->getSubExpr()); - // Take the converted arguments and use them for the new expression. - NumConsArgs = ConvertedConstructorArgs.size(); - ConsArgs = (Expr **)ConvertedConstructorArgs.take(); + Initializer = FullInit.take(); } // Mark the new and delete operators as referenced. @@ -1281,8 +1295,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, // access and ambiguity control are done for the destructor. - if (ArraySize && Constructor) { - if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) { + if (ArraySize && AllocType->isRecordType()) { + if (CXXDestructorDecl *dtor = LookupDestructor( + cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl()))) { MarkFunctionReferenced(StartLoc, dtor); CheckDestructorAccess(StartLoc, dtor, PDiag(diag::err_access_dtor) @@ -1291,25 +1306,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } PlacementArgs.release(); - ConstructorArgs.release(); return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, - PlaceArgs, NumPlaceArgs, TypeIdParens, - ArraySize, Constructor, Init, - ConsArgs, NumConsArgs, - HadMultipleCandidates, OperatorDelete, UsualArrayDeleteWantsSize, + PlaceArgs, NumPlaceArgs, TypeIdParens, + ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, - StartLoc, - Init ? ConstructorRParen : - TypeRange.getEnd(), - ConstructorLParen, ConstructorRParen)); + StartLoc, DirectInitRange)); } -/// CheckAllocatedType - Checks that a type is suitable as the allocated type +/// \brief Checks that a type is suitable as the allocated type /// in a new-expression. -/// dimension off and stores the size expression in ArraySize. bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 3293f7468d..88173555e9 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1976,9 +1976,8 @@ public: QualType AllocatedType, TypeSourceInfo *AllocatedTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen) { + SourceRange DirectInitRange, + Expr *Initializer) { return getSema().BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), @@ -1987,9 +1986,8 @@ public: AllocatedType, AllocatedTypeInfo, ArraySize, - ConstructorLParen, - move(ConstructorArgs), - ConstructorRParen); + DirectInitRange, + Initializer); } /// \brief Build a new C++ "delete" expression. @@ -7106,29 +7104,17 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (getDerived().TransformExprs(E->getPlacementArgs(), E->getNumPlacementArgs(), true, PlacementArgs, &ArgumentChanged)) - return ExprError(); - - // Transform the constructor arguments (if any). - // As an annoying corner case, we may have introduced an implicit value- - // initialization expression when allocating a new array, which we implicitly - // drop. It will be re-created during type checking. - ASTOwningVector<Expr*> ConstructorArgs(SemaRef); - if (!(E->isArray() && E->getNumConstructorArgs() == 1 && - isa<ImplicitValueInitExpr>(E->getConstructorArgs()[0])) && - TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true, - ConstructorArgs, &ArgumentChanged)) - return ExprError(); - - // Transform constructor, new operator, and delete operator. - CXXConstructorDecl *Constructor = 0; - if (E->getConstructor()) { - Constructor = cast_or_null<CXXConstructorDecl>( - getDerived().TransformDecl(E->getLocStart(), - E->getConstructor())); - if (!Constructor) - return ExprError(); - } + return ExprError(); + + // Transform the initializer (if any). + Expr *OldInit = E->getInitializer(); + ExprResult NewInit; + if (OldInit) + NewInit = getDerived().TransformExpr(OldInit); + if (NewInit.isInvalid()) + return ExprError(); + // Transform new operator and delete operator. FunctionDecl *OperatorNew = 0; if (E->getOperatorNew()) { OperatorNew = cast_or_null<FunctionDecl>( @@ -7150,21 +7136,18 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { if (!getDerived().AlwaysRebuild() && AllocTypeInfo == E->getAllocatedTypeSourceInfo() && ArraySize.get() == E->getArraySize() && - Constructor == E->getConstructor() && + NewInit.get() == OldInit && OperatorNew == E->getOperatorNew() && OperatorDelete == E->getOperatorDelete() && !ArgumentChanged) { // Mark any declarations we need as referenced. // FIXME: instantiation-specific. - if (Construct |