From dd4fdbef5ad9954c5af124e970dcce1ba58e4b80 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 2 Feb 2015 22:15:31 +0000 Subject: [PATCH] SEH: Diagnose use of C++ EH and SEH in the same function This check does not apply when Borland extensions are enabled, as they have a checked in test case indicating that mixed usage of SEH and C++ is supported. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@227876 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++ include/clang/Sema/ScopeInfo.h | 16 +++++++++++++ lib/Sema/ScopeInfo.cpp | 2 ++ lib/Sema/SemaStmt.cpp | 28 +++++++++++++++------- test/SemaCXX/exceptions-seh.cpp | 24 ++++++++++++++++++- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index bb448616ab..5669415c26 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5447,6 +5447,10 @@ def err_exceptions_disabled : Error< "cannot use '%0' with exceptions disabled">; def err_objc_exceptions_disabled : Error< "cannot use '%0' with Objective-C exceptions disabled">; +def err_mixing_cxx_try_seh_try : Error< + "cannot use C++ 'try' in the same function as SEH '__try'">; +def note_conflicting_try_here : Note< + "conflicting %0 here">; def warn_non_virtual_dtor : Warning< "%0 has virtual functions but non-virtual destructor">, InGroup, DefaultIgnore; diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index d63b734a8d..ec8e56be87 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -124,6 +124,12 @@ public: /// false if there is an invocation of an initializer on 'self'. bool ObjCWarnForNoInitDelegation; + /// First C++ 'try' statement in the current function. + SourceLocation FirstCXXTryLoc; + + /// First SEH '__try' statement in the current function. + SourceLocation FirstSEHTryLoc; + /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -321,6 +327,16 @@ public: HasDroppedStmt = true; } + void setHasCXXTry(SourceLocation TryLoc) { + setHasBranchProtectedScope(); + FirstCXXTryLoc = TryLoc; + } + + void setHasSEHTry(SourceLocation TryLoc) { + setHasBranchProtectedScope(); + FirstSEHTryLoc = TryLoc; + } + bool NeedsScopeChecking() const { return !HasDroppedStmt && (HasIndirectGoto || diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp index 63ef3b2355..f80eadf18d 100644 --- a/lib/Sema/ScopeInfo.cpp +++ b/lib/Sema/ScopeInfo.cpp @@ -33,6 +33,8 @@ void FunctionScopeInfo::Clear() { ObjCWarnForNoDesignatedInitChain = false; ObjCIsSecondaryInit = false; ObjCWarnForNoInitDelegation = false; + FirstCXXTryLoc = SourceLocation(); + FirstSEHTryLoc = SourceLocation(); SwitchStack.clear(); Returns.clear(); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 22ed930820..d17cf22701 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3303,6 +3303,13 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; + // C++ try is incompatible with SEH __try. + if (!getLangOpts().Borland && getCurFunction()->FirstSEHTryLoc.isValid()) { + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); + Diag(getCurFunction()->FirstSEHTryLoc, diag::note_conflicting_try_here) + << "'__try'"; + } + const unsigned NumHandlers = Handlers.size(); assert(NumHandlers > 0 && "The parser shouldn't call this if there are no handlers."); @@ -3345,7 +3352,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, } } - getCurFunction()->setHasBranchProtectedScope(); + getCurFunction()->setHasCXXTry(TryLoc); // FIXME: We should detect handlers that cannot catch anything because an // earlier handler catches a superclass. Need to find a method that is not @@ -3356,16 +3363,21 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers); } -StmtResult -Sema::ActOnSEHTryBlock(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, - Stmt *Handler) { +StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, + Stmt *TryBlock, Stmt *Handler) { assert(TryBlock && Handler); - getCurFunction()->setHasBranchProtectedScope(); + // SEH __try is incompatible with C++ try. Borland appears to support this, + // however. + if (!getLangOpts().Borland && getCurFunction()->FirstCXXTryLoc.isValid()) { + Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); + Diag(getCurFunction()->FirstCXXTryLoc, diag::note_conflicting_try_here) + << "'try'"; + } + + getCurFunction()->setHasSEHTry(TryLoc); - return SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler); + return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler); } StmtResult diff --git a/test/SemaCXX/exceptions-seh.cpp b/test/SemaCXX/exceptions-seh.cpp index 8cc4b4fe3d..dd00c11590 100644 --- a/test/SemaCXX/exceptions-seh.cpp +++ b/test/SemaCXX/exceptions-seh.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fsyntax-only -fexceptions -fcxx-exceptions -verify %s // Basic usage should work. int safe_div(int n, int d) { @@ -46,3 +46,25 @@ void inject_builtins() { func_template(); func_template(); } + +void use_seh_after_cxx() { + try { // expected-note {{conflicting 'try' here}} + might_crash(); + } catch (int) { + } + __try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}} + might_crash(); + } __except(1) { + } +} + +void use_cxx_after_seh() { + __try { // expected-note {{conflicting '__try' here}} + might_crash(); + } __except(1) { + } + try { // expected-error {{cannot use C++ 'try' in the same function as SEH '__try'}} + might_crash(); + } catch (int) { + } +} -- 2.40.0