Skip to content

Commit f8cedc6

Browse files
committed
[clang] Never wrap a nullptr in CXXNewExpr::getArraySize()
Otherwise callers of these functions have to check both the return value for and the contents of the returned llvm::Optional. Fixes #53742 Differential Revision: https://reviews.llvm.org/D119525
1 parent 5c4f749 commit f8cedc6

File tree

6 files changed

+48
-8
lines changed

6 files changed

+48
-8
lines changed

clang/docs/ReleaseNotes.rst

+10-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ Major New Features
5454
There is an analogous ``zero_call_used_regs`` attribute to allow for finer
5555
control of this feature.
5656

57+
Bug Fixes
58+
------------------
59+
- ``CXXNewExpr::getArraySize()`` previously returned a ``llvm::Optional``
60+
wrapping a ``nullptr`` when the ``CXXNewExpr`` did not have an array
61+
size expression. This was fixed and ``::getArraySize()`` will now always
62+
either return ``None`` or a ``llvm::Optional`` wrapping a valid ``Expr*``.
63+
This fixes `Issue #53742<https://github.com/llvm/llvm-project/issues/53742>`_.
64+
5765
Improvements to Clang's diagnostics
5866
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5967

@@ -83,7 +91,8 @@ Attribute Changes in Clang
8391
- Added support for parameter pack expansion in `clang::annotate`.
8492

8593
- The ``overloadable`` attribute can now be written in all of the syntactic
86-
locations a declaration attribute may appear. Fixes PR53805.
94+
locations a declaration attribute may appear.
95+
This fixes `Issue #53805<https://github.com/llvm/llvm-project/issues/53805>`_.
8796

8897
Windows Support
8998
---------------

clang/include/clang/AST/ExprCXX.h

+19-2
Original file line numberDiff line numberDiff line change
@@ -2261,15 +2261,32 @@ class CXXNewExpr final
22612261

22622262
bool isArray() const { return CXXNewExprBits.IsArray; }
22632263

2264+
/// This might return None even if isArray() returns true,
2265+
/// since there might not be an array size expression.
2266+
/// If the result is not-None, it will never wrap a nullptr.
22642267
Optional<Expr *> getArraySize() {
22652268
if (!isArray())
22662269
return None;
2267-
return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
2270+
2271+
if (auto *Result =
2272+
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
2273+
return Result;
2274+
2275+
return None;
22682276
}
2277+
2278+
/// This might return None even if isArray() returns true,
2279+
/// since there might not be an array size expression.
2280+
/// If the result is not-None, it will never wrap a nullptr.
22692281
Optional<const Expr *> getArraySize() const {
22702282
if (!isArray())
22712283
return None;
2272-
return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]);
2284+
2285+
if (auto *Result =
2286+
cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]))
2287+
return Result;
2288+
2289+
return None;
22732290
}
22742291

22752292
unsigned getNumPlacementArgs() const {

clang/lib/AST/ExprConstant.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9427,7 +9427,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
94279427
bool ValueInit = false;
94289428

94299429
QualType AllocType = E->getAllocatedType();
9430-
if (Optional<const Expr*> ArraySize = E->getArraySize()) {
9430+
if (Optional<const Expr *> ArraySize = E->getArraySize()) {
94319431
const Expr *Stripped = *ArraySize;
94329432
for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
94339433
Stripped = ICE->getSubExpr())

clang/lib/AST/StmtPrinter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -2132,10 +2132,10 @@ void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
21322132
if (E->isParenTypeId())
21332133
OS << "(";
21342134
std::string TypeS;
2135-
if (Optional<Expr *> Size = E->getArraySize()) {
2135+
if (E->isArray()) {
21362136
llvm::raw_string_ostream s(TypeS);
21372137
s << '[';
2138-
if (*Size)
2138+
if (Optional<Expr *> Size = E->getArraySize())
21392139
(*Size)->printPretty(s, Helper, Policy);
21402140
s << ']';
21412141
}

clang/lib/Sema/TreeTransform.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -11912,9 +11912,9 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
1191211912

1191311913
// Transform the size of the array we're allocating (if any).
1191411914
Optional<Expr *> ArraySize;
11915-
if (Optional<Expr *> OldArraySize = E->getArraySize()) {
11915+
if (E->isArray()) {
1191611916
ExprResult NewArraySize;
11917-
if (*OldArraySize) {
11917+
if (Optional<Expr *> OldArraySize = E->getArraySize()) {
1191811918
NewArraySize = getDerived().TransformExpr(*OldArraySize);
1191911919
if (NewArraySize.isInvalid())
1192011920
return ExprError();

clang/test/AST/issue53742.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -fsyntax-only %s -verify
2+
3+
struct Data {
4+
char *a;
5+
char *b;
6+
bool *c;
7+
};
8+
9+
int main() {
10+
Data in;
11+
in.a = new char[](); // expected-error {{cannot determine allocated array size from initializer}}
12+
in.c = new bool[100]();
13+
in.b = new char[100]();
14+
}

0 commit comments

Comments
 (0)