]> granicus.if.org Git - clang/commitdiff
Add an AST node for __leave statements, hook it up.
authorNico Weber <nicolasweber@gmx.de>
Mon, 7 Jul 2014 00:12:30 +0000 (00:12 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 7 Jul 2014 00:12:30 +0000 (00:12 +0000)
Codegen is still missing (and I won't work on that), but __leave is now
as implemented as __try and friends.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212425 91177308-0d34-0410-b5e6-96231b3b80d8

20 files changed:
include/clang-c/Index.h
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/StmtNodes.td
include/clang/Serialization/ASTBitCodes.h
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/CodeGen/CGException.cpp
lib/CodeGen/CGStmt.cpp
lib/CodeGen/CodeGenFunction.h
lib/Sema/SemaStmt.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/CodeGen/exceptions-seh.c
test/Sema/__try.c
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index 561bed923150a91920fa45f04aa543ee23acc742..4819293c734cace7390f1001115371a6ac43980d 100644 (file)
@@ -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.
index f35d4f2f8571f51d749862751475c9e84526aaba..1556babb7bd02e14fc7b502b17b3034f298561c2 100644 (file)
@@ -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, {})
index cde5adedbd0be76bb3fc6bd5955fbbb2ae302266..31580ca9af577b611f5c8a7876dbd26ccd072656 100644 (file)
@@ -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, {})
index 99e84f8267dae53ebae4558febb0c7e60de0d9ee..790c8e3e663dfc52712e4c5759f831718fe1262b 100644 (file)
@@ -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.
index 1b8e01ebc22122a060ddde47fefcca15e8d726b9..321f24d735db5363d41dccc9040ebe9423495b8d 100644 (file)
@@ -5153,8 +5153,6 @@ def err_need_header_before_typeid : Error<
   "you need to include <typeinfo> before using the 'typeid' operator">;
 def err_need_header_before_ms_uuidof : Error<
   "you need to include <guiddef.h> 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<
index 17a56adcf6e899a39a07545bc6025175ad545991..aec07ec764a33472b1634025528f232660a68b89 100644 (file)
@@ -170,6 +170,7 @@ def CXXUuidofExpr : DStmt<Expr>;
 def SEHTryStmt : Stmt;
 def SEHExceptStmt : Stmt;
 def SEHFinallyStmt : Stmt;
+def SEHLeaveStmt : Stmt;
 def MSDependentExistsStmt : Stmt;
 
 // OpenCL Extensions.
index fe91b15d99c93898726f362405c5e14d19ab47b9..331fb1f76a67752135074ab792a102f150e18976 100644 (file)
@@ -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
index 28ce174207d42c0f30fd2607fdec387d441b5a42..1d96c49c7bb54937028aaca091c37cb35bee01da 100644 (file)
@@ -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
 //===----------------------------------------------------------------------===//
index f562ed6aa7625eacdf48dd483d2664081cb3dda5..f666be7008f67c059d4a4063f75059f54d807ecb 100644 (file)
@@ -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);
 }
index ffcab074caad88dce6c7c79dd03fee2be30087ca..1bbda5cbf09c9d557801043e67f9fa2069181752 100644 (file)
@@ -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");
+}
index 9cc23e2632a9d7efd67eacf6d3ab15818fb469a2..6fed5d3a9d4dbb357b61a9042951de0ad38a55d2 100644 (file)
@@ -173,6 +173,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
   case Stmt::SEHTryStmtClass:
     EmitSEHTryStmt(cast<SEHTryStmt>(*S));
     break;
+  case Stmt::SEHLeaveStmtClass:
+    EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
+    break;
   case Stmt::OMPParallelDirectiveClass:
     EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
     break;
index 3446216f22480356bd2823659fd72d021d4140d9..055e935684268e00a3cc8c856db0a89a46757170 100644 (file)
@@ -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<const Attr *> &Attrs = None);
 
index 0b778918543e186f3262f9a1e0da625bed2c9b78..dc5619db9a468efd99af82ed0d624ea1c2b91d19 100644 (file)
@@ -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,
index c48c4d04f5eb7d6f3edfbb47716dea404fdbefa7..64c717f570ab3d457bec671af23c472c4e21dfb7 100644 (file)
@@ -6376,6 +6376,12 @@ StmtResult TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
     return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler));
 }
 
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHLeaveStmt(SEHLeaveStmt *S) {
+  return S;
+}
+
 //===----------------------------------------------------------------------===//
 // OpenMP directive transformation
 //===----------------------------------------------------------------------===//
index c94c43578fdb06c024195d53ef658155fd72afde..a8cfe9e0006491b9c8007a38403138d3dd611f55 100644 (file)
@@ -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;
index 8655bc67ed772f1e4fcb7ebb2124d730c3b3df94..11be3fdd6de126f427f1a1be2dfc610138a33dc4 100644 (file)
@@ -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.
 //===----------------------------------------------------------------------===//
index f7d24bd3093f506795a0d5280a157ca59b4bd969..0a82e379b2cc459fddb3539d205225a1f6c275d3 100644 (file)
@@ -7,6 +7,7 @@ int SaveDiv(int numerator, int denominator, int *res) {
   int myres = 0;
   __try {
     myres = numerator / denominator;
+    __leave;
   } __except (1) {
     return 0;
   }
index 3e03842fb331f89d520f801646d67c35eb05aebb..a355de9ccf94ee9bfd5dee9c1fb422e0e7388cbc 100644 (file)
@@ -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}}
   }
index 0e5ef315031413acc961e770b53cb19bad0476e9..f008cfcd56858d9fe3811f76a1b1c12170733556 100644 (file)
@@ -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:
index f3a3a6ea6b6df9d4edbe9ce3fd0bb0397497f238..8c9cdf436c87bb40974065e0ef7691738e3eda92 100644 (file)
@@ -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: