From 6047f07e815c631a1cbca7531f4dfc5331592da7 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Thu, 16 Feb 2012 12:22:20 +0000 Subject: [PATCH] Revert "Revert "Make CXXNewExpr contain only a single initialier, and not hold the used constructor itself."" This reintroduces commit r150682 with a fix for the Bullet benchmark crash. llvm-svn: 150685 --- clang/include/clang/AST/ExprCXX.h | 135 ++++++-------- clang/include/clang/Sema/Sema.h | 9 +- clang/lib/AST/Expr.cpp | 5 +- clang/lib/AST/ExprCXX.cpp | 71 +++---- clang/lib/AST/ItaniumMangle.cpp | 16 +- clang/lib/AST/StmtPrinter.cpp | 18 +- clang/lib/AST/StmtProfile.cpp | 4 +- clang/lib/CodeGen/CGExprCXX.cpp | 51 +++-- clang/lib/Parse/ParseExprCXX.cpp | 18 +- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/lib/Sema/SemaExprCXX.cpp | 176 +++++++++--------- clang/lib/Sema/TreeTransform.h | 56 ++---- clang/lib/Serialization/ASTReaderStmt.cpp | 15 +- clang/lib/Serialization/ASTWriterStmt.cpp | 13 +- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 3 + clang/test/Analysis/new.cpp | 1 + clang/test/SemaCXX/new-delete.cpp | 29 +++ clang/tools/libclang/CIndex.cpp | 5 +- 18 files changed, 308 insertions(+), 321 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index c305faa8a998..458c96f3b548 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1359,34 +1359,24 @@ public: class CXXNewExpr : public Expr { // Was the usage ::new, i.e. is the global new to be used? bool GlobalNew : 1; - // Is there an initializer? If not, built-ins are uninitialized, else they're - // value-initialized. - bool Initializer : 1; // Do we allocate an array? If so, the first SubExpr is the size expression. bool Array : 1; // If this is an array allocation, does the usual deallocation // function for the allocated type want to know the allocated size? bool UsualArrayDeleteWantsSize : 1; - // Whether the referred constructor (if any) was resolved from an - // overload set having size greater than 1. - bool HadMultipleCandidates : 1; // The number of placement new arguments. unsigned NumPlacementArgs : 13; - // The number of constructor arguments. This may be 1 even for non-class - // types; use the pseudo copy constructor. - unsigned NumConstructorArgs : 14; - // Contains an optional array size expression, any number of optional - // placement arguments, and any number of optional constructor arguments, - // in that order. + // What kind of initializer do we have? Could be none, parens, or braces. + // In storage, we distinguish between "none, and no initializer expr", and + // "none, but an implicit initializer expr". + unsigned StoredInitializationStyle : 2; + // Contains an optional array size expression, an optional initialization + // expression, and any number of optional placement arguments, in that order. Stmt **SubExprs; // Points to the allocation function used. FunctionDecl *OperatorNew; // Points to the deallocation function used in case of error. May be null. FunctionDecl *OperatorDelete; - // Points to the constructor used. Cannot be null if AllocType is a record; - // it would still point at the default constructor (even an implicit one). - // Must be null for all other types. - CXXConstructorDecl *Constructor; /// \brief The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; @@ -1395,29 +1385,33 @@ class CXXNewExpr : public Expr { /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; + /// \brief Location of the first token. SourceLocation StartLoc; - SourceLocation EndLoc; - SourceLocation ConstructorLParen; - SourceLocation ConstructorRParen; + + /// \brief Source-range of a paren-delimited initializer. + SourceRange DirectInitRange; friend class ASTStmtReader; + friend class ASTStmtWriter; public: + enum InitializationStyle { + NoInit, ///< New-expression has no initializer as written. + CallInit, ///< New-expression has a C++98 paren-delimited initializer. + ListInit ///< New-expression has a C++11 list-initializer. + }; + 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, + Expr **placementArgs, unsigned numPlaceArgs, + SourceRange typeIdParens, Expr *arraySize, + InitializationStyle initializationStyle, Expr *initializer, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceLocation endLoc, - SourceLocation constructorLParen, - SourceLocation constructorRParen); + SourceLocation startLoc, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, - unsigned numConsArgs); + bool hasInitializer); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1443,8 +1437,6 @@ public: void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } - CXXConstructorDecl *getConstructor() const { return Constructor; } - void setConstructor(CXXConstructorDecl *D) { Constructor = D; } bool isArray() const { return Array; } Expr *getArraySize() { @@ -1456,23 +1448,40 @@ public: unsigned getNumPlacementArgs() const { return NumPlacementArgs; } Expr **getPlacementArgs() { - return reinterpret_cast(SubExprs + Array); + return reinterpret_cast(SubExprs + Array + hasInitializer()); } Expr *getPlacementArg(unsigned i) { assert(i < NumPlacementArgs && "Index out of range"); - return cast(SubExprs[Array + i]); + return getPlacementArgs()[i]; } const Expr *getPlacementArg(unsigned i) const { assert(i < NumPlacementArgs && "Index out of range"); - return cast(SubExprs[Array + i]); + return const_cast(this)->getPlacementArg(i); } bool isParenTypeId() const { return TypeIdParens.isValid(); } SourceRange getTypeIdParens() const { return TypeIdParens; } bool isGlobalNew() const { return GlobalNew; } - bool hasInitializer() const { return Initializer; } + + /// \brief Whether this new-expression has any initializer at all. + bool hasInitializer() const { return StoredInitializationStyle > 0; } + + /// \brief The kind of initializer this new-expression has. + InitializationStyle getInitializationStyle() const { + if (StoredInitializationStyle == 0) + return NoInit; + return static_cast(StoredInitializationStyle-1); + } + + /// \brief The initializer of this new-expression. + Expr *getInitializer() { + return hasInitializer() ? cast(SubExprs[Array]) : 0; + } + const Expr *getInitializer() const { + return hasInitializer() ? cast(SubExprs[Array]) : 0; + } /// Answers whether the usual array deallocation function for the /// allocated type expects the size of the allocation as a @@ -1481,71 +1490,39 @@ public: return UsualArrayDeleteWantsSize; } - unsigned getNumConstructorArgs() const { return NumConstructorArgs; } - - Expr **getConstructorArgs() { - return reinterpret_cast(SubExprs + Array + NumPlacementArgs); - } - - Expr *getConstructorArg(unsigned i) { - assert(i < NumConstructorArgs && "Index out of range"); - return cast(SubExprs[Array + NumPlacementArgs + i]); - } - const Expr *getConstructorArg(unsigned i) const { - assert(i < NumConstructorArgs && "Index out of range"); - return cast(SubExprs[Array + NumPlacementArgs + i]); - } - - /// \brief Whether the new expression refers a constructor that was - /// resolved from an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { return HadMultipleCandidates; } - void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } - typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; arg_iterator placement_arg_begin() { - return SubExprs + Array; + return SubExprs + Array + hasInitializer(); } arg_iterator placement_arg_end() { - return SubExprs + Array + getNumPlacementArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array; + return SubExprs + Array + hasInitializer(); } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + getNumPlacementArgs(); - } - - arg_iterator constructor_arg_begin() { - return SubExprs + Array + getNumPlacementArgs(); - } - arg_iterator constructor_arg_end() { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); - } - const_arg_iterator constructor_arg_begin() const { - return SubExprs + Array + getNumPlacementArgs(); - } - const_arg_iterator constructor_arg_end() const { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } typedef Stmt **raw_arg_iterator; raw_arg_iterator raw_arg_begin() { return SubExprs; } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); } const_arg_iterator raw_arg_begin() const { return SubExprs; } - const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } + const_arg_iterator raw_arg_end() const { + return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + } SourceLocation getStartLoc() const { return StartLoc; } - SourceLocation getEndLoc() const { return EndLoc; } + SourceLocation getEndLoc() const; - SourceLocation getConstructorLParen() const { return ConstructorLParen; } - SourceLocation getConstructorRParen() const { return ConstructorRParen; } + SourceRange getDirectInitRange() const { return DirectInitRange; } SourceRange getSourceRange() const { - return SourceRange(StartLoc, EndLoc); + return SourceRange(getStartLoc(), getEndLoc()); } static bool classof(const Stmt *T) { @@ -1555,9 +1532,7 @@ public: // Iterators child_range children() { - return child_range(&SubExprs[0], - &SubExprs[0] + Array + getNumPlacementArgs() - + getNumConstructorArgs()); + return child_range(raw_arg_begin(), raw_arg_end()); } }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 018acdcab4a6..1ef4ac67dde7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3194,9 +3194,7 @@ public: MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen); + Expr *Initializer); ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -3205,9 +3203,8 @@ public: QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceLocation ConstructorLParen, - MultiExprArg ConstructorArgs, - SourceLocation ConstructorRParen, + SourceRange DirectInitRange, + Expr *Initializer, bool TypeMayContainAuto = true); bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f9f7ba542cdf..4b19031852c6 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/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(this)->getOperatorNew()), - CanCalleeThrow(C, this, cast(this)->getConstructor(), - /*NullThrows*/false)); + CT = CanCalleeThrow(C, this, cast(this)->getOperatorNew()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e09d88091be4..718010b81ed4 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/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,6 +76,16 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = arraySize; } + if (initializer) { + if (initializer->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + + if (initializer->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i++] = initializer; + } + for (unsigned j = 0; j < NumPlacementArgs; ++j) { if (placementArgs[j]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; @@ -88,25 +94,15 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = placementArgs[j]; } - - for (unsigned j = 0; j < NumConstructorArgs; ++j) { - if (constructorArgs[j]->isInstantiationDependent()) - ExprBits.InstantiationDependent = true; - if (constructorArgs[j]->containsUnexpandedParameterPack()) - ExprBits.ContainsUnexpandedParameterPack = true; - - SubExprs[i++] = constructorArgs[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()->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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7df8f6fc6b85..4843716909fb 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/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(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(Init)) { + for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i) + mangleExpression(PLE->getExpr(i)); + } else + mangleExpression(Init); } Out << 'E'; break; diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 746049b16614..c83bfad1c2e4 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 1d58fd7b2b25..fdd0c8502db5 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/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/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 7b1ae1cc24a4..12bdc7e43f73 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/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(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(E->getConstructorArg(0)) && + } else if (Init && isa(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(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/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 5996e2a26432..7185e93a11d3 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7fee518d2cc3..6b66a42ad345 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 4ffdb3e5c154..159d4d35af32 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/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(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(Init)) { + if (PLE->getNumExprs() != 1) + return PLE->getNumExprs() == 0; + Init = PLE->getExpr(0); + } + if (isa(Init)) + return true; + else if (CXXConstructExpr *CCE = dyn_cast(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(Initializer)) + initStyle = CXXNewExpr::ListInit; + else { + assert((!Initializer || isa(Initializer) || + isa(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(Initializer)) { + Inits = List->getExprs(); + NumInits = List->getNumExprs(); + } else if (CXXConstructExpr *CCE = dyn_cast(Initializer)){ + if (!isa(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(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 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(FullInitExpr)) - FullInitExpr = Binder->getSubExpr(); - if (CXXConstructExpr *Construct - = dyn_cast(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(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() && !AllocType->isDependentType()) { + if (CXXDestructorDecl *dtor = LookupDestructor( + cast(AllocType->getAs()->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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3293f7468d82..88173555e927 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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::TransformCXXNewExpr(CXXNewExpr *E) { if (getDerived().TransformExprs(E->getPlacementArgs(), E->getNumPlacementArgs(), true, PlacementArgs, &ArgumentChanged)) - return ExprError(); + 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 ConstructorArgs(SemaRef); - if (!(E->isArray() && E->getNumConstructorArgs() == 1 && - isa(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( - getDerived().TransformDecl(E->getLocStart(), - E->getConstructor())); - if (!Constructor) - 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( @@ -7150,21 +7136,18 @@ TreeTransform::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 (Constructor) - SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor); if (OperatorNew) SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew); if (OperatorDelete) SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete); - if (E->isArray() && Constructor && - !E->getAllocatedType()->isDependentType()) { + if (E->isArray() && !E->getAllocatedType()->isDependentType()) { QualType ElementType = SemaRef.Context.getBaseElementType(E->getAllocatedType()); if (const RecordType *RecordT = ElementType->getAs()) { @@ -7174,7 +7157,7 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { } } } - + return SemaRef.Owned(E); } @@ -7204,7 +7187,7 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { } } } - + return getDerived().RebuildCXXNewExpr(E->getLocStart(), E->isGlobalNew(), /*FIXME:*/E->getLocStart(), @@ -7214,9 +7197,8 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { AllocType, AllocTypeInfo, ArraySize.get(), - E->getConstructorLParen(), - move_arg(ConstructorArgs), - E->getConstructorRParen()); + E->getDirectInitRange(), + NewInit.take()); } template diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 361ff3f48366..8b85976bf42e 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1167,27 +1167,24 @@ void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); E->GlobalNew = Record[Idx++]; - E->Initializer = Record[Idx++]; - E->UsualArrayDeleteWantsSize = Record[Idx++]; bool isArray = Record[Idx++]; - E->setHadMultipleCandidates(Record[Idx++]); + E->UsualArrayDeleteWantsSize = Record[Idx++]; unsigned NumPlacementArgs = Record[Idx++]; - unsigned NumCtorArgs = Record[Idx++]; + E->StoredInitializationStyle = Record[Idx++]; E->setOperatorNew(ReadDeclAs(Record, Idx)); E->setOperatorDelete(ReadDeclAs(Record, Idx)); - E->setConstructor(ReadDeclAs(Record, Idx)); E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx); SourceRange TypeIdParens; TypeIdParens.setBegin(ReadSourceLocation(Record, Idx)); TypeIdParens.setEnd(ReadSourceLocation(Record, Idx)); E->TypeIdParens = TypeIdParens; E->StartLoc = ReadSourceLocation(Record, Idx); - E->EndLoc = ReadSourceLocation(Record, Idx); - E->ConstructorLParen = ReadSourceLocation(Record, Idx); - E->ConstructorRParen = ReadSourceLocation(Record, Idx); + SourceRange DirectInitRange; + DirectInitRange.setBegin(ReadSourceLocation(Record, Idx)); + DirectInitRange.setEnd(ReadSourceLocation(Record, Idx)); E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs, - NumCtorArgs); + E->StoredInitializationStyle != 0); // Install all the subexpressions. for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index f6cfd01341f8..0ba413df7224 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1158,25 +1158,20 @@ void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); Record.push_back(E->isGlobalNew()); - Record.push_back(E->hasInitializer()); - Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->isArray()); - Record.push_back(E->hadMultipleCandidates()); + Record.push_back(E->doesUsualArrayDeleteWantSize()); Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->getNumConstructorArgs()); + Record.push_back(E->StoredInitializationStyle); Writer.AddDeclRef(E->getOperatorNew(), Record); Writer.AddDeclRef(E->getOperatorDelete(), Record); - Writer.AddDeclRef(E->getConstructor(), Record); Writer.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo(), Record); Writer.AddSourceRange(E->getTypeIdParens(), Record); Writer.AddSourceLocation(E->getStartLoc(), Record); - Writer.AddSourceLocation(E->getEndLoc(), Record); - Writer.AddSourceLocation(E->getConstructorLParen(), Record); - Writer.AddSourceLocation(E->getConstructorRParen(), Record); + Writer.AddSourceRange(E->getDirectInitRange(), Record); for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); I != e; ++I) Writer.AddStmt(*I); - + Code = serialization::EXPR_CXX_NEW; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index cd636aead882..7a5cb877772d 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -268,6 +268,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, return; } + // FIXME: Update for AST changes. +#if 0 // Evaluate constructor arguments. const FunctionProtoType *FnType = NULL; const CXXConstructorDecl *CD = CNE->getConstructor(); @@ -327,6 +329,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, loc::MemRegionVal(EleReg)); Bldr.generateNode(CNE, *I, state); } +#endif } void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, diff --git a/clang/test/Analysis/new.cpp b/clang/test/Analysis/new.cpp index 29ac5eebd242..5ca8c462bdf5 100644 --- a/clang/test/Analysis/new.cpp +++ b/clang/test/Analysis/new.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -verify %s +// XFAIL: * void f1() { int *n = new int; diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index 4daa65efc224..dfe880e34bb8 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -417,3 +417,32 @@ namespace PR10504 { }; void f(A *x) { delete x; } // expected-warning {{delete called on 'PR10504::A' that is abstract but has non-virtual destructor}} } + +struct PlacementArg {}; +inline void *operator new[](size_t, const PlacementArg &) throw () { + return 0; +} +inline void operator delete[](void *, const PlacementArg &) throw () { +} + +namespace r150682 { + + template + struct S { + struct Inner {}; + S() { new Inner[1]; } + }; + + struct T { + }; + + template + void tfn() { + new (*(PlacementArg*)0) T[1]; + } + + void fn() { + tfn(); + } + +} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index beec4d2352f8..2ab693e183ed 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1856,9 +1856,8 @@ VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { AddStmt(E->getBase()); } void EnqueueVisitor::VisitCXXNewExpr(CXXNewExpr *E) { - // Enqueue the initializer or constructor arguments. - for (unsigned I = E->getNumConstructorArgs(); I > 0; --I) - AddStmt(E->getConstructorArg(I-1)); + // Enqueue the initializer , if any. + AddStmt(E->getInitializer()); // Enqueue the array size, if any. AddStmt(E->getArraySize()); // Enqueue the allocated type.