r373037 - For P0784R7: add support for new (std::nothrow).
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 26 18:26:49 PDT 2019
Author: rsmith
Date: Thu Sep 26 18:26:49 2019
New Revision: 373037
URL: http://llvm.org/viewvc/llvm-project?rev=373037&view=rev
Log:
For P0784R7: add support for new (std::nothrow).
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=373037&r1=373036&r2=373037&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Sep 26 18:26:49 2019
@@ -2056,6 +2056,7 @@ public:
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++11 std::nullptr_t
+ bool isNothrowT() const; // C++ std::nothrow_t
bool isAlignValT() const; // C++17 std::align_val_t
bool isStdByteType() const; // C++17 std::byte
bool isAtomicType() const; // C11 _Atomic()
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=373037&r1=373036&r2=373037&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Sep 26 18:26:49 2019
@@ -2977,8 +2977,7 @@ bool FunctionDecl::isReplaceableGlobalAl
Ty = Ty->getPointeeType();
if (Ty.getCVRQualifiers() != Qualifiers::Const)
return false;
- const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace())
+ if (Ty->isNothrowT())
Consume();
}
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=373037&r1=373036&r2=373037&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Sep 26 18:26:49 2019
@@ -8043,6 +8043,9 @@ static bool EvaluateArrayNewInitList(Eva
QualType AllocType);
bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
+ if (!Info.getLangOpts().CPlusPlus2a)
+ Info.CCEDiag(E, diag::note_constexpr_new);
+
// We cannot speculatively evaluate a delete expression.
if (Info.SpeculativeEvaluationDepth)
return false;
@@ -8054,17 +8057,27 @@ bool PointerExprEvaluator::VisitCXXNewEx
return false;
}
- // FIXME: There is no restriction on this, but it's not clear that it
- // makes any sense. We get here for cases such as:
- //
- // new (std::align_val_t{N}) X(int)
- //
- // (which should presumably be valid only if N is a multiple of
- // alignof(int).
- if (E->getNumPlacementArgs())
- return Error(E, diag::note_constexpr_new_placement);
- if (!Info.getLangOpts().CPlusPlus2a)
- Info.CCEDiag(E, diag::note_constexpr_new);
+ bool IsNothrow = false;
+ if (E->getNumPlacementArgs()) {
+ // The only new-placement list we support is of the form (std::nothrow).
+ //
+ // FIXME: There is no restriction on this, but it's not clear that any
+ // other form makes any sense. We get here for cases such as:
+ //
+ // new (std::align_val_t{N}) X(int)
+ //
+ // (which should presumably be valid only if N is a multiple of
+ // alignof(int), and in any case can't be deallocated unless N is
+ // alignof(X) and X has new-extended alignment).
+ if (E->getNumPlacementArgs() != 1 ||
+ !E->getPlacementArg(0)->getType()->isNothrowT())
+ return Error(E, diag::note_constexpr_new_placement);
+
+ LValue Nothrow;
+ if (!EvaluateLValue(E->getPlacementArg(0), Nothrow, Info))
+ return false;
+ IsNothrow = true;
+ }
const Expr *Init = E->getInitializer();
const InitListExpr *ResizedArrayILE = nullptr;
@@ -8087,6 +8100,9 @@ bool PointerExprEvaluator::VisitCXXNewEx
// -- [...] its value before converting to size_t [or] applying the
// second standard conversion sequence is less than zero
if (ArrayBound.isSigned() && ArrayBound.isNegative()) {
+ if (IsNothrow)
+ return ZeroInitialization(E);
+
Info.FFDiag(*ArraySize, diag::note_constexpr_new_negative)
<< ArrayBound << (*ArraySize)->getSourceRange();
return false;
@@ -8097,6 +8113,9 @@ bool PointerExprEvaluator::VisitCXXNewEx
if (ConstantArrayType::getNumAddressingBits(Info.Ctx, AllocType,
ArrayBound) >
ConstantArrayType::getMaxSizeBits(Info.Ctx)) {
+ if (IsNothrow)
+ return ZeroInitialization(E);
+
Info.FFDiag(*ArraySize, diag::note_constexpr_new_too_large)
<< ArrayBound << (*ArraySize)->getSourceRange();
return false;
@@ -8114,6 +8133,9 @@ bool PointerExprEvaluator::VisitCXXNewEx
llvm::APInt InitBound = CAT->getSize().zextOrSelf(Bits);
llvm::APInt AllocBound = ArrayBound.zextOrSelf(Bits);
if (InitBound.ugt(AllocBound)) {
+ if (IsNothrow)
+ return ZeroInitialization(E);
+
Info.FFDiag(*ArraySize, diag::note_constexpr_new_too_small)
<< AllocBound.toString(10, /*Signed=*/false)
<< InitBound.toString(10, /*Signed=*/false)
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=373037&r1=373036&r2=373037&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Sep 26 18:26:49 2019
@@ -2490,6 +2490,15 @@ bool QualType::isCXX11PODType(const ASTC
return false;
}
+bool Type::isNothrowT() const {
+ if (const auto *RD = getAsCXXRecordDecl()) {
+ IdentifierInfo *II = RD->getIdentifier();
+ if (II && II->isStr("nothrow_t") && RD->isInStdNamespace())
+ return true;
+ }
+ return false;
+}
+
bool Type::isAlignValT() const {
if (const auto *ET = getAs<EnumType>()) {
IdentifierInfo *II = ET->getDecl()->getIdentifier();
Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp?rev=373037&r1=373036&r2=373037&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp Thu Sep 26 18:26:49 2019
@@ -926,6 +926,24 @@ namespace dynamic_alloc {
static_assert(erroneous_array_bound(-1)); // expected-error {{constant expression}} expected-note {{in call}}
static_assert(erroneous_array_bound(1LL << 62)); // expected-error {{constant expression}} expected-note {{in call}}
+ constexpr bool erroneous_array_bound_nothrow(long long n) {
+ int *p = new (std::nothrow) int[n];
+ bool result = p != 0;
+ delete[] p;
+ return result;
+ }
+ static_assert(erroneous_array_bound_nothrow(3));
+ static_assert(erroneous_array_bound_nothrow(0));
+ static_assert(!erroneous_array_bound_nothrow(-1));
+ static_assert(!erroneous_array_bound_nothrow(1LL << 62));
+
+ constexpr bool evaluate_nothrow_arg() {
+ bool ok = false;
+ delete new ((ok = true, std::nothrow)) int;
+ return ok;
+ }
+ static_assert(evaluate_nothrow_arg());
+
constexpr void double_delete() { // expected-error {{never produces a constant expression}}
int *p = new int;
delete p;
More information about the cfe-commits
mailing list