diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 35456b38efcf..435f7548ea5a 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1369,6 +1369,9 @@ static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { if (DC->isTypeDependent()) return Expr::CT_Dependent; + if (!DC->getTypeAsWritten()->isReferenceType()) + return Expr::CT_Cannot; + return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot; } @@ -1429,7 +1432,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } - case CXXConstructExprClass: { + case CXXConstructExprClass: + case CXXTemporaryObjectExprClass: { CanThrowResult CT = CanCalleeThrow( cast(this)->getConstructor()); if (CT == CT_Can) @@ -1479,7 +1483,6 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXDefaultArgExprClass: case CXXBindTemporaryExprClass: case CXXExprWithTemporariesClass: - case CXXTemporaryObjectExprClass: case ObjCIvarRefExprClass: case ObjCIsaExprClass: case ShuffleVectorExprClass: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 165dd4d0c017..c2b981cdbc26 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -958,6 +958,8 @@ public: bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); + bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1740,6 +1742,10 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { return Success(0, E); } +bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { + return Success(E->getValue(), E); +} + //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp new file mode 100644 index 000000000000..c1865fc4ff32 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -fms-extensions %s + +#define P(e) static_assert(noexcept(e), "expected nothrow") +#define N(e) static_assert(!noexcept(e), "expected throw") + +void simple() { + P(0); + P(0 + 0); + int i; + P(i); + P(sizeof(0)); + P(static_cast(0)); + N(throw 0); +} + +void nospec(); +void allspec() throw(...); +void intspec() throw(int); +void emptyspec() throw(); + +void call() { + N(nospec()); + N(allspec()); + N(intspec()); + P(emptyspec()); +} + +void (*pnospec)(); +void (*pallspec)() throw(...); +void (*pintspec)() throw(int); +void (*pemptyspec)() throw(); + +void callptr() { + N(pnospec()); + N((*pnospec)()); + N(pallspec()); + N((*pallspec)()); + N(pintspec()); + N((*pintspec)()); + P(pemptyspec()); + P((*pemptyspec)()); +} + +struct S1 { + void nospec(); + void allspec() throw(...); + void intspec() throw(int); + void emptyspec() throw(); +}; + +void callmem() { + S1 s; + N(s.nospec()); + N(s.allspec()); + N(s.intspec()); + P(s.emptyspec()); +} + +void (S1::*mpnospec)(); +void (S1::*mpallspec)() throw(...); +void (S1::*mpintspec)() throw(int); +void (S1::*mpemptyspec)() throw(); + +void callmemptr() { + S1 s; + N((s.*mpnospec)()); + N((s.*mpallspec)()); + N((s.*mpintspec)()); + P((s.*mpemptyspec)()); +} + +struct S2 { + S2(); + S2(int, int) throw(); + void operator +(); + void operator -() throw(); + void operator +(int); + void operator -(int) throw(); + operator int(); + operator float() throw(); +}; + +void *operator new(__typeof__(sizeof(int)) sz, int) throw(); + +void implicits() { + N(new int); + P(new (0) int); + N(S2()); + P(S2(0, 0)); + S2 s; + N(+s); + P(-s); + N(s + 0); + P(s - 0); + N(static_cast(s)); + P(static_cast(s)); + // FIXME: test destructors of temporaries +} + +struct V { + virtual ~V() throw(); +}; +struct D : V {}; + +void dyncast() { + V *pv = 0; + D *pd = 0; + P(dynamic_cast(*pd)); + P(dynamic_cast(pd)); + N(dynamic_cast(*pv)); + P(dynamic_cast(pv)); +} + +namespace std { + struct type_info {}; +} + +void idtype() { + P(typeid(V)); + P(typeid((V*)0)); + P(typeid(*(S1*)0)); + N(typeid(*(V*)0)); +} + +void uneval() { + P(sizeof(typeid(*(V*)0))); + P(typeid(typeid(*(V*)0))); +}