summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2014-07-06 22:53:19 +0000
committerNico Weber <nicolasweber@gmx.de>2014-07-06 22:53:19 +0000
commiteb61d4d7c2fdc089c5625aa1128c844edd51285f (patch)
tree6dd096b3b22dd563046e02f1301e524b8545d3a1
parentc7d0596429b6051c212a5ae1864c8635ab8ae906 (diff)
downloadbcm5719-llvm-eb61d4d7c2fdc089c5625aa1128c844edd51285f.tar.gz
bcm5719-llvm-eb61d4d7c2fdc089c5625aa1128c844edd51285f.zip
Sema: Check that __leave is contained in a __try block.
Give scope a SEHTryScope bit, set that in ParseSEHTry(), and let Sema walk the scope chain to find the SEHTry parent on __leave statements. (They are rare enough that it seems better to do the walk instead of giving Scope a SEHTryParent pointer -- this is similar to AtCatchScope.) llvm-svn: 212422
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Sema/Scope.h6
-rw-r--r--clang/lib/Parse/ParseStmt.cpp3
-rw-r--r--clang/lib/Sema/Scope.cpp3
-rw-r--r--clang/lib/Sema/SemaStmt.cpp6
-rw-r--r--clang/test/Sema/__try.c13
-rw-r--r--clang/test/SemaCXX/__try.cpp3
7 files changed, 25 insertions, 11 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5622c7050ee..1b8e01ebc22 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5155,6 +5155,8 @@ 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<
"cannot call operator __uuidof on a type with no GUID">;
def err_uuidof_with_multiple_guids : Error<
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index 5d2eab98b63..27067a11198 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -114,6 +114,9 @@ public:
/// This scope corresponds to an enum.
EnumScope = 0x40000,
+
+ /// This scope corresponds to a SEH try.
+ SEHTryScope = 0x80000,
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -398,6 +401,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 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;
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index e81945437bf..d29da837c09 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -427,7 +427,8 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) {
if(Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
- StmtResult TryBlock(ParseCompoundStatement());
+ StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
+ Scope::DeclScope | Scope::SEHTryScope));
if(TryBlock.isInvalid())
return TryBlock;
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp
index c49133d4727..6c797788238 100644
--- a/clang/lib/Sema/Scope.cpp
+++ b/clang/lib/Sema/Scope.cpp
@@ -182,6 +182,9 @@ void Scope::dumpImpl(raw_ostream &OS) const {
} else if (Flags & FnTryCatchScope) {
OS << "FnTryCatchScope";
Flags &= ~FnTryCatchScope;
+ } else if (Flags & SEHTryScope) {
+ OS << "SEHTryScope";
+ Flags &= ~SEHTryScope;
} else if (Flags & OpenMPDirectiveScope) {
OS << "OpenMPDirectiveScope";
Flags &= ~OpenMPDirectiveScope;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 6090d6d14d4..0b778918543 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3279,6 +3279,12 @@ Sema::ActOnSEHFinallyBlock(SourceLocation Loc,
StmtResult
Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) {
+ Scope *SEHTryParent = CurScope;
+ while (SEHTryParent && !SEHTryParent->isSEHTryScope())
+ SEHTryParent = SEHTryParent->getParent();
+ if (!SEHTryParent)
+ return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));
+
return StmtError(Diag(Loc, diag::err_ms___leave_unimplemented));
}
diff --git a/clang/test/Sema/__try.c b/clang/test/Sema/__try.c
index 9c9cec21230..3e03842fb33 100644
--- a/clang/test/Sema/__try.c
+++ b/clang/test/Sema/__try.c
@@ -172,26 +172,23 @@ void TEST() {
}
void test___leave() {
- // FIXME: should say "__leave stmt not in __try block":
- __leave; // expected-error{{not implemented yet}}
+ __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}}
} __except(1) {
- // FIXME: should say "__leave stmt not in __try block":
- __leave; // expected-error{{not implemented yet}}
+ __leave; // expected-error{{'__leave' statement not in __try block}}
}
__try {
// FIXME: should be fine
__leave; // expected-error{{not implemented yet}}
} __finally {
- // FIXME: should say "__leave stmt not in __try block":
- __leave; // expected-error{{not implemented yet}}
+ __leave; // expected-error{{'__leave' statement not in __try block}}
}
- // FIXME: should say "__leave stmt not in __try block":
- __leave; // expected-error{{not implemented yet}}
+ __leave; // expected-error{{'__leave' statement not in __try block}}
}
diff --git a/clang/test/SemaCXX/__try.cpp b/clang/test/SemaCXX/__try.cpp
index ac79ee74720..28a37014887 100644
--- a/clang/test/SemaCXX/__try.cpp
+++ b/clang/test/SemaCXX/__try.cpp
@@ -83,8 +83,7 @@ void test___leave() {
// Clang accepts try with __finally. MSVC doesn't. (Maybe a Borland thing?)
// __leave in mixed blocks isn't supported.
try {
- // FIXME: should say "__leave stmt not in __try block":
- __leave; // expected-error{{not implemented yet}}
+ __leave; // expected-error{{'__leave' statement not in __try block}}
} __finally {
}
}
OpenPOWER on IntegriCloud