diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 4ba0d07e954320c91d749c6df43f5f6c7b767545..1b0a63e32a2bced4ca72e1997d3c1362cf7cd2a4 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -2441,9 +2441,6 @@ class CXXNoexceptExpr : public Expr { SourceRange Range; friend class ASTStmtReader; - void setOperand(Expr *E) { Operand = E; } - void setSourceRange(const SourceRange &R) { Range = R; } - void setValue(bool V) { Value = V; } public: CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 435f7548ea5a5f0ebb55e49cfe252ded18c0af41..65dafae35e472387664b80aa20b7937c151a5504 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1347,6 +1347,11 @@ static Expr::CanThrowResult CanCalleeThrow(const Decl *D, if (!VD) // If we have no clue what we're calling, assume the worst. return Expr::CT_Can; + // As an extension, we assume that __attribute__((nothrow)) functions don't + // throw. + if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>()) + return Expr::CT_Cannot; + QualType T = VD->getType(); const FunctionProtoType *FT; if ((FT = T->getAs<FunctionProtoType>())) { @@ -1482,7 +1487,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case VAArgExprClass: case CXXDefaultArgExprClass: case CXXBindTemporaryExprClass: - case CXXExprWithTemporariesClass: + case CXXExprWithTemporariesClass: // FIXME: this thing calls destructors case ObjCIvarRefExprClass: case ObjCIsaExprClass: case ShuffleVectorExprClass: diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 0449a989302213c34bed5e7aee7638b98bbf0caf..c2b054b1f8fed538ae8178b3a07892a6648f9151 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1255,9 +1255,9 @@ void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { VisitExpr(E); - E->setValue((bool)Record[Idx++]); - E->setSourceRange(Reader.ReadSourceRange(Record, Idx)); - E->setOperand(Reader.ReadSubExpr()); + E->Value = (bool)Record[Idx++]; + E->Range = Reader.ReadSourceRange(Record, Idx); + E->Operand = Reader.ReadSubExpr(); } Stmt *ASTReader::ReadStmt(llvm::BitstreamCursor &Cursor) { diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp b/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp index aa2d553542d2bffb10d9ce258b13e75dcb49c7bf..e7a8b1e47f8f93db72e6b4023ced6009da47f373 100644 --- a/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp @@ -11,9 +11,9 @@ struct E { void test() { bool b; - // CHECK: store i8 1, i8* %b, align 1 + // CHECK: store i8 1 b = noexcept(0); - // CHECK: store i8 0, i8* %b, align 1 + // CHECK: store i8 0 b = noexcept(throw 0); b = f1(); b = f2(); 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 e4d1537cdc184f2c31e477738c8e5495502f002b..5182709c89ddc4745024fa13f31b427651596cdc 100644 --- a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -19,12 +19,14 @@ void nospec(); void allspec() throw(...); void intspec() throw(int); void emptyspec() throw(); +void nothrowattr() __attribute__((nothrow)); void call() { N(nospec()); N(allspec()); N(intspec()); P(emptyspec()); + P(nothrowattr()); } void (*pnospec)();