]> granicus.if.org Git - clang/commitdiff
Implemented parsing and AST support for the MS __leave exception statement. Also...
authorJoao Matos <ripzonetriton@gmail.com>
Sun, 2 Sep 2012 03:45:41 +0000 (03:45 +0000)
committerJoao Matos <ripzonetriton@gmail.com>
Sun, 2 Sep 2012 03:45:41 +0000 (03:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163083 91177308-0d34-0410-b5e6-96231b3b80d8

19 files changed:
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/StmtNodes.td
include/clang/Sema/Scope.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/Stmt.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/CodeGen/CGStmt.cpp
lib/Parse/ParseStmt.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Parser/MicrosoftExtensions.c
tools/libclang/RecursiveASTVisitor.h

index ae4ff4b1f83c7f59a70e7f29d33c176ab0e19c50..46585d64cd02ae955e1582bc127e0810da377aa3 100644 (file)
@@ -2202,6 +2202,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
 })
 
 DEF_TRAVERSE_STMT(SEHTryStmt, {})
+DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
 DEF_TRAVERSE_STMT(SEHExceptStmt, {})
 DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
 
index 042c51355268c5de28e87926ef281873f3d9c2a6..e43a6f93fc4da2c882d93c1abd8053108ac2ef79 100644 (file)
@@ -1889,6 +1889,34 @@ public:
   static bool classof(SEHTryStmt *) { return true; }
 };
 
+class SEHLeaveStmt : public Stmt {
+  SourceLocation  LeaveLoc;
+
+  SEHLeaveStmt(SourceLocation LeaveLoc);
+
+  friend class ASTReader;
+  friend class ASTStmtReader;
+  explicit SEHLeaveStmt(EmptyShell E) : Stmt(SEHLeaveStmtClass, E) { }
+
+public:
+  static SEHLeaveStmt* Create(ASTContext &C,
+                              SourceLocation LeaveLoc);
+
+  SourceRange getSourceRange() const LLVM_READONLY {
+    return SourceRange(getLeaveLoc());
+  }
+
+  SourceLocation getLeaveLoc() const { return LeaveLoc; }
+
+  child_range children() { return child_range(); }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == SEHLeaveStmtClass;
+  }
+
+  static bool classof(SEHLeaveStmt *) { return true; }
+};
+
 }  // end namespace clang
 
 #endif
index e4e339aefc467af7fd47883fa19e0afdf18e168f..5608fa8755ebdcf8aa0016a44b09dae748f2a5a1 100644 (file)
@@ -740,6 +740,9 @@ def err_seh___except_filter : Error<
 
 def err_seh___finally_block : Error<
   "%0 only allowed in __finally block">;
+
+def err_seh___try_block : Error<
+  "%0 only allowed in __try block">;
   
 } // end of Parse Issue category.
 
index 06da94708f19780cd7517f5059dd6e3e4aac2370..46ae07f7a643e4cba8edb4601dbe3b9ff1f6e6f0 100644 (file)
@@ -164,6 +164,7 @@ def OpaqueValueExpr : DStmt<Expr>;
 // Microsoft Extensions.
 def CXXUuidofExpr : DStmt<Expr>; 
 def SEHTryStmt : Stmt;
+def SEHLeaveStmt : Stmt;
 def SEHExceptStmt : Stmt;
 def SEHFinallyStmt : Stmt;
 def MSDependentExistsStmt : Stmt;
index b78556e65a6ca5722b5d465a1b5698460e5b7db3..201b2e7a40117064f40fc0de51798a246dbae97c 100644 (file)
@@ -82,7 +82,10 @@ public:
     SwitchScope = 0x800,
 
     /// TryScope - This is the scope of a C++ try statement.
-    TryScope = 0x1000
+    TryScope = 0x1000,
+
+    /// SEHTryScope - This is scope of a Microsoft SEH try statement.
+    SEHTryScope = 0x2000
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
@@ -292,6 +295,9 @@ public:
   /// \brief Determine whether this scope is a C++ 'try' block.
   bool isTryScope() const { return getFlags() & Scope::TryScope; }
 
+  /// \brief Determine whether this scope is a MS SEH 'try' block.
+  bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
+
   /// containedInPrototypeScope - Return true if this or a parent scope
   /// is a FunctionPrototypeScope.
   bool containedInPrototypeScope() const;
index 5fdb09caea984a6424f4dcf637647882770ce80e..fd0cd9c397219f1ab2be11221414c18db302c464 100644 (file)
@@ -2622,6 +2622,8 @@ public:
                               Stmt *TryBlock,
                               Stmt *Handler);
 
+  StmtResult ActOnSEHLeaveStmt(SourceLocation LeaveLoc);
+
   StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
                                  Expr *FilterExpr,
                                  Stmt *Block);
index f2134134ae8d972f338fea78815c8d84b2f7e773..25303efcf2e7a6188909021b2a1f03437ffec3a5 100644 (file)
@@ -1204,6 +1204,7 @@ namespace clang {
       STMT_SEH_EXCEPT,            // SEHExceptStmt
       STMT_SEH_FINALLY,           // SEHFinallyStmt
       STMT_SEH_TRY,               // SEHTryStmt
+      STMT_SEH_LEAVE,             // SEHLeaveStmt
       
       // ARC
       EXPR_OBJC_BRIDGED_CAST,     // ObjCBridgedCastExpr
index ddd47bf5abc6bde74ad2fcc6e694bb3fedff356e..dfe61f24298f3b6f552791a541cbfc5baa3239f7 100644 (file)
@@ -1006,6 +1006,17 @@ SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
   return dyn_cast<SEHFinallyStmt>(getHandler());
 }
 
+SEHLeaveStmt::SEHLeaveStmt(SourceLocation LeaveLoc)
+  : Stmt(SEHLeaveStmtClass),
+    LeaveLoc(LeaveLoc)
+{
+}
+
+SEHLeaveStmt* SEHLeaveStmt::Create(ASTContext &C,
+                                   SourceLocation LeaveLoc) {
+  return new(C) SEHLeaveStmt(LeaveLoc);
+}
+
 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc,
                              Expr *FilterExpr,
                              Stmt *Block)
index 0cf3aaf5580c4fa0cba499e2f6263c0124fc952c..ea8878ebbb1fca48ac65c4abc6c90ba6f1d82fa7 100644 (file)
@@ -537,6 +537,11 @@ void StmtPrinter::VisitSEHTryStmt(SEHTryStmt *Node) {
   OS << "\n";
 }
 
+void StmtPrinter::VisitSEHLeaveStmt(SEHLeaveStmt *Node) {
+  Indent() << "__leave;";
+  OS << "\n";
+}
+
 void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) {
   OS << "__finally ";
   PrintRawCompoundStmt(Node->getBlock());
@@ -546,7 +551,7 @@ void StmtPrinter::PrintRawSEHFinallyStmt(SEHFinallyStmt *Node) {
 void StmtPrinter::PrintRawSEHExceptHandler(SEHExceptStmt *Node) {
   OS << "__except (";
   VisitExpr(Node->getFilterExpr());
-  OS << ")\n";
+  OS << ") ";
   PrintRawCompoundStmt(Node->getBlock());
   OS << "\n";
 }
index 5d7f9f8edee217a362693010d6e394b4980de800..1ab789e83c656539392c86329e6c2519792026f0 100644 (file)
@@ -215,6 +215,10 @@ void StmtProfiler::VisitSEHExceptStmt(const SEHExceptStmt *S) {
   VisitStmt(S);
 }
 
+void StmtProfiler::VisitSEHLeaveStmt(const SEHLeaveStmt *S) {
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
   VisitStmt(S);
 }
index 465fb968b7bbdb74c2c7411df3c83395f6ab635d..c535ec41a770eb9c7327b0fcd9b3cc9ac1325dc2 100644 (file)
@@ -163,6 +163,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
   case Stmt::CXXForRangeStmtClass:
     EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S));
   case Stmt::SEHTryStmtClass:
+  case Stmt::SEHLeaveStmtClass:
     // FIXME Not yet implemented
     break;
   }
index f58f90d56c5d2c102ca0bf65be712dd952a329fb..f46ccb255a79df41c21b60597acf418b25c8e1b9 100644 (file)
@@ -183,6 +183,19 @@ Retry:
 
     return ParseExprStatement();
   }
+  
+  case tok::kw___leave: {
+    Token LeaveTok = Tok;
+    ConsumeToken();
+    if (getCurScope()->isSEHTryScope()) {
+      Res = Actions.ActOnSEHLeaveStmt(LeaveTok.getLocation());
+    } else {
+      Diag(LeaveTok, diag::err_seh___try_block)
+         << LeaveTok.getIdentifierInfo()->getName();
+      Res = StmtError();
+    }
+    break;
+  }
 
   case tok::kw_case:                // C99 6.8.1: labeled-statement
     return ParseCaseStatement();
@@ -322,7 +335,9 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
   if(Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok,diag::err_expected_lbrace));
 
-  StmtResult TryBlock(ParseCompoundStatement());
+  // Use the SEHTryScope to handle __leave as a statement.
+  unsigned ScopeFlags = Scope::DeclScope | Scope::SEHTryScope;
+  StmtResult TryBlock(ParseCompoundStatement(false /*isStmtExpr*/, ScopeFlags));
   if(TryBlock.isInvalid())
     return TryBlock;
 
index 76410e20aca5c3145c6b075cfda5109ceb176679..e9866ffb3bc12406d8d07949944f6a9e295952ba 100644 (file)
@@ -2745,6 +2745,12 @@ Sema::ActOnSEHTryBlock(bool IsCXXTry,
   return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler));
 }
 
+StmtResult
+Sema::ActOnSEHLeaveStmt(SourceLocation LeaveLoc)
+{
+  return Owned(SEHLeaveStmt::Create(Context, LeaveLoc));
+}
+
 StmtResult
 Sema::ActOnSEHExceptBlock(SourceLocation Loc,
                           Expr *FilterExpr,
index 19636f41438f1b0132c74585bef5f3801c68f967..10eb52a89073fd3662d6ad107593650b8b8f2a1c 100644 (file)
@@ -1361,6 +1361,10 @@ public:
     return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler);
   }
 
+  StmtResult RebuildSEHLeaveStmt(SourceLocation LeaveLoc) {
+    return getSema().ActOnSEHLeaveStmt(LeaveLoc);
+  }
+
   StmtResult RebuildSEHExceptStmt(SourceLocation Loc,
                                   Expr *FilterExpr,
                                   Stmt *Block) {
@@ -5999,6 +6003,12 @@ TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) {
                                         Handler.take());
 }
 
+template<typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformSEHLeaveStmt(SEHLeaveStmt *S) {
+  return getDerived().RebuildSEHLeaveStmt(S->getLeaveLoc());
+}
+
 template<typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) {
index 6ca450b9fb48582c87fa88050768841644ec213f..3252c7db5878a477c2abbc9c9b525ace603e89da 100644 (file)
@@ -1516,6 +1516,11 @@ void ASTStmtReader::VisitSEHTryStmt(SEHTryStmt *S) {
   S->Children[SEHTryStmt::HANDLER] = Reader.ReadSubStmt();
 }
 
+void ASTStmtReader::VisitSEHLeaveStmt(SEHLeaveStmt *S) {
+  VisitStmt(S);
+  S->LeaveLoc = ReadSourceLocation(Record, Idx);
+}
+
 //===----------------------------------------------------------------------===//
 // CUDA Expressions and Statements
 //===----------------------------------------------------------------------===//
@@ -1986,6 +1991,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
     case STMT_SEH_TRY:
       S = new (Context) SEHTryStmt(Empty);
       break;
+    case STMT_SEH_LEAVE:
+      S = new (Context) SEHLeaveStmt(Empty);
+      break;
     case STMT_CXX_CATCH:
       S = new (Context) CXXCatchStmt(Empty);
       break;
index 5fa08d256cdcf612993e129b646b3d9f19beddbb..9d626d1b59afa0453a3baea479d4e1fb1d63ac67 100644 (file)
@@ -1554,6 +1554,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;
+}
+
 //===----------------------------------------------------------------------===//
 // ASTWriter Implementation
 //===----------------------------------------------------------------------===//
index 4225c67dc704a791d17f7b2150b97caf6d6a187f..5c4492a48c2b8e0e7723e623a8e6195d2ad99942 100644 (file)
@@ -527,6 +527,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::PackExpansionExprClass:
     case Stmt::SubstNonTypeTemplateParmPackExprClass:
     case Stmt::SEHTryStmtClass:
+    case Stmt::SEHLeaveStmtClass:
     case Stmt::SEHExceptStmtClass:
     case Stmt::LambdaExprClass:
     case Stmt::SEHFinallyStmtClass: {
index 7703999d67ce6543398d8a7edb3f3fdb7f996377..57eee04c234f4d48606490de3645c516e7b2bf1b 100644 (file)
@@ -102,3 +102,9 @@ __declspec() void quux( void ) {
   struct S7 s;
   int i = s.t; /* expected-warning {{'t' is deprecated}} */
 }
+
+void SEH() {
+  __try { __leave; } __except (0) {}
+  __try { } __except (0) { __leave; } // expected-error {{__leave only allowed in __try block}}
+  __try { } __finally { __leave; } // expected-error {{__leave only allowed in __try block}}
+}
\ No newline at end of file
index ab96f36205b9606ab851ed8afb2cf67063291fe4..6642d81d61aff43a691e6ea7de05be22ba6ca29b 100644 (file)
@@ -2122,6 +2122,7 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
 })
 
 DEF_TRAVERSE_STMT(SEHTryStmt, {})
+DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
 DEF_TRAVERSE_STMT(SEHExceptStmt, {})
 DEF_TRAVERSE_STMT(SEHFinallyStmt,{})