forked from OSchip/llvm-project
PR9882: Fix noexcept to deal with dependent new, delete, calls, and
dynamic_cast correctly. llvm-svn: 131177
This commit is contained in:
parent
2a09d65979
commit
c6587cc550
|
@ -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<CallExpr>(this)->getCalleeDecl());
|
||||
CanThrowResult CT;
|
||||
if (isTypeDependent())
|
||||
CT = CT_Dependent;
|
||||
else
|
||||
CT = CanCalleeThrow(C, cast<CallExpr>(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<CXXNewExpr>(this)->getOperatorNew()),
|
||||
CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(),
|
||||
/*NullThrows*/false));
|
||||
|
@ -1773,22 +1784,18 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
|
|||
}
|
||||
|
||||
case CXXDeleteExprClass: {
|
||||
CanThrowResult CT = CanCalleeThrow(C,
|
||||
cast<CXXDeleteExpr>(this)->getOperatorDelete());
|
||||
if (CT == CT_Can)
|
||||
return CT;
|
||||
const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument();
|
||||
// Unwrap exactly one implicit cast, which converts all pointers to void*.
|
||||
if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
|
||||
Arg = Cast->getSubExpr();
|
||||
if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) {
|
||||
if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
|
||||
CanThrowResult CT2 = CanCalleeThrow(C,
|
||||
cast<CXXRecordDecl>(RT->getDecl())->getDestructor());
|
||||
if (CT2 == CT_Can)
|
||||
return CT2;
|
||||
CT = MergeCanThrow(CT, CT2);
|
||||
CanThrowResult CT;
|
||||
QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType();
|
||||
if (DTy.isNull() || DTy->isDependentType()) {
|
||||
CT = CT_Dependent;
|
||||
} else {
|
||||
CT = CanCalleeThrow(C, cast<CXXDeleteExpr>(this)->getOperatorDelete());
|
||||
if (const RecordType *RT = DTy->getAs<RecordType>()) {
|
||||
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
CT = MergeCanThrow(CT, CanCalleeThrow(C, RD->getDestructor()));
|
||||
}
|
||||
if (CT == CT_Can)
|
||||
return CT;
|
||||
}
|
||||
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
|
||||
}
|
||||
|
|
|
@ -155,12 +155,16 @@ void gencon() {
|
|||
N(G3());
|
||||
}
|
||||
|
||||
template <class T> void f(T&&) noexcept;
|
||||
template <typename T, bool b>
|
||||
void late() {
|
||||
B(b, typeid(*(T*)0));
|
||||
B(b, T(1));
|
||||
B(b, static_cast<T>(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 <class T> T&& f2() noexcept;
|
||||
template <typename T>
|
||||
void late2() {
|
||||
P(dynamic_cast<S3&>(f2<T&>()));
|
||||
}
|
||||
void operator +(const S1&, float) throw();
|
||||
void operator +(const S1&, const S3&);
|
||||
void tlate() {
|
||||
late<float, true>();
|
||||
late<S3, false>();
|
||||
late2<S3>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue