Parsing/AST support for Structured Exception Handling

Patch authored by Sohail Somani.

Provide parsing and AST support for Windows structured exception handling.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130366 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Sema/__try.c b/test/Sema/__try.c
new file mode 100644
index 0000000..5490aea
--- /dev/null
+++ b/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}}
+}