[cfe-commits] r113621 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp
Douglas Gregor
dgregor at apple.com
Fri Sep 10 14:58:16 PDT 2010
On Sep 10, 2010, at 1:55 PM, Sebastian Redl wrote:
> Author: cornedbee
> Date: Fri Sep 10 15:55:33 2010
> New Revision: 113621
>
> URL: http://llvm.org/viewvc/llvm-project?rev=113621&view=rev
> Log:
> Implement Expr::CanThrow, a function that applies the noexcept operator rules to expressions.
>
> Modified:
> cfe/trunk/include/clang/AST/Expr.h
> cfe/trunk/lib/AST/Expr.cpp
>
> +static Expr::CanThrowResult CanCalleeThrow(const Decl *D,
> + bool NullThrows = true) {
> + if (!D)
> + return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
> +
> + // See if we can get a function type from the decl somehow.
> + const ValueDecl *VD = dyn_cast<ValueDecl>(D);
> + if (!VD) // If we have no clue what we're calling, assume the worst.
> + return Expr::CT_Can;
> +
> + QualType T = VD->getType();
> + const FunctionProtoType *FT;
> + if ((FT = T->getAs<FunctionProtoType>())) {
> + } else if (const PointerType *PT = T->getAs<PointerType>())
> + FT = PT->getPointeeType()->getAs<FunctionProtoType>();
> + else if (const ReferenceType *RT = T->getAs<ReferenceType>())
> + FT = RT->getPointeeType()->getAs<FunctionProtoType>();
> + else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
> + FT = MT->getPointeeType()->getAs<FunctionProtoType>();
> + else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
> + FT = BT->getPointeeType()->getAs<FunctionProtoType>();
> +
> + if (!FT)
> + return Expr::CT_Can;
> +
> + return FT->hasEmptyExceptionSpec() ? Expr::CT_Cannot : Expr::CT_Can;
> +}
We should also be checking whether D is a FunctionDecl with the nothrow attribute. At least, I think GCC does this.
> +static Expr::CanThrowResult CanTypeidThrow(ASTContext &C,
> + const CXXTypeidExpr *DC) {
> + if (DC->isTypeOperand())
> + return Expr::CT_Cannot;
> +
> + Expr *Op = DC->getExprOperand();
> + if (Op->isTypeDependent())
> + return Expr::CT_Dependent;
> +
> + const RecordType *RT = Op->getType()->getAs<RecordType>();
> + if (!RT)
> + return Expr::CT_Cannot;
> +
> + if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
> + return Expr::CT_Cannot;
> +
> + if (Op->Classify(C).isPRValue())
> + return Expr::CT_Cannot;
> +
> + return Expr::CT_Can;
> +}
> +
> +Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
> + // C++ [expr.unary.noexcept]p3:
> + // [Can throw] if in a potentially-evaluated context the expression would
> + // contain:
> + switch (getStmtClass()) {
> + case CXXThrowExprClass:
> + // - a potentially evaluated throw-expression
> + return CT_Can;
> +
> + case CXXDynamicCastExprClass: {
> + // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
> + // where T is a reference type, that requires a run-time check
> + CanThrowResult CT = CanDynamicCastThrow(cast<CXXDynamicCastExpr>(this));
> + if (CT == CT_Can)
> + return CT;
> + return MergeCanThrow(CT, CanSubExprsThrow(C, this));
> + }
> +
> + case CXXTypeidExprClass:
> + // - a potentially evaluated typeid expression applied to a glvalue
> + // expression whose type is a polymorphic class type
> + return CanTypeidThrow(C, cast<CXXTypeidExpr>(this));
> +
> + // - a potentially evaluated call to a function, member function, function
> + // pointer, or member function pointer that does not have a non-throwing
> + // exception-specification
> + case CallExprClass:
> + case CXXOperatorCallExprClass:
> + case CXXMemberCallExprClass: {
> + CanThrowResult CT = CanCalleeThrow(cast<CallExpr>(this)->getCalleeDecl());
> + if (CT == CT_Can)
> + return CT;
> + return MergeCanThrow(CT, CanSubExprsThrow(C, this));
> + }
> +
> + case CXXConstructExprClass: {
> + CanThrowResult CT = CanCalleeThrow(
> + cast<CXXConstructExpr>(this)->getConstructor());
> + if (CT == CT_Can)
> + return CT;
> + return MergeCanThrow(CT, CanSubExprsThrow(C, this));
> + }
CXXTemporaryObjectExprClass?
>
> + case CXXExprWithTemporariesClass:
CXXExprWithTemporaries is where we'll end up calling the destructors for temporary objects.
Looks good!
- Doug
More information about the cfe-commits
mailing list