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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits