From be57cf41fb55b48e3f889787960b3ac2eb5e4dbd Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 11 May 2011 05:22:44 +0000 Subject: [PATCH] PR9882: Fix noexcept to deal with dependent new, delete, calls, and dynamic_cast correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131177 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Expr.cpp | 41 +++++++++++-------- .../expr.unary/expr.unary.noexcept/sema.cpp | 10 +++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6499f327b0..7f15d86a19 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1693,6 +1693,9 @@ static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { if (!DC->getTypeAsWritten()->isReferenceType()) return Expr::CT_Cannot; + if (DC->getSubExpr()->isTypeDependent()) + return Expr::CT_Dependent; + return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot; } @@ -1747,7 +1750,11 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: { - CanThrowResult CT = CanCalleeThrow(C,cast(this)->getCalleeDecl()); + CanThrowResult CT; + if (isTypeDependent()) + CT = CT_Dependent; + else + CT = CanCalleeThrow(C, cast(this)->getCalleeDecl()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); @@ -1763,7 +1770,11 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXNewExprClass: { - CanThrowResult CT = MergeCanThrow( + CanThrowResult CT; + if (isTypeDependent()) + CT = CT_Dependent; + else + CT = MergeCanThrow( CanCalleeThrow(C, cast(this)->getOperatorNew()), CanCalleeThrow(C, cast(this)->getConstructor(), /*NullThrows*/false)); @@ -1773,22 +1784,18 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXDeleteExprClass: { - CanThrowResult CT = CanCalleeThrow(C, - cast(this)->getOperatorDelete()); - if (CT == CT_Can) - return CT; - const Expr *Arg = cast(this)->getArgument(); - // Unwrap exactly one implicit cast, which converts all pointers to void*. - if (const ImplicitCastExpr *Cast = dyn_cast(Arg)) - Arg = Cast->getSubExpr(); - if (const PointerType *PT = Arg->getType()->getAs()) { - if (const RecordType *RT = PT->getPointeeType()->getAs()) { - CanThrowResult CT2 = CanCalleeThrow(C, - cast(RT->getDecl())->getDestructor()); - if (CT2 == CT_Can) - return CT2; - CT = MergeCanThrow(CT, CT2); + CanThrowResult CT; + QualType DTy = cast(this)->getDestroyedType(); + if (DTy.isNull() || DTy->isDependentType()) { + CT = CT_Dependent; + } else { + CT = CanCalleeThrow(C, cast(this)->getOperatorDelete()); + if (const RecordType *RT = DTy->getAs()) { + const CXXRecordDecl *RD = cast(RT->getDecl()); + CT = MergeCanThrow(CT, CanCalleeThrow(C, RD->getDestructor())); } + if (CT == CT_Can) + return CT; } return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp index 28ed62c71e..35a8b0f7d0 100644 --- a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -155,12 +155,16 @@ void gencon() { N(G3()); } +template void f(T&&) noexcept; template void late() { B(b, typeid(*(T*)0)); B(b, T(1)); B(b, static_cast(S2(0, 0))); B(b, S1() + T()); + P(f(T())); + P(new (0) T); + P(delete (T*)0); } struct S3 { virtual ~S3() throw(); @@ -168,9 +172,15 @@ struct S3 { explicit S3(int); S3(const S2&); }; +template T&& f2() noexcept; +template +void late2() { + P(dynamic_cast(f2())); +} void operator +(const S1&, float) throw(); void operator +(const S1&, const S3&); void tlate() { late(); late(); + late2(); } -- 2.40.0