diff options
-rw-r--r-- | include/clang/AST/ExprCXX.h | 135 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 9 | ||||
-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 | ||||
-rw-r--r-- | test/Analysis/new.cpp | 1 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 5 |
17 files changed, 321 insertions, 279 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 458c96f3b5..c305faa8a9 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1359,24 +1359,34 @@ 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; - // 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. + // 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. 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; @@ -1385,33 +1395,29 @@ class CXXNewExpr : public Expr { /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; - /// \brief Location of the first token. SourceLocation StartLoc; - - /// \brief Source-range of a paren-delimited initializer. - SourceRange DirectInitRange; + SourceLocation EndLoc; + SourceLocation ConstructorLParen; + SourceLocation ConstructorRParen; 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, - FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, Expr **placementArgs, unsigned numPlaceArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, Expr *initializer, + SourceRange TypeIdParens, + Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, + Expr **constructorArgs, unsigned numConsArgs, + bool HadMultipleCandidates, + FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceLocation startLoc, SourceRange directInitRange); + SourceLocation startLoc, SourceLocation endLoc, + SourceLocation constructorLParen, + SourceLocation constructorRParen); explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, - bool hasInitializer); + unsigned numConsArgs); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1437,6 +1443,8 @@ 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() { @@ -1448,40 +1456,23 @@ public: unsigned getNumPlacementArgs() const { return NumPlacementArgs; } Expr **getPlacementArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); + return reinterpret_cast<Expr **>(SubExprs + Array); } Expr *getPlacementArg(unsigned i) { assert(i < NumPlacementArgs && "Index out of range"); - return getPlacementArgs()[i]; + return cast<Expr>(SubExprs[Array + i]); } const Expr *getPlacementArg(unsigned i) const { assert(i < NumPlacementArgs && "Index out of range"); - return const_cast<CXXNewExpr*>(this)->getPlacementArg(i); + return cast<Expr>(SubExprs[Array + i]); } bool isParenTypeId() const { return TypeIdParens.isValid(); } SourceRange getTypeIdParens() const { return TypeIdParens; } bool isGlobalNew() const { return GlobalNew; } - - /// \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<InitializationStyle>(StoredInitializationStyle-1); - } - - /// \brief The initializer of this new-expression. - Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; - } - const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; - } + bool hasInitializer() const { return Initializer; } /// Answers whether the usual array deallocation function for the /// allocated type expects the size of the allocation as a @@ -1490,39 +1481,71 @@ public: return UsualArrayDeleteWantsSize; } + unsigned getNumConstructorArgs() const { return NumConstructorArgs; } + + Expr **getConstructorArgs() { + return reinterpret_cast<Expr **>(SubExprs + Array + NumPlacementArgs); + } + + Expr *getConstructorArg(unsigned i) { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]); + } + const Expr *getConstructorArg(unsigned i) const { + assert(i < NumConstructorArgs && "Index out of range"); + return cast<Expr>(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 + hasInitializer(); + return SubExprs + Array; } arg_iterator placement_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return SubExprs + Array + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array + hasInitializer(); + return SubExprs + Array; } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + 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(); } typedef Stmt **raw_arg_iterator; raw_arg_iterator raw_arg_begin() { return SubExprs; } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs(); } const_arg_iterator raw_arg_begin() const { return SubExprs; } - const_arg_iterator raw_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); - } + const_arg_iterator raw_arg_end() const { return constructor_arg_end(); } SourceLocation getStartLoc() const { return StartLoc; } - SourceLocation getEndLoc() const; + SourceLocation getEndLoc() const { return EndLoc; } - SourceRange getDirectInitRange() const { return DirectInitRange; } + SourceLocation getConstructorLParen() const { return ConstructorLParen; } + SourceLocation getConstructorRParen() const { return ConstructorRParen; } SourceRange getSourceRange() const { - return SourceRange(getStartLoc(), getEndLoc()); + return SourceRange(StartLoc, EndLoc); } static bool classof(const Stmt *T) { @@ -1532,7 +1555,9 @@ public: // Iterators child_range children() { - return child_range(raw_arg_begin(), raw_arg_end()); + return child_range(&SubExprs[0], + &SubExprs[0] + Array + getNumPlacementArgs() + + getNumConstructorArgs()); } }; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1ef4ac67dd..018acdcab4 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3194,7 +3194,9 @@ public: MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, - Expr *Initializer); + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen); ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -3203,8 +3205,9 @@ public: QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceRange DirectInitRange, - Expr *Initializer, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen, bool TypeMayContainAuto = true); bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 4b19031852..f9f7ba542c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2041,7 +2041,10 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { if (isTypeDependent()) CT = CT_Dependent; else - CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()); + CT = MergeCanThrow( + CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()), + CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(), + /*NullThrows*/false)); 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 718010b81e..e09d88091b 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -45,26 +45,30 @@ SourceRange CXXScalarValueInitExpr::getSourceRange() const { // CXXNewExpr CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, - bool usualArrayDeleteWantsSize, Expr **placementArgs, unsigned numPlaceArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, - Expr *initializer, QualType ty, - TypeSourceInfo *allocatedTypeInfo, - SourceLocation startLoc, SourceRange directInitRange) + 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) : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), ty->isDependentType(), ty->isInstantiationDependentType(), ty->containsUnexpandedParameterPack()), - 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); + 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); unsigned i = 0; if (Array) { if (arraySize->isInstantiationDependent()) @@ -76,33 +80,33 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SubExprs[i++] = arraySize; } - if (initializer) { - if (initializer->isInstantiationDependent()) + for (unsigned j = 0; j < NumPlacementArgs; ++j) { + if (placementArgs[j]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - - if (initializer->containsUnexpandedParameterPack()) + if (placementArgs[j]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = initializer; + SubExprs[i++] = placementArgs[j]; } - for (unsigned j = 0; j < NumPlacementArgs; ++j) { - if (placementArgs[j]->isInstantiationDependent()) + for (unsigned j = 0; j < NumConstructorArgs; ++j) { + if (constructorArgs[j]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (placementArgs[j]->containsUnexpandedParameterPack()) + if (constructorArgs[j]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = placementArgs[j]; + SubExprs[i++] = constructorArgs[j]; } } void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer){ + unsigned numPlaceArgs, unsigned numConsArgs){ assert(SubExprs == 0 && "SubExprs already allocated"); Array = isArray; NumPlacementArgs = numPlaceArgs; - - unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; + NumConstructorArgs = numConsArgs; + + unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; SubExprs = new (C) Stmt*[TotalSize]; } @@ -111,17 +115,6 @@ 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 4843716909..7df8f6fc6b 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2351,20 +2351,10 @@ recurse: Out << '_'; mangleType(New->getAllocatedType()); if (New->hasInitializer()) { - // FIXME: Does this mean "parenthesized initializer"? Out << "pi"; - 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); + for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(), + E = New->constructor_arg_end(); I != E; ++I) + mangleExpression(*I); } Out << 'E'; break; diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index c83bfad1c2..746049b166 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1390,13 +1390,17 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) { if (E->isParenTypeId()) OS << ")"; - CXXNewExpr::InitializationStyle InitStyle = E->getInitializationStyle(); - if (InitStyle) { - if (InitStyle == CXXNewExpr::CallInit) - OS << "("; - PrintExpr(E->getInitializer()); - if (InitStyle == CXXNewExpr::CallInit) - 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 << ")"; } } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index fdd0c8502d..1d58fd7b2b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -825,11 +825,13 @@ 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.AddInteger(S->getInitializationStyle()); + ID.AddBoolean(S->hasInitializer()); + ID.AddInteger(S->getNumConstructorArgs()); } void diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 12bdc7e43f..7b1ae1cc24 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -743,8 +743,11 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E, llvm::Value *NewPtr) { - - const Expr *Init = E->getInitializer(); + + assert(E->getNumConstructorArgs() == 1 && + "Can only have one argument to initializer of POD type."); + + const Expr *Init = E->getConstructorArg(0); QualType AllocType = E->getAllocatedType(); CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType); @@ -770,8 +773,9 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Value *beginPtr, llvm::Value *numElements) { - if (!E->hasInitializer()) - return; // We have a POD type. + // We have a POD type. + if (E->getNumConstructorArgs() == 0) + return; // Check if the number of elements is constant. bool checkZero = true; @@ -854,15 +858,13 @@ 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 (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)){ - CXXConstructorDecl *Ctor = CCE->getConstructor(); + if (CXXConstructorDecl *Ctor = E->getConstructor()) { bool RequiresZeroInitialization = false; if (Ctor->getParent()->hasTrivialDefaultConstructor()) { // If new expression did not specify value-initialization, then there // is no initialization. - if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty()) + if (!E->hasInitializer() || Ctor->getParent()->isEmpty()) return; if (CGF.CGM.getTypes().isZeroInitializable(ElementType)) { @@ -875,38 +877,43 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, RequiresZeroInitialization = true; } - CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, - CCE->arg_begin(), CCE->arg_end(), + CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, + E->constructor_arg_begin(), + E->constructor_arg_end(), RequiresZeroInitialization); return; - } else if (Init && isa<ImplicitValueInitExpr>(Init) && + } else if (E->getNumConstructorArgs() == 1 && + isa<ImplicitValueInitExpr>(E->getConstructorArg(0)) && 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 (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)) { - CXXConstructorDecl *Ctor = CCE->getConstructor(); + if (CXXConstructorDecl *Ctor = E->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 (!Ctor->getParent()->hasUserDeclaredConstructor() && + if (E->hasInitializer() && + !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 (!Init) + if (E->getNumConstructorArgs() == 0) return; - + StoreAnyExprIntoOneUnit(CGF, E, NewPtr); } @@ -1138,7 +1145,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; @@ -1204,7 +1211,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 7185e93a11..5996e2a264 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2193,11 +2193,10 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { return ExprError(); } - ExprResult Initializer; + ExprVector ConstructorArgs(Actions); + SourceLocation ConstructorLParen, ConstructorRParen; if (Tok.is(tok::l_paren)) { - SourceLocation ConstructorLParen, ConstructorRParen; - ExprVector ConstructorArgs(Actions); BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); ConstructorLParen = T.getOpenLocation(); @@ -2214,20 +2213,19 @@ 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); - Initializer = ParseBraceInitializer(); + ExprResult InitList = ParseBraceInitializer(); + if (InitList.isInvalid()) + return InitList; + ConstructorArgs.push_back(InitList.take()); } - if (Initializer.isInvalid()) - return Initializer; return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, move_arg(PlacementArgs), PlacementRParen, - TypeIdParens, DeclaratorInfo, Initializer.take()); + TypeIdParens, DeclaratorInfo, ConstructorLParen, + move_arg(ConstructorArgs), ConstructorRParen); } /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6b66a42ad3..7fee518d2c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10148,13 +10148,15 @@ 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 dfa2148fc3..4ffdb3e5c1 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -914,7 +914,9 @@ ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, - Declarator &D, Expr *Initializer) { + Declarator &D, SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen) { bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; Expr *ArraySize = 0; @@ -959,10 +961,6 @@ 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), @@ -971,27 +969,12 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, AllocType, TInfo, ArraySize, - DirectInitRange, - Initializer, + ConstructorLParen, + move(ConstructorArgs), + ConstructorRParen, 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, @@ -1001,56 +984,29 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, QualType AllocType, TypeSourceInfo *AllocTypeInfo, Expr *ArraySize, - SourceRange DirectInitRange, - Expr *Initializer, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen, 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 (initStyle == CXXNewExpr::NoInit || NumInits == 0) + if (ConstructorArgs.size() == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); - 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]; + if (ConstructorArgs.size() != 1) { + Expr *FirstBad = ConstructorArgs.get()[1]; return ExprError(Diag(FirstBad->getSourceRange().getBegin(), diag::err_auto_new_ctor_multiple_expressions) << AllocType << TypeRange); } - Expr *Deduce = Inits[0]; + Expr *Deduce = ConstructorArgs.get()[0]; + if (ConstructorLParen.isInvalid()) { + return ExprError(Diag(Deduce->getSourceRange().getBegin(), + diag::err_auto_new_requires_parens) + << AllocType << TypeRange); + } TypeSourceInfo *DeducedType = 0; if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == |