Parsing/AST support for Structured Exception Handling
Patch authored by Sohail Somani.
Provide parsing and AST support for Windows structured exception handling.
llvm-svn: 130366
diff --git a/clang/test/AST/__try.c b/clang/test/AST/__try.c
new file mode 100644
index 0000000..6170adb
--- /dev/null
+++ b/clang/test/AST/__try.c
@@ -0,0 +1,28 @@
+// RUN: %ast_test -fborland-extensions %s
+
+#define JOIN2(x,y) x ## y
+#define JOIN(x,y) JOIN2(x,y)
+#define TEST2(name) JOIN(name,__LINE__)
+#define TEST TEST2(test)
+typedef int DWORD;
+
+DWORD FilterExpression();
+
+void TEST() {
+ __try // expected-stmt-class-name{{SEHTryStmt}}
+ { // expected-stmt-class-name{{CompoundStmt}}
+ }
+ __except ( FilterExpression() ) // expected-stmt-class-name{{SEHExceptStmt}} expected-stmt-class-name{{CallExpr}} \
+ // expected-expr-type{{DWORD}}
+ { // expected-stmt-class-name{{CompoundStmt}}
+ }
+}
+
+void TEST() {
+ __try // expected-stmt-class-name{{SEHTryStmt}}
+ { // expected-stmt-class-name{{CompoundStmt}}
+ }
+ __finally // expected-stmt-class-name{{SEHFinallyStmt}}
+ { // expected-stmt-class-name{{CompoundStmt}}
+ }
+}
diff --git a/clang/test/Sema/__try.c b/clang/test/Sema/__try.c
new file mode 100644
index 0000000..5490aea
--- /dev/null
+++ b/clang/test/Sema/__try.c
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -fborland-extensions -fsyntax-only -verify %s
+
+#define JOIN2(x,y) x ## y
+#define JOIN(x,y) JOIN2(x,y)
+#define TEST2(name) JOIN(name,__LINE__)
+#define TEST TEST2(test)
+typedef int DWORD;
+
+#pragma sysheader begin
+
+struct EXCEPTION_INFO{};
+
+int __exception_code();
+struct EXCEPTION_INFO* __exception_info();
+void __abnormal_termination();
+
+#define GetExceptionCode __exception_code
+#define GetExceptionInformation __exception_info
+#define AbnormalTermination __abnormal_termination
+
+#pragma sysheader end
+
+DWORD FilterExpression(int);
+DWORD FilterExceptionInformation(struct EXCEPTION_INFO*);
+
+const char * NotFilterExpression();
+
+void TEST() {
+ __try {
+ __try {
+ __try {
+ }
+ __finally{
+ }
+ }
+ __finally{
+ }
+ }
+ __finally{
+ }
+}
+
+void TEST() {
+ __try {
+
+ }
+} // expected-error{{expected '__except' or '__finally' block}}
+
+void TEST() {
+ __except ( FilterExpression() ) { // expected-error{{}}
+
+ }
+}
+
+void TEST() {
+ __finally { } // expected-error{{}}
+}
+
+void TEST() {
+ __try{
+ int try_scope = 0;
+ } // TODO: expected expression is an extra error
+ __except( try_scope ? 1 : -1 ) // expected-error{{undeclared identifier 'try_scope'}} expected-error{{expected expression}}
+ {}
+}
+
+void TEST() {
+ __try {
+
+ }
+ // TODO: Why are there two errors?
+ __except( ) { // expected-error{{expected expression}} expected-error{{expected expression}}
+ }
+}
+
+void TEST() {
+ __try {
+
+ }
+ __except ( FilterExpression(GetExceptionCode()) ) {
+
+ }
+
+ __try {
+
+ }
+ __except( FilterExpression(__exception_code()) ) {
+
+ }
+
+ __try {
+
+ }
+ __except( FilterExceptionInformation(__exception_info()) ) {
+
+ }
+
+ __try {
+
+ }
+ __except(FilterExceptionInformation( GetExceptionInformation() ) ) {
+
+ }
+}
+
+void TEST() {
+ __try {
+
+ }
+ __except ( NotFilterExpression() ) { // expected-error{{filter expression type should be an integral value not 'const char *'}}
+
+ }
+}
+
+void TEST() {
+ int function_scope = 0;
+ __try {
+ int try_scope = 0;
+ }
+ __except ( FilterExpression(GetExceptionCode()) ) {
+ (void)function_scope;
+ (void)try_scope; // expected-error{{undeclared identifier}}
+ }
+}
+
+void TEST() {
+ int function_scope = 0;
+ __try {
+ int try_scope = 0;
+ }
+ __finally {
+ (void)function_scope;
+ (void)try_scope; // expected-error{{undeclared identifier}}
+ }
+}
+
+void TEST() {
+ int function_scope = 0;
+ __try {
+
+ }
+ __except( function_scope ? 1 : -1 ) {}
+}
+
+void TEST() {
+ __try {
+ (void)AbnormalTermination; // expected-error{{only allowed in __finally block}}
+ (void)__abnormal_termination; // expected-error{{only allowed in __finally block}}
+ }
+ __except( 1 ) {
+ (void)AbnormalTermination; // expected-error{{only allowed in __finally block}}
+ (void)__abnormal_termination; // expected-error{{only allowed in __finally block}}
+ }
+
+ __try {
+ }
+ __finally {
+ AbnormalTermination();
+ __abnormal_termination();
+ }
+}
+
+void TEST() {
+ (void)__exception_code; // expected-error{{only allowed in __except block}}
+ (void)__exception_info; // expected-error{{only allowed in __except filter expression}}
+ (void)__abnormal_termination; // expected-error{{only allowed in __finally block}}
+
+ (void)GetExceptionCode(); // expected-error{{only allowed in __except block}}
+ (void)GetExceptionInformation(); // expected-error{{only allowed in __except filter expression}}
+ (void)AbnormalTermination(); // expected-error{{only allowed in __finally block}}
+}
diff --git a/clang/test/SemaCXX/__try.cpp b/clang/test/SemaCXX/__try.cpp
new file mode 100644
index 0000000..cb5d38a
--- /dev/null
+++ b/clang/test/SemaCXX/__try.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fborland-extensions -fcxx-exceptions %s
+
+// This test is from http://docwiki.embarcadero.com/RADStudio/en/Try
+
+int puts(const char *);
+
+template<typename T>
+int printf(const char *, T);
+
+const char * strdup(const char *);
+
+void free(const void *);
+
+#define EXCEPTION_EXECUTE_HANDLER 1
+
+class Exception
+{
+public:
+ Exception(const char* s = "Unknown"){what = strdup(s); }
+ Exception(const Exception& e ){what = strdup(e.what); }
+ ~Exception() {free(what); }
+ const char* msg() const {return what; }
+private:
+ const char* what;
+};
+
+int main()
+{
+ float e, f, g;
+ try
+ {
+ try
+ {
+ f = 1.0;
+ g = 0.0;
+ try
+ {
+ puts("Another exception:");
+
+ e = f / g;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ puts("Caught a C-based exception.");
+ throw(Exception("Hardware error: Divide by 0"));
+ }
+ }
+ catch(const Exception& e)
+ {
+ printf("Caught C++ Exception: %s :\n", e.msg());
+ }
+ }
+ __finally
+ {
+ puts("C++ allows __finally too!");
+ }
+ return e;
+}