forked from OSchip/llvm-project
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
This commit is contained in:
parent
c3a3c60040
commit
6047f07e81
|
@ -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<Expr **>(SubExprs + Array);
|
||||
return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer());
|
||||
}
|
||||
|
||||
Expr *getPlacementArg(unsigned i) {
|
||||
assert(i < NumPlacementArgs && "Index out of range");
|
||||
return cast<Expr>(SubExprs[Array + i]);
|
||||
return getPlacementArgs()[i];
|
||||
}
|
||||
const Expr *getPlacementArg(unsigned i) const {
|
||||
assert(i < NumPlacementArgs && "Index out of range");
|
||||
return cast<Expr>(SubExprs[Array + i]);
|
||||
return const_cast<CXXNewExpr*>(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<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;
|
||||
}
|
||||
|
||||
/// 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<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;
|
||||
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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -2041,10 +2041,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
|
|||
if (isTypeDependent())
|
||||
CT = CT_Dependent;
|
||||
else
|
||||
CT = MergeCanThrow(
|
||||
CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()),
|
||||
CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(),
|
||||
/*NullThrows*/false));
|
||||
CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew());
|
||||
if (CT == CT_Can)
|
||||
return CT;
|
||||
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
|
||||
|
|
|
@ -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<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();
|
||||
|
|
|
@ -2351,10 +2351,20 @@ recurse:
|
|||
Out << '_';
|
||||
mangleType(New->getAllocatedType());
|
||||
if (New->hasInitializer()) {
|
||||
// FIXME: Does this mean "parenthesized initializer"?
|
||||
Out << "pi";
|
||||
for (CXXNewExpr::const_arg_iterator I = New->constructor_arg_begin(),
|
||||
E = New->constructor_arg_end(); I != E; ++I)
|
||||
mangleExpression(*I);
|
||||
const Expr *Init = New->getInitializer();
|
||||
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
|
||||
// Directly inline the initializers.
|
||||
for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
|
||||
E = CCE->arg_end();
|
||||
I != E; ++I)
|
||||
mangleExpression(*I);
|
||||
} else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
|
||||
for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
|
||||
mangleExpression(PLE->getExpr(i));
|
||||
} else
|
||||
mangleExpression(Init);
|
||||
}
|
||||
Out << 'E';
|
||||
break;
|
||||
|
|
|
@ -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 << ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -743,11 +743,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
|
|||
|
||||
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
|
||||
llvm::Value *NewPtr) {
|
||||
|
||||
assert(E->getNumConstructorArgs() == 1 &&
|
||||
"Can only have one argument to initializer of POD type.");
|
||||
|
||||
const Expr *Init = E->getConstructorArg(0);
|
||||
|
||||
const Expr *Init = E->getInitializer();
|
||||
QualType AllocType = E->getAllocatedType();
|
||||
|
||||
CharUnits Alignment = CGF.getContext().getTypeAlignInChars(AllocType);
|
||||
|
@ -773,9 +770,8 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
|
|||
QualType elementType,
|
||||
llvm::Value *beginPtr,
|
||||
llvm::Value *numElements) {
|
||||
// We have a POD type.
|
||||
if (E->getNumConstructorArgs() == 0)
|
||||
return;
|
||||
if (!E->hasInitializer())
|
||||
return; // We have a POD type.
|
||||
|
||||
// Check if the number of elements is constant.
|
||||
bool checkZero = true;
|
||||
|
@ -858,13 +854,15 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
|
|||
llvm::Value *NewPtr,
|
||||
llvm::Value *NumElements,
|
||||
llvm::Value *AllocSizeWithoutCookie) {
|
||||
const Expr *Init = E->getInitializer();
|
||||
if (E->isArray()) {
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
|
||||
if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)){
|
||||
CXXConstructorDecl *Ctor = CCE->getConstructor();
|
||||
bool RequiresZeroInitialization = false;
|
||||
if (Ctor->getParent()->hasTrivialDefaultConstructor()) {
|
||||
// If new expression did not specify value-initialization, then there
|
||||
// is no initialization.
|
||||
if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
|
||||
if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty())
|
||||
return;
|
||||
|
||||
if (CGF.CGM.getTypes().isZeroInitializable(ElementType)) {
|
||||
|
@ -877,43 +875,38 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
|
|||
RequiresZeroInitialization = true;
|
||||
}
|
||||
|
||||
CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
|
||||
E->constructor_arg_begin(),
|
||||
E->constructor_arg_end(),
|
||||
CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
|
||||
CCE->arg_begin(), CCE->arg_end(),
|
||||
RequiresZeroInitialization);
|
||||
return;
|
||||
} else if (E->getNumConstructorArgs() == 1 &&
|
||||
isa<ImplicitValueInitExpr>(E->getConstructorArg(0)) &&
|
||||
} else if (Init && isa<ImplicitValueInitExpr>(Init) &&
|
||||
CGF.CGM.getTypes().isZeroInitializable(ElementType)) {
|
||||
// Optimization: since zero initialization will just set the memory
|
||||
// to all zeroes, generate a single memset to do it in one shot.
|
||||
EmitZeroMemSet(CGF, ElementType, NewPtr, AllocSizeWithoutCookie);
|
||||
return;
|
||||
} else {
|
||||
CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements);
|
||||
return;
|
||||
}
|
||||
CGF.EmitNewArrayInitializer(E, ElementType, NewPtr, NumElements);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
|
||||
if (const CXXConstructExpr *CCE = dyn_cast_or_null<CXXConstructExpr>(Init)) {
|
||||
CXXConstructorDecl *Ctor = CCE->getConstructor();
|
||||
// Per C++ [expr.new]p15, if we have an initializer, then we're performing
|
||||
// direct initialization. C++ [dcl.init]p5 requires that we
|
||||
// zero-initialize storage if there are no user-declared constructors.
|
||||
if (E->hasInitializer() &&
|
||||
!Ctor->getParent()->hasUserDeclaredConstructor() &&
|
||||
if (!Ctor->getParent()->hasUserDeclaredConstructor() &&
|
||||
!Ctor->getParent()->isEmpty())
|
||||
CGF.EmitNullInitialization(NewPtr, ElementType);
|
||||
|
||||
CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,
|
||||
NewPtr, E->constructor_arg_begin(),
|
||||
E->constructor_arg_end());
|
||||
|
||||
CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,
|
||||
NewPtr, CCE->arg_begin(), CCE->arg_end());
|
||||
return;
|
||||
}
|
||||
// We have a POD type.
|
||||
if (E->getNumConstructorArgs() == 0)
|
||||
if (!Init)
|
||||
return;
|
||||
|
||||
|
||||
StoreAnyExprIntoOneUnit(CGF, E, NewPtr);
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1138,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||
// CXXNewExpr::shouldNullCheckAllocation()) and we have an
|
||||
// interesting initializer.
|
||||
bool nullCheck = allocatorType->isNothrow(getContext()) &&
|
||||
!(allocType.isPODType(getContext()) && !E->hasInitializer());
|
||||
(!allocType.isPODType(getContext()) || E->hasInitializer());
|
||||
|
||||
llvm::BasicBlock *nullCheckBB = 0;
|
||||
llvm::BasicBlock *contBB = 0;
|
||||
|
@ -1211,7 +1204,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
|
|||
DeactivateCleanupBlock(operatorDeleteCleanup, cleanupDominator);
|
||||
cleanupDominator->eraseFromParent();
|
||||
}
|
||||
|
||||
|
||||
if (nullCheck) {
|
||||
conditional.end(*this);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -914,9 +914,7 @@ ExprResult
|
|||
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
||||
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
|
||||
SourceLocation PlacementRParen, SourceRange TypeIdParens,
|
||||
Declarator &D, SourceLocation ConstructorLParen,
|
||||
MultiExprArg ConstructorArgs,
|
||||
SourceLocation ConstructorRParen) {
|
||||
Declarator &D, Expr *Initializer) {
|
||||
bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
|
||||
|
||||
Expr *ArraySize = 0;
|
||||
|
@ -961,6 +959,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
if (D.isInvalidType())
|
||||
return ExprError();
|
||||
|
||||
SourceRange DirectInitRange;
|
||||
if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer))
|
||||
DirectInitRange = List->getSourceRange();
|
||||
|
||||
return BuildCXXNew(StartLoc, UseGlobal,
|
||||
PlacementLParen,
|
||||
move(PlacementArgs),
|
||||
|
@ -969,12 +971,27 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
AllocType,
|
||||
TInfo,
|
||||
ArraySize,
|
||||
ConstructorLParen,
|
||||
move(ConstructorArgs),
|
||||
ConstructorRParen,
|
||||
DirectInitRange,
|
||||
Initializer,
|
||||
TypeContainsAuto);
|
||||
}
|
||||
|
||||
static bool isLegalArrayNewInitializer(Expr *Init) {
|
||||
if (!Init)
|
||||
return true;
|
||||
if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
|
||||
if (PLE->getNumExprs() != 1)
|
||||
return PLE->getNumExprs() == 0;
|
||||
Init = PLE->getExpr(0);
|
||||
}
|
||||
if (isa<ImplicitValueInitExpr>(Init))
|
||||
return true;
|
||||
else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init))
|
||||
return !CCE->isListInitialization() &&
|
||||
CCE->getConstructor()->isDefaultConstructor();
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprResult
|
||||
Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
||||
SourceLocation PlacementLParen,
|
||||
|
@ -984,29 +1001,56 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
QualType AllocType,
|
||||
TypeSourceInfo *AllocTypeInfo,
|
||||
Expr *ArraySize,
|
||||
SourceLocation ConstructorLParen,
|
||||
MultiExprArg ConstructorArgs,
|
||||
SourceLocation ConstructorRParen,
|
||||
SourceRange DirectInitRange,
|
||||
Expr *Initializer,
|
||||
bool TypeMayContainAuto) {
|
||||
SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
|
||||
|
||||
CXXNewExpr::InitializationStyle initStyle;
|
||||
if (DirectInitRange.isValid()) {
|
||||
assert(Initializer && "Have parens but no initializer.");
|
||||
initStyle = CXXNewExpr::CallInit;
|
||||
} else if (Initializer && isa<InitListExpr>(Initializer))
|
||||
initStyle = CXXNewExpr::ListInit;
|
||||
else {
|
||||
assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) ||
|
||||
isa<CXXConstructExpr>(Initializer)) &&
|
||||
"Initializer expression that cannot have been implicitly created.");
|
||||
initStyle = CXXNewExpr::NoInit;
|
||||
}
|
||||
|
||||
Expr **Inits = &Initializer;
|
||||
unsigned NumInits = Initializer ? 1 : 0;
|
||||
if (initStyle == CXXNewExpr::CallInit) {
|
||||
if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) {
|
||||
Inits = List->getExprs();
|
||||
NumInits = List->getNumExprs();
|
||||
} else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){
|
||||
if (!isa<CXXTemporaryObjectExpr>(CCE)) {
|
||||
// Can happen in template instantiation. Since this is just an implicit
|
||||
// construction, we just take it apart and rebuild it.
|
||||
Inits = CCE->getArgs();
|
||||
NumInits = CCE->getNumArgs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
||||
if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
|
||||
if (ConstructorArgs.size() == 0)
|
||||
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
|
||||
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
|
||||
<< AllocType << TypeRange);
|
||||
if (ConstructorArgs.size() != 1) {
|
||||
Expr *FirstBad = ConstructorArgs.get()[1];
|
||||
if (initStyle == CXXNewExpr::ListInit)
|
||||
return ExprError(Diag(Inits[0]->getSourceRange().getBegin(),
|
||||
diag::err_auto_new_requires_parens)
|
||||
<< AllocType << TypeRange);
|
||||
if (NumInits > 1) {
|
||||
Expr *FirstBad = Inits[1];
|
||||
return ExprError(Diag(FirstBad->getSourceRange().getBegin(),
|
||||
diag::err_auto_new_ctor_multiple_expressions)
|
||||
<< AllocType << TypeRange);
|
||||
}
|
||||
Expr *Deduce = ConstructorArgs.get()[0];
|
||||
if (ConstructorLParen.isInvalid()) {
|
||||
return ExprError(Diag(Deduce->getSourceRange().getBegin(),
|
||||
diag::err_auto_new_requires_parens)
|
||||
<< AllocType << TypeRange);
|
||||
}
|
||||
Expr *Deduce = Inits[0];
|
||||
TypeSourceInfo *DeducedType = 0;
|
||||
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
|
||||
DAR_Failed)
|
||||
|
@ -1035,15 +1079,10 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
|
||||
return ExprError();
|
||||
|
||||
bool ListInitialization = ConstructorLParen.isInvalid() &&
|
||||
ConstructorArgs.size() > 0;
|
||||
assert((!ListInitialization || (ConstructorArgs.size() == 1 &&
|
||||
isa<InitListExpr>(ConstructorArgs.get()[0])))
|
||||
&& "List initialization means a braced-init-list for arguments.");
|
||||
if (ListInitialization && isStdInitializerList(AllocType, 0)) {
|
||||
if (initStyle == CXXNewExpr::ListInit && isStdInitializerList(AllocType, 0)) {
|
||||
Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
|
||||
diag::warn_dangling_std_initializer_list)
|
||||
<< /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange();
|
||||
<< /*at end of FE*/0 << Inits[0]->getSourceRange();
|
||||
}
|
||||
|
||||
// In ARC, infer 'retaining' for the allocated
|
||||
|
@ -1201,25 +1240,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
}
|
||||
}
|
||||
|
||||
bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0;
|
||||
// --- Choosing a constructor ---
|
||||
CXXConstructorDecl *Constructor = 0;
|
||||
bool HadMultipleCandidates = false;
|
||||
Expr **ConsArgs = (Expr**)ConstructorArgs.get();
|
||||
unsigned NumConsArgs = ConstructorArgs.size();
|
||||
ASTOwningVector<Expr*> ConvertedConstructorArgs(*this);
|
||||
|
||||
// Array 'new' can't have any initializers.
|
||||
if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) {
|
||||
SourceRange InitRange(ConsArgs[0]->getLocStart(),
|
||||
ConsArgs[NumConsArgs - 1]->getLocEnd());
|
||||
// Array 'new' can't have any initializers except empty parentheses.
|
||||
if (!isLegalArrayNewInitializer(Initializer) &&
|
||||
(ResultType->isArrayType() || ArraySize)) {
|
||||
SourceRange InitRange(Inits[0]->getLocStart(),
|
||||
Inits[NumInits - 1]->getLocEnd());
|
||||
|
||||
Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
if (!AllocType->isDependentType() &&
|
||||
!Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
|
||||
!Expr::hasAnyTypeDependentArguments(Inits, NumInits)) {
|
||||
// C++11 [expr.new]p15:
|
||||
// A new-expression that creates an object of type T initializes that
|
||||
// object as follows:
|
||||
|
@ -1227,49 +1259,31 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
// - If the new-initializer is omitted, the object is default-
|
||||
// initialized (8.5); if no initialization is performed,
|
||||
// the object has indeterminate value
|
||||
= !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
|
||||
= initStyle == CXXNewExpr::NoInit
|
||||
? InitializationKind::CreateDefault(TypeRange.getBegin())
|
||||
// - Otherwise, the new-initializer is interpreted according to the
|
||||
// initialization rules of 8.5 for direct-initialization.
|
||||
: ListInitialization ? InitializationKind::CreateDirectList(
|
||||
TypeRange.getBegin())
|
||||
: InitializationKind::CreateDirect(
|
||||
TypeRange.getBegin(),
|
||||
ConstructorLParen,
|
||||
ConstructorRParen);
|
||||
: initStyle == CXXNewExpr::ListInit
|
||||
? InitializationKind::CreateDirectList(TypeRange.getBegin())
|
||||
: InitializationKind::CreateDirect(TypeRange.getBegin(),
|
||||
DirectInitRange.getBegin(),
|
||||
DirectInitRange.getEnd());
|
||||
|
||||
InitializedEntity Entity
|
||||
= InitializedEntity::InitializeNew(StartLoc, AllocType);
|
||||
InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
|
||||
InitializationSequence InitSeq(*this, Entity, Kind, Inits, NumInits);
|
||||
ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
|
||||
move(ConstructorArgs));
|
||||
MultiExprArg(Inits, NumInits));
|
||||
if (FullInit.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
// FullInit is our initializer; walk through it to determine if it's a
|
||||
// constructor call, which CXXNewExpr handles directly.
|
||||
if (Expr *FullInitExpr = (Expr *)FullInit.get()) {
|
||||
if (CXXBindTemporaryExpr *Binder
|
||||
= dyn_cast<CXXBindTemporaryExpr>(FullInitExpr))
|
||||
FullInitExpr = Binder->getSubExpr();
|
||||
if (CXXConstructExpr *Construct
|
||||
= dyn_cast<CXXConstructExpr>(FullInitExpr)) {
|
||||
Constructor = Construct->getConstructor();
|
||||
HadMultipleCandidates = Construct->hadMultipleCandidates();
|
||||
for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(),
|
||||
AEnd = Construct->arg_end();
|
||||
A != AEnd; ++A)
|
||||
ConvertedConstructorArgs.push_back(*A);
|
||||
} else {
|
||||
// Take the converted initializer.
|
||||
ConvertedConstructorArgs.push_back(FullInit.release());
|
||||
}
|
||||
} else {
|
||||
// No initialization required.
|
||||
}
|
||||
// FullInit is our initializer; strip off CXXBindTemporaryExprs, because
|
||||
// we don't want the initialized object to be destructed.
|
||||
if (CXXBindTemporaryExpr *Binder =
|
||||
dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get()))
|
||||
FullInit = Owned(Binder->getSubExpr());
|
||||
|
||||
// Take the converted arguments and use them for the new expression.
|
||||
NumConsArgs = ConvertedConstructorArgs.size();
|
||||
ConsArgs = (Expr **)ConvertedConstructorArgs.take();
|
||||
Initializer = FullInit.take();
|
||||
}
|
||||
|
||||
// Mark the new and delete operators as referenced.
|
||||
|
@ -1281,8 +1295,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
// C++0x [expr.new]p17:
|
||||
// If the new expression creates an array of objects of class type,
|
||||
// access and ambiguity control are done for the destructor.
|
||||
if (ArraySize && Constructor) {
|
||||
if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) {
|
||||
if (ArraySize && AllocType->isRecordType() && !AllocType->isDependentType()) {
|
||||
if (CXXDestructorDecl *dtor = LookupDestructor(
|
||||
cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl()))) {
|
||||
MarkFunctionReferenced(StartLoc, dtor);
|
||||
CheckDestructorAccess(StartLoc, dtor,
|
||||
PDiag(diag::err_access_dtor)
|
||||
|
@ -1291,25 +1306,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
}
|
||||
|
||||
PlacementArgs.release();
|
||||
ConstructorArgs.release();
|
||||
|
||||
return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
|
||||
PlaceArgs, NumPlaceArgs, TypeIdParens,
|
||||
ArraySize, Constructor, Init,
|
||||
ConsArgs, NumConsArgs,
|
||||
HadMultipleCandidates,
|
||||
OperatorDelete,
|
||||
UsualArrayDeleteWantsSize,
|
||||
PlaceArgs, NumPlaceArgs, TypeIdParens,
|
||||
ArraySize, initStyle, Initializer,
|
||||
ResultType, AllocTypeInfo,
|
||||
StartLoc,
|
||||
Init ? ConstructorRParen :
|
||||
TypeRange.getEnd(),
|
||||
ConstructorLParen, ConstructorRParen));
|
||||
StartLoc, DirectInitRange));
|
||||
}
|
||||
|
||||
/// CheckAllocatedType - Checks that a type is suitable as the allocated type
|
||||
/// \brief Checks that a type is suitable as the allocated type
|
||||
/// in a new-expression.
|
||||
/// dimension off and stores the size expression in ArraySize.
|
||||
bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
|
||||
SourceRange R) {
|
||||
// C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
|
||||
|
|
|
@ -1976,9 +1976,8 @@ public:
|
|||
QualType AllocatedType,
|
||||
TypeSourceInfo *AllocatedTypeInfo,
|
||||
Expr *ArraySize,
|
||||
SourceLocation ConstructorLParen,
|
||||
MultiExprArg ConstructorArgs,
|
||||
SourceLocation ConstructorRParen) {
|
||||
SourceRange DirectInitRange,
|
||||
Expr *Initializer) {
|
||||
return getSema().BuildCXXNew(StartLoc, UseGlobal,
|
||||
PlacementLParen,
|
||||
move(PlacementArgs),
|
||||
|
@ -1987,9 +1986,8 @@ public:
|
|||
AllocatedType,
|
||||
AllocatedTypeInfo,
|
||||
ArraySize,
|
||||
ConstructorLParen,
|
||||
move(ConstructorArgs),
|
||||
ConstructorRParen);
|
||||
DirectInitRange,
|
||||
Initializer);
|
||||
}
|
||||
|
||||
/// \brief Build a new C++ "delete" expression.
|
||||
|
@ -7106,29 +7104,17 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
|
|||
if (getDerived().TransformExprs(E->getPlacementArgs(),
|
||||
E->getNumPlacementArgs(), true,
|
||||
PlacementArgs, &ArgumentChanged))
|
||||
return ExprError();
|
||||
return ExprError();
|
||||
|
||||
// Transform the constructor arguments (if any).
|
||||
// As an annoying corner case, we may have introduced an implicit value-
|
||||
// initialization expression when allocating a new array, which we implicitly
|
||||
// drop. It will be re-created during type checking.
|
||||
ASTOwningVector<Expr*> ConstructorArgs(SemaRef);
|
||||
if (!(E->isArray() && E->getNumConstructorArgs() == 1 &&
|
||||
isa<ImplicitValueInitExpr>(E->getConstructorArgs()[0])) &&
|
||||
TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true,
|
||||
ConstructorArgs, &ArgumentChanged))
|
||||
return ExprError();
|
||||
|
||||
// Transform constructor, new operator, and delete operator.
|
||||
CXXConstructorDecl *Constructor = 0;
|
||||
if (E->getConstructor()) {
|
||||
Constructor = cast_or_null<CXXConstructorDecl>(
|
||||
getDerived().TransformDecl(E->getLocStart(),
|
||||
E->getConstructor()));
|
||||
if (!Constructor)
|
||||
return ExprError();
|
||||
}
|
||||
// Transform the initializer (if any).
|
||||
Expr *OldInit = E->getInitializer();
|
||||
ExprResult NewInit;
|
||||
if (OldInit)
|
||||
NewInit = getDerived().TransformExpr(OldInit);
|
||||
if (NewInit.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
// Transform new operator and delete operator.
|
||||
FunctionDecl *OperatorNew = 0;
|
||||
if (E->getOperatorNew()) {
|
||||
OperatorNew = cast_or_null<FunctionDecl>(
|
||||
|
@ -7150,21 +7136,18 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
|
|||
if (!getDerived().AlwaysRebuild() &&
|
||||
AllocTypeInfo == E->getAllocatedTypeSourceInfo() &&
|
||||
ArraySize.get() == E->getArraySize() &&
|
||||
Constructor == E->getConstructor() &&
|
||||
NewInit.get() == OldInit &&
|
||||
OperatorNew == E->getOperatorNew() &&
|
||||
OperatorDelete == E->getOperatorDelete() &&
|
||||
!ArgumentChanged) {
|
||||
// Mark any declarations we need as referenced.
|
||||
// FIXME: instantiation-specific.
|
||||
if (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<RecordType>()) {
|
||||
|
@ -7174,7 +7157,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
|
@ -7204,7 +7187,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return getDerived().RebuildCXXNewExpr(E->getLocStart(),
|
||||
E->isGlobalNew(),
|
||||
/*FIXME:*/E->getLocStart(),
|
||||
|
@ -7214,9 +7197,8 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
|
|||
AllocType,
|
||||
AllocTypeInfo,
|
||||
ArraySize.get(),
|
||||
E->getConstructorLParen(),
|
||||
move_arg(ConstructorArgs),
|
||||
E->getConstructorRParen());
|
||||
E->getDirectInitRange(),
|
||||
NewInit.take());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -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<FunctionDecl>(Record, Idx));
|
||||
E->setOperatorDelete(ReadDeclAs<FunctionDecl>(Record, Idx));
|
||||
E->setConstructor(ReadDeclAs<CXXConstructorDecl>(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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -verify %s
|
||||
// XFAIL: *
|
||||
|
||||
void f1() {
|
||||
int *n = new int;
|
||||
|
|
|
@ -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 <typename X>
|
||||
struct S {
|
||||
struct Inner {};
|
||||
S() { new Inner[1]; }
|
||||
};
|
||||
|
||||
struct T {
|
||||
};
|
||||
|
||||
template<typename X>
|
||||
void tfn() {
|
||||
new (*(PlacementArg*)0) T[1];
|
||||
}
|
||||
|
||||
void fn() {
|
||||
tfn<int>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue