summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-04 05:35:53 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-04 05:35:53 +0000
commitbcc9bcb65fe28af2ca256af21b34aed76c357097 (patch)
treecb3411ee563134c8e1230c0943ceb90cdb063de1 /clang/lib/Sema/SemaExprCXX.cpp
parent5d8e7593e384abe27a9ed4cd80fedd2cb46a127a (diff)
downloadbcm5719-llvm-bcc9bcb65fe28af2ca256af21b34aed76c357097.tar.gz
bcm5719-llvm-bcc9bcb65fe28af2ca256af21b34aed76c357097.zip
Fix a rejects-valid in C++11: array new of a negative size, or overflowing array
new, is well-formed with defined semantics of throwing (a type which can be caught by a handler for) std::bad_array_new_length, unlike in C++98 where it is somewhere nebulous between undefined behavior and ill-formed. If the array size is an integral constant expression and satisfies one of these criteria, we would previous the array new expression, but now in C++11 mode, we merely issue a warning (the code is still rejected in C++98 mode, naturally). We don't yet implement new C++11 semantics correctly (see PR11644), but we do implement the overflow checking, and (for the default operator new) convert such expressions to an exception, so accepting such code now does not seem especially unsafe. llvm-svn: 149767
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp48
1 files changed, 32 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 793b70789a9..a0fb6e44d9c 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1018,28 +1018,44 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (!SizeType->isIntegralOrUnscopedEnumerationType())
return ExprError();
- // Let's see if this is a constant < 0. If so, we reject it out of hand.
- // We don't care about special rules, so we tell the machinery it's not
- // evaluated - it gives us a result in more cases.
+ // C++98 [expr.new]p7:
+ // The expression in a direct-new-declarator shall have integral type
+ // with a non-negative value.
+ //
+ // Let's see if this is a constant < 0. If so, we reject it out of
+ // hand. Otherwise, if it's not a constant, we must have an unparenthesized
+ // array type.
+ //
+ // Note: such a construct has well-defined semantics in C++11: it throws
+ // std::bad_array_new_length.
if (!ArraySize->isValueDependent()) {
llvm::APSInt Value;
- if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) {
+ if (ArraySize->isIntegerConstantExpr(Value, Context)) {
if (Value < llvm::APSInt(
llvm::APInt::getNullValue(Value.getBitWidth()),
- Value.isUnsigned()))
- return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
- diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange());
-
- if (!AllocType->isDependentType()) {
- unsigned ActiveSizeBits
- = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ Value.isUnsigned())) {
+ if (getLangOptions().CPlusPlus0x)
Diag(ArraySize->getSourceRange().getBegin(),
- diag::err_array_too_large)
- << Value.toString(10)
+ diag::warn_typecheck_negative_array_new_size)
<< ArraySize->getSourceRange();
- return ExprError();
+ else
+ return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange());
+ } else if (!AllocType->isDependentType()) {
+ unsigned ActiveSizeBits =
+ ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ if (getLangOptions().CPlusPlus0x)
+ Diag(ArraySize->getSourceRange().getBegin(),
+ diag::warn_array_new_too_large)
+ << Value.toString(10)
+ << ArraySize->getSourceRange();
+ else
+ return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_array_too_large)
+ << Value.toString(10)
+ << ArraySize->getSourceRange());
}
}
} else if (TypeIdParens.isValid()) {
OpenPOWER on IntegriCloud