Implementation of new and delete parsing and sema.
This version uses VLAs to represent arrays. I'll try an alternative way next, but I want this safe first.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59835 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 2e13352..e6a7b41 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -329,7 +329,13 @@
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->hasLocalSideEffect();
- }
+
+ case CXXNewExprClass:
+ // FIXME: In theory, there might be new expressions that don't have side
+ // effects (e.g. a placement new with an uninitialized POD).
+ case CXXDeleteExprClass:
+ return true;
+ }
}
/// DeclCanBeLvalue - Determine whether the given declaration can be
@@ -481,8 +487,6 @@
case CXXTypeidExprClass:
// C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
return LV_Valid;
- case CXXThisExprClass:
- return LV_InvalidExpression;
default:
break;
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 1155a4b..c0f2985 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -77,6 +77,39 @@
return child_iterator();
}
+// CXXNewExpr
+CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
+ Expr **placementArgs, unsigned numPlaceArgs,
+ bool parenTypeId, QualType alloc,
+ CXXConstructorDecl *constructor, bool initializer,
+ Expr **constructorArgs, unsigned numConsArgs,
+ FunctionDecl *operatorDelete, QualType ty,
+ SourceLocation startLoc, SourceLocation endLoc)
+ : Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
+ Initializer(initializer), NumPlacementArgs(numPlaceArgs),
+ NumConstructorArgs(numConsArgs), OperatorNew(operatorNew),
+ OperatorDelete(operatorDelete), Constructor(constructor), AllocType(alloc),
+ StartLoc(startLoc), EndLoc(endLoc)
+{
+ unsigned TotalSize = NumPlacementArgs + NumConstructorArgs;
+ SubExprs = new Stmt*[TotalSize];
+ unsigned i = 0;
+ for(unsigned j = 0; j < NumPlacementArgs; ++j)
+ SubExprs[i++] = placementArgs[j];
+ for(unsigned j = 0; j < NumConstructorArgs; ++j)
+ SubExprs[i++] = constructorArgs[j];
+ assert(i == TotalSize);
+}
+
+Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
+Stmt::child_iterator CXXNewExpr::child_end() {
+ return &SubExprs[0] + getNumPlacementArgs() + getNumConstructorArgs();
+}
+
+// CXXDeleteExpr
+Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; }
+Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; }
+
OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const {
// All simple function calls (e.g. func()) are implicitly cast to pointer to
// function. As a result, we try and obtain the DeclRefExpr from the
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index cf6d4c0..cb5c44f 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -925,6 +925,49 @@
PrintRawDecl(E->getVarDecl());
}
+void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
+ if (E->isGlobalNew())
+ OS << "::";
+ OS << "new ";
+ unsigned NumPlace = E->getNumPlacementArgs();
+ if (NumPlace > 0) {
+ OS << "(";
+ PrintExpr(E->getPlacementArg(0));
+ for (unsigned i = 1; i < NumPlace; ++i) {
+ OS << ", ";
+ PrintExpr(E->getPlacementArg(i));
+ }
+ OS << ") ";
+ }
+ if (E->isParenTypeId())
+ OS << "(";
+ OS << E->getAllocatedType().getAsString();
+ 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 << ")";
+ }
+}
+
+void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ if (E->isGlobalDelete())
+ OS << "::";
+ OS << "delete ";
+ if (E->isArrayForm())
+ OS << "[] ";
+ PrintExpr(E->getArgument());
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 268922e..8faef8b 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -227,6 +227,12 @@
case CXXZeroInitValueExprClass:
return CXXZeroInitValueExpr::CreateImpl(D, C);
+
+ case CXXNewExprClass:
+ return CXXNewExpr::CreateImpl(D, C);
+
+ case CXXDeleteExprClass:
+ return CXXDeleteExpr::CreateImpl(D, C);
}
}
@@ -1414,3 +1420,66 @@
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
}
+
+void CXXNewExpr::EmitImpl(Serializer& S) const {
+ S.Emit(getType());
+ S.Emit(Initializer);
+ S.Emit(NumPlacementArgs);
+ S.Emit(NumConstructorArgs);
+ S.BatchEmitOwnedPtrs(NumPlacementArgs + NumConstructorArgs, SubExprs);
+ assert((OperatorNew == 0 || S.isRegistered(OperatorNew)) &&
+ (OperatorDelete == 0 || S.isRegistered(OperatorDelete)) &&
+ (Constructor == 0 || S.isRegistered(Constructor)) &&
+ "CXXNewExpr cannot own declarations");
+ S.EmitPtr(OperatorNew);
+ S.EmitPtr(OperatorDelete);
+ S.EmitPtr(Constructor);
+ S.Emit(AllocType);
+ S.Emit(StartLoc);
+ S.Emit(EndLoc);
+}
+
+CXXNewExpr *
+CXXNewExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+ QualType T = QualType::ReadVal(D);
+ bool GlobalNew = D.ReadBool();
+ bool ParenTypeId = D.ReadBool();
+ bool Initializer = D.ReadBool();
+ unsigned NumPlacementArgs = D.ReadInt();
+ unsigned NumConstructorArgs = D.ReadInt();
+ unsigned TotalExprs = NumPlacementArgs + NumConstructorArgs;
+ Stmt** SubExprs = new Stmt*[TotalExprs];
+ D.BatchReadOwnedPtrs(TotalExprs, SubExprs, C);
+ FunctionDecl *OperatorNew = D.ReadPtr<FunctionDecl>();
+ FunctionDecl *OperatorDelete = D.ReadPtr<FunctionDecl>();
+ CXXConstructorDecl *Constructor = D.ReadPtr<CXXConstructorDecl>();
+ QualType AllocType = QualType::ReadVal(D);
+ SourceLocation StartLoc = SourceLocation::ReadVal(D);
+ SourceLocation EndLoc = SourceLocation::ReadVal(D);
+
+ return new CXXNewExpr(T, AllocType, GlobalNew, ParenTypeId, Initializer,
+ NumPlacementArgs, NumConstructorArgs, SubExprs,
+ OperatorNew, OperatorDelete, Constructor, StartLoc,
+ EndLoc);
+}
+
+void CXXDeleteExpr::EmitImpl(Serializer& S) const {
+ S.Emit(getType());
+ S.Emit(GlobalDelete);
+ S.Emit(ArrayForm);
+ S.EmitPtr(OperatorDelete);
+ S.EmitOwnedPtr(Argument);
+ S.Emit(Loc);
+}
+
+CXXDeleteExpr *
+CXXDeleteExpr::CreateImpl(Deserializer& D, ASTContext& C) {
+ QualType Ty = QualType::ReadVal(D);
+ bool GlobalDelete = D.ReadBool();
+ bool ArrayForm = D.ReadBool();
+ FunctionDecl *OperatorDelete = D.ReadPtr<FunctionDecl>();
+ Stmt *Argument = D.ReadOwnedPtr<Stmt>(C);
+ SourceLocation Loc = SourceLocation::ReadVal(D);
+ return new CXXDeleteExpr(Ty, GlobalDelete, ArrayForm, OperatorDelete,
+ cast<Expr>(Argument), Loc);
+}