aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ExprCXX.h135
-rw-r--r--include/clang/Sema/Sema.h9
-rw-r--r--lib/AST/Expr.cpp5
-rw-r--r--lib/AST/ExprCXX.cpp69
-rw-r--r--lib/AST/ItaniumMangle.cpp16
-rw-r--r--lib/AST/StmtPrinter.cpp18
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/CodeGen/CGExprCXX.cpp51
-rw-r--r--lib/Parse/ParseExprCXX.cpp18
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp176
-rw-r--r--lib/Sema/TreeTransform.h58
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp15
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp13
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp3
-rw-r--r--test/Analysis/new.cpp1
-rw-r--r--tools/libclang/CIndex.cpp5
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) ==