summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2014-07-07 00:12:30 +0000
committerNico Weber <nicolasweber@gmx.de>2014-07-07 00:12:30 +0000
commit9b982078e9076b9b36586ae8b6bf21a3868f1b93 (patch)
treef5c493e854ded43d6e037219e2ab42d549c7b689
parent784a5a41e79169714bd640df2c3c062b6f11dc20 (diff)
downloadbcm5719-llvm-9b982078e9076b9b36586ae8b6bf21a3868f1b93.tar.gz
bcm5719-llvm-9b982078e9076b9b36586ae8b6bf21a3868f1b93.zip
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
-rw-r--r--clang/include/clang-c/Index.h6
-rw-r--r--clang/include/clang/AST/DataRecursiveASTVisitor.h1
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h1
-rw-r--r--clang/include/clang/AST/Stmt.h25
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Basic/StmtNodes.td1
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--clang/lib/AST/StmtPrinter.cpp5
-rw-r--r--clang/lib/AST/StmtProfile.cpp4
-rw-r--r--clang/lib/CodeGen/CGException.cpp4
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h1
-rw-r--r--clang/lib/Sema/SemaStmt.cpp2
-rw-r--r--clang/lib/Sema/TreeTransform.h6
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp8
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp6
-rw-r--r--clang/test/CodeGen/exceptions-seh.c1
-rw-r--r--clang/test/Sema/__try.c11
-rw-r--r--clang/tools/libclang/CIndex.cpp2
-rw-r--r--clang/tools/libclang/CXCursor.cpp4
20 files changed, 83 insertions, 11 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 561bed92315..4819293c734 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 f35d4f2f857..1556babb7bd 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 cde5adedbd0..31580ca9af5 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 99e84f8267d..790c8e3e663 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 1b8e01ebc22..321f24d735d 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 <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<
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 17a56adcf6e..aec07ec764a 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -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.
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index fe91b15d99c..331fb1f76a6 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 28ce174207d..1d96c49c7bb 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 f562ed6aa76..f666be7008f 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 ffcab074caa..1bbda5cbf09 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 9cc23e2632a..6fed5d3a9d4 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<SEHTryStmt>(*S));
break;
+ case Stmt::SEHLeaveStmtClass:
+ EmitSEHLeaveStmt(cast<SEHLeaveStmt>(*S));
+ break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 3446216f224..055e9356842 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<const Attr *> &Attrs = None);
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 0b778918543..dc5619db9a4 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 c48c4d04f5e..64c717f570a 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index c94c43578fd..a8cfe9e0006 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 8655bc67ed7..11be3fdd6de 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 f7d24bd3093..0a82e379b2c 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 3e03842fb33..a355de9ccf9 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 0e5ef315031..f008cfcd568 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 f3a3a6ea6b6..8c9cdf436c8 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:
OpenPOWER on IntegriCloud