From 9b982078e9076b9b36586ae8b6bf21a3868f1b93 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 7 Jul 2014 00:12:30 +0000 Subject: [PATCH] Add an AST node for __leave statements, hook it up. Codegen is still missing (and I won't work on that), but __leave is now as implemented as __try and friends. llvm-svn: 212425 --- clang/include/clang-c/Index.h | 6 +++++- clang/include/clang/AST/DataRecursiveASTVisitor.h | 1 + clang/include/clang/AST/RecursiveASTVisitor.h | 1 + clang/include/clang/AST/Stmt.h | 25 +++++++++++++++++++++++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 -- clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/StmtPrinter.cpp | 5 +++++ clang/lib/AST/StmtProfile.cpp | 4 ++++ clang/lib/CodeGen/CGException.cpp | 4 ++++ clang/lib/CodeGen/CGStmt.cpp | 3 +++ clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Sema/SemaStmt.cpp | 2 +- clang/lib/Sema/TreeTransform.h | 6 ++++++ clang/lib/Serialization/ASTReaderStmt.cpp | 8 ++++++++ clang/lib/Serialization/ASTWriterStmt.cpp | 6 ++++++ clang/test/CodeGen/exceptions-seh.c | 1 + clang/test/Sema/__try.c | 11 ++++------ clang/tools/libclang/CIndex.cpp | 2 ++ clang/tools/libclang/CXCursor.cpp | 4 ++++ 20 files changed, 83 insertions(+), 11 deletions(-) diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 561bed9..4819293 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2155,7 +2155,11 @@ enum CXCursorKind { */ CXCursor_OMPSingleDirective = 237, - CXCursor_LastStmt = CXCursor_OMPSingleDirective, + /** \brief Windows Structured Exception Handling's leave statement. + */ + CXCursor_SEHLeaveStmt = 238, + + CXCursor_LastStmt = CXCursor_SEHLeaveStmt, /** * \brief Cursor that represents the translation unit itself. diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index f35d4f2..1556bab 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -2232,6 +2232,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { DEF_TRAVERSE_STMT(SEHTryStmt, {}) DEF_TRAVERSE_STMT(SEHExceptStmt, {}) DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) +DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index cde5ade..31580ca 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2254,6 +2254,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { DEF_TRAVERSE_STMT(SEHTryStmt, {}) DEF_TRAVERSE_STMT(SEHExceptStmt, {}) DEF_TRAVERSE_STMT(SEHFinallyStmt, {}) +DEF_TRAVERSE_STMT(SEHLeaveStmt, {}) DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 99e84f8..790c8e3 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1936,6 +1936,31 @@ public: } }; +/// Represents a __leave statement. +/// +class SEHLeaveStmt : public Stmt { + SourceLocation LeaveLoc; +public: + explicit SEHLeaveStmt(SourceLocation LL) + : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} + + /// \brief Build an empty __leave statement. + explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { } + + SourceLocation getLeaveLoc() const { return LeaveLoc; } + void setLeaveLoc(SourceLocation L) { LeaveLoc = L; } + + SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHLeaveStmtClass; + } + + // Iterators + child_range children() { return child_range(); } +}; + /// \brief This captures a statement into a function. For example, the following /// pragma annotated compound statement can be represented as a CapturedStmt, /// and this compound statement is the body of an anonymous outlined function. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1b8e01e..321f24d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5153,8 +5153,6 @@ def err_need_header_before_typeid : Error< "you need to include before using the 'typeid' operator">; def err_need_header_before_ms_uuidof : Error< "you need to include before using the '__uuidof' operator">; -def err_ms___leave_unimplemented : Error< - "__leave support not implemented yet">; def err_ms___leave_not_in___try : Error< "'__leave' statement not in __try block">; def err_uuidof_without_guid : Error< diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 17a56ad..aec07ec 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -170,6 +170,7 @@ def CXXUuidofExpr : DStmt; def SEHTryStmt : Stmt; def SEHExceptStmt : Stmt; def SEHFinallyStmt : Stmt; +def SEHLeaveStmt : Stmt; def MSDependentExistsStmt : Stmt; // OpenCL Extensions. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index fe91b15..331fb1f 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1334,6 +1334,7 @@ namespace clang { EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr). EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type). + STMT_SEH_LEAVE, // SEHLeaveStmt STMT_SEH_EXCEPT, // SEHExceptStmt STMT_SEH_FINALLY, // SEHFinallyStmt STMT_SEH_TRY, // SEHTryStmt diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 28ce174..1d96c49 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -573,6 +573,11 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { OS << "\n"; } +void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) { + Indent() << "__leave;"; + if (Policy.IncludeNewlines) OS << "\n"; +} + //===----------------------------------------------------------------------===// // OpenMP clauses printing methods //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index f562ed6..f666be7 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -214,6 +214,10 @@ void StmtProfiler::VisitSEHExceptStmt(const SEHExceptStmt *S) { VisitStmt(S); } +void StmtProfiler::VisitSEHLeaveStmt(const SEHLeaveStmt *S) { + VisitStmt(S); +} + void StmtProfiler::VisitCapturedStmt(const CapturedStmt *S) { VisitStmt(S); } diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index ffcab07..1bbda5c 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1632,3 +1632,7 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { CGM.ErrorUnsupported(&S, "SEH __try"); } + +void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) { + CGM.ErrorUnsupported(&S, "SEH __leave"); +} diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 9cc23e2..6fed5d3 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -173,6 +173,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::SEHTryStmtClass: EmitSEHTryStmt(cast(*S)); break; + case Stmt::SEHLeaveStmtClass: + EmitSEHLeaveStmt(cast(*S)); + break; case Stmt::OMPParallelDirectiveClass: EmitOMPParallelDirective(cast(*S)); break; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3446216..055e9356 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1889,6 +1889,7 @@ public: void EmitCXXTryStmt(const CXXTryStmt &S); void EmitSEHTryStmt(const SEHTryStmt &S); + void EmitSEHLeaveStmt(const SEHLeaveStmt &S); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, const ArrayRef &Attrs = None); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0b77891..dc5619d 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3285,7 +3285,7 @@ Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) { if (!SEHTryParent) return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try)); - return StmtError(Diag(Loc, diag::err_ms___leave_unimplemented)); + return new (Context) SEHLeaveStmt(Loc); } StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c48c4d0..64c717f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6376,6 +6376,12 @@ StmtResult TreeTransform::TransformSEHHandler(Stmt *Handler) { return getDerived().TransformSEHExceptStmt(cast(Handler)); } +template +StmtResult +TreeTransform::TransformSEHLeaveStmt(SEHLeaveStmt *S) { + return S; +} + //===----------------------------------------------------------------------===// // OpenMP directive transformation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index c94c435..a8cfe9e0 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1609,6 +1609,11 @@ void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { E->setExprOperand(Reader.ReadSubExpr()); } +void ASTStmtReader::VisitSEHLeaveStmt(SEHLeaveStmt *S) { + VisitStmt(S); + S->setLeaveLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitSEHExceptStmt(SEHExceptStmt *S) { VisitStmt(S); S->Loc = ReadSourceLocation(Record, Idx); @@ -2381,6 +2386,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case EXPR_OBJC_BOOL_LITERAL: S = new (Context) ObjCBoolLiteralExpr(Empty); break; + case STMT_SEH_LEAVE: + S = new (Context) SEHLeaveStmt(Empty); + break; case STMT_SEH_EXCEPT: S = new (Context) SEHExceptStmt(Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 8655bc6..11be3fd 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1650,6 +1650,12 @@ void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { Code = serialization::STMT_SEH_TRY; } +void ASTStmtWriter::VisitSEHLeaveStmt(SEHLeaveStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getLeaveLoc(), Record); + Code = serialization::STMT_SEH_LEAVE; +} + //===----------------------------------------------------------------------===// // OpenMP Clauses. //===----------------------------------------------------------------------===// diff --git a/clang/test/CodeGen/exceptions-seh.c b/clang/test/CodeGen/exceptions-seh.c index f7d24bd..0a82e37 100644 --- a/clang/test/CodeGen/exceptions-seh.c +++ b/clang/test/CodeGen/exceptions-seh.c @@ -7,6 +7,7 @@ int SaveDiv(int numerator, int denominator, int *res) { int myres = 0; __try { myres = numerator / denominator; + __leave; } __except (1) { return 0; } diff --git a/clang/test/Sema/__try.c b/clang/test/Sema/__try.c index 3e03842..a355de9 100644 --- a/clang/test/Sema/__try.c +++ b/clang/test/Sema/__try.c @@ -171,21 +171,18 @@ void TEST() { (void)AbnormalTermination(); // expected-error{{only allowed in __finally block}} } -void test___leave() { +void test_seh_leave_stmt() { __leave; // expected-error{{'__leave' statement not in __try block}} __try { - // FIXME: should be fine - __leave; // expected-error{{not implemented yet}} - // FIXME: should say "expected ';' after __leave statement" - __leave 4; // expected-error{{not implemented yet}} expected-warning{{expression result unused}} + __leave; + __leave 4; // expected-error{{expected ';' after __leave statement}} } __except(1) { __leave; // expected-error{{'__leave' statement not in __try block}} } __try { - // FIXME: should be fine - __leave; // expected-error{{not implemented yet}} + __leave; } __finally { __leave; // expected-error{{'__leave' statement not in __try block}} } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 0e5ef31..f008cfc 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -3893,6 +3893,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("SEHExceptStmt"); case CXCursor_SEHFinallyStmt: return cxstring::createRef("SEHFinallyStmt"); + case CXCursor_SEHLeaveStmt: + return cxstring::createRef("SEHLeaveStmt"); case CXCursor_NullStmt: return cxstring::createRef("NullStmt"); case CXCursor_InvalidFile: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index f3a3a6e..8c9cdf4 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -215,6 +215,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::SEHFinallyStmtClass: K = CXCursor_SEHFinallyStmt; break; + + case Stmt::SEHLeaveStmtClass: + K = CXCursor_SEHLeaveStmt; + break; case Stmt::ArrayTypeTraitExprClass: case Stmt::AsTypeExprClass: -- 2.7.4