aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-09-13 20:15:54 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-09-13 20:15:54 +0000
commit4076dacf1497fb95cb298b9d964fbdbdaf9bde6c (patch)
tree5b91fb94a2e1a10ffbd30a975bebb9865c88395e
parentf1b8911d35bb2830a13267581d3cbde4b6b85db6 (diff)
When applying 'delete' on a pointer-to-array type match GCC and EDG behavior and treat it as 'delete[]'.
Also offer a fix-it hint adding '[]'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113778 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ExprCXX.h12
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaExprCXX.cpp13
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp1
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp1
-rw-r--r--test/CodeGenCXX/delete.cpp7
-rw-r--r--test/SemaCXX/delete.cpp9
7 files changed, 40 insertions, 5 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 219e2f982b..2ad7285f44 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -1107,6 +1107,10 @@ class CXXDeleteExpr : public Expr {
bool GlobalDelete : 1;
// Is this the array form of delete, i.e. "delete[]"?
bool ArrayForm : 1;
+ // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied
+ // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm
+ // will be true).
+ bool ArrayFormAsWritten : 1;
// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
// The pointer expression to be deleted.
@@ -1115,15 +1119,17 @@ class CXXDeleteExpr : public Expr {
SourceLocation Loc;
public:
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
- FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
+ bool arrayFormAsWritten, FunctionDecl *operatorDelete,
+ Expr *arg, SourceLocation loc)
: Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete),
- ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg),
- Loc(loc) { }
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { }
explicit CXXDeleteExpr(EmptyShell Shell)
: Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { }
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
+ bool isArrayFormAsWritten() const { return ArrayFormAsWritten; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index ab16675986..9edceb820c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2448,6 +2448,8 @@ def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behaviour">;
def err_delete_incomplete_class_type : Warning<
"deleting incomplete class type %0; no conversions to pointer type">;
+def warn_delete_array_type : Warning<
+ "'delete' applied to a pointer-to-array type %0 treated as delete[]">;
def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
def err_ambiguous_suitable_delete_member_function_found : Error<
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 382e9bb185..db287515ce 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1438,6 +1438,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// DR599 amends "pointer type" to "pointer to object type" in both cases.
FunctionDecl *OperatorDelete = 0;
+ bool ArrayFormAsWritten = ArrayForm;
if (!Ex->isTypeDependent()) {
QualType Type = Ex->getType();
@@ -1514,7 +1515,14 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// of the delete-expression. ]
ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy),
CK_NoOp);
-
+
+ if (Pointee->isArrayType() && !ArrayForm) {
+ Diag(StartLoc, diag::warn_delete_array_type)
+ << Type << Ex->getSourceRange()
+ << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]");
+ ArrayForm = true;
+ }
+
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
ArrayForm ? OO_Array_Delete : OO_Delete);
@@ -1548,7 +1556,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
}
return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
- OperatorDelete, Ex, StartLoc));
+ ArrayFormAsWritten, OperatorDelete,
+ Ex, StartLoc));
}
/// \brief Check the use of the given variable as a C++ condition in an if,
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index e53bf716a8..a6da3c7296 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1112,6 +1112,7 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
E->GlobalDelete = Record[Idx++];
E->ArrayForm = Record[Idx++];
+ E->ArrayFormAsWritten = Record[Idx++];
E->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
E->Argument = Reader.ReadSubExpr();
E->Loc = Reader.ReadSourceLocation(Record, Idx);
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index b9a22842b9..3701e0c146 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1121,6 +1121,7 @@ void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
Record.push_back(E->isGlobalDelete());
Record.push_back(E->isArrayForm());
+ Record.push_back(E->isArrayFormAsWritten());
Writer.AddDeclRef(E->getOperatorDelete(), Record);
Writer.AddStmt(E->getArgument());
Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record);
diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp
index 1f52a783e6..b8726a863e 100644
--- a/test/CodeGenCXX/delete.cpp
+++ b/test/CodeGenCXX/delete.cpp
@@ -105,3 +105,10 @@ namespace test2 {
delete [] b;
}
}
+
+namespace test3 {
+ void f(int a[10][20]) {
+ // CHECK: call void @_ZdaPv(i8*
+ delete a;
+ }
+}
diff --git a/test/SemaCXX/delete.cpp b/test/SemaCXX/delete.cpp
new file mode 100644
index 0000000000..4567888a37
--- /dev/null
+++ b/test/SemaCXX/delete.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: cp %s %t
+// RUN: %clang_cc1 -fixit -x c++ %t
+// RUN: FileCheck -input-file=%t %s
+
+void f(int a[10][20]) {
+ // CHECK: delete[] a;
+ delete a; // expected-warning {{'delete' applied to a pointer-to-array type}}
+}