summaryrefslogtreecommitdiff
path: root/test/Sema/warn-unreachable-ms.c
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2017-08-23 15:33:16 +0000
committerNico Weber <nicolasweber@gmx.de>2017-08-23 15:33:16 +0000
commit7ed95d923631f84fd6679c8b9e32d7d6aca24c8b (patch)
tree11e46f6eb256ba887adb4a12a65f7230cc352f7d /test/Sema/warn-unreachable-ms.c
parentd2a520ee9ed8f9f67f561bd8e074781cef7a202c (diff)
downloadclang-7ed95d923631f84fd6679c8b9e32d7d6aca24c8b.tar.gz
Implement CFG construction for __try / __except / __leave.
This makes -Wunreachable-code work for programs containing SEH (except for __finally, which is still missing for now). __try is modeled like try (but simpler since it can only have a single __except or __finally), __except is fairly similar to catch (but simpler, since it can't contain declarations). __leave is implemented similarly to break / continue. Use the existing addTryDispatchBlock infrastructure (which FindUnreachableCode() in ReachableCode.cpp uses via cfg->try_blocks_begin()) to mark things in the __except blocks as reachable. Re-use TryTerminatedBlock. This means we add EH edges from calls to the __try block, but not from all other statements. While this is incomplete, it matches LLVM's SEH codegen support. Also, in practice, BuildOpts.AddEHEdges is always false in practice from what I can tell, so we never even insert the call EH edges either. https://reviews.llvm.org/D36914 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Sema/warn-unreachable-ms.c')
-rw-r--r--test/Sema/warn-unreachable-ms.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/test/Sema/warn-unreachable-ms.c b/test/Sema/warn-unreachable-ms.c
new file mode 100644
index 0000000000..421415e932
--- /dev/null
+++ b/test/Sema/warn-unreachable-ms.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fsyntax-only -verify -fms-extensions -Wunreachable-code
+
+void f();
+
+void g1() {
+ __try {
+ f();
+ __leave;
+ f(); // expected-warning{{will never be executed}}
+ } __except(1) {
+ f();
+ }
+
+ // Completely empty.
+ __try {
+ } __except(1) {
+ }
+
+ __try {
+ f();
+ return;
+ } __except(1) { // Filter expression should not be marked as unreachable.
+ // Empty __except body.
+ }
+}
+
+void g2() {
+ __try {
+ // Nested __try.
+ __try {
+ f();
+ __leave;
+ f(); // expected-warning{{will never be executed}}
+ } __except(2) {
+ }
+ f();
+ __leave;
+ f(); // expected-warning{{will never be executed}}
+ } __except(1) {
+ f();
+ }
+}
+
+void g3() {
+ __try {
+ __try {
+ f();
+ } __except (1) {
+ __leave; // should exit outer try
+ }
+ __leave;
+ f(); // expected-warning{{never be executed}}
+ } __except (1) {
+ }
+}