summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp12
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp14
-rw-r--r--clang/lib/CodeGen/CGException.cpp265
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp6
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h30
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp3
7 files changed, 195 insertions, 137 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index f890719c209..6e55655d85b 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -166,6 +166,8 @@ public:
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) override;
@@ -3967,6 +3969,16 @@ void ItaniumMangleContextImpl::mangleSEHFilterExpression(
Mangler.getStream() << EnclosingDecl->getName();
}
+void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "__fin_";
+ if (shouldMangleDeclName(EnclosingDecl))
+ Mangler.mangle(EnclosingDecl);
+ else
+ Mangler.getStream() << EnclosingDecl->getName();
+}
+
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,
raw_ostream &Out) {
// <special-name> ::= TH <object name>
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index bf9d7a0118c..269fb1c2553 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -94,6 +94,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
+ llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -151,6 +152,8 @@ public:
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
+ void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
raw_ostream &Out) override;
@@ -2469,6 +2472,17 @@ void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
Mangler.mangleName(EnclosingDecl);
}
+void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
+ const NamedDecl *EnclosingDecl, raw_ostream &Out) {
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ // The function body is in the same comdat as the function with the handler,
+ // so the numbering here doesn't have to be the same across TUs.
+ //
+ // <mangled-name> ::= ?fin$ <filter-number> @0
+ Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
+ Mangler.mangleName(EnclosingDecl);
+}
+
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
// This is just a made up unique string for the purposes of tbaa. undname
// does *not* know how to demangle it.
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index cc16053ac7f..ff12a9ab829 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -23,6 +23,7 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -408,13 +409,6 @@ llvm::Value *CodeGenFunction::getSelectorFromSlot() {
return Builder.CreateLoad(getEHSelectorSlot(), "sel");
}
-llvm::Value *CodeGenFunction::getAbnormalTerminationSlot() {
- if (!AbnormalTerminationSlot)
- AbnormalTerminationSlot =
- CreateTempAlloca(Int8Ty, "abnormal.termination.slot");
- return AbnormalTerminationSlot;
-}
-
void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
bool KeepInsertionPoint) {
if (const Expr *SubExpr = E->getSubExpr()) {
@@ -1287,8 +1281,7 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
return;
}
- SEHFinallyInfo FI;
- EnterSEHTryStmt(S, FI);
+ EnterSEHTryStmt(S);
{
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@@ -1301,42 +1294,36 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
else
delete TryExit.getBlock();
}
- ExitSEHTryStmt(S, FI);
+ ExitSEHTryStmt(S);
}
namespace {
-struct PerformSEHFinally : EHScopeStack::Cleanup {
- CodeGenFunction::SEHFinallyInfo *FI;
- PerformSEHFinally(CodeGenFunction::SEHFinallyInfo *FI) : FI(FI) {}
+struct PerformSEHFinally : EHScopeStack::Cleanup {
+ llvm::Function *OutlinedFinally;
+ PerformSEHFinally(llvm::Function *OutlinedFinally)
+ : OutlinedFinally(OutlinedFinally) {}
void Emit(CodeGenFunction &CGF, Flags F) override {
- // Cleanups are emitted at most twice: once for normal control flow and once
- // for exception control flow. Branch into the finally block, and remember
- // the continuation block so we can branch out later.
- if (!FI->FinallyBB) {
- FI->FinallyBB = CGF.createBasicBlock("__finally");
- FI->FinallyBB->insertInto(CGF.CurFn);
- FI->FinallyBB->moveAfter(CGF.Builder.GetInsertBlock());
- }
-
- // Set the termination status and branch in.
- CGF.Builder.CreateStore(
- llvm::ConstantInt::get(CGF.Int8Ty, F.isForEHCleanup()),
- CGF.getAbnormalTerminationSlot());
- CGF.Builder.CreateBr(FI->FinallyBB);
-
- // Create a continuation block for normal or exceptional control.
- if (F.isForEHCleanup()) {
- assert(!FI->ResumeBB && "double emission for EH");
- FI->ResumeBB = CGF.createBasicBlock("__finally.resume");
- CGF.EmitBlock(FI->ResumeBB);
- } else {
- assert(F.isForNormalCleanup() && !FI->ContBB && "double normal emission");
- FI->ContBB = CGF.createBasicBlock("__finally.cont");
- CGF.EmitBlock(FI->ContBB);
- // Try to keep source order.
- FI->ContBB->moveAfter(FI->FinallyBB);
- }
+ ASTContext &Context = CGF.getContext();
+ QualType ArgTys[2] = {Context.BoolTy, Context.VoidPtrTy};
+ FunctionProtoType::ExtProtoInfo EPI;
+ const auto *FTP = cast<FunctionType>(
+ Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
+
+ CallArgList Args;
+ llvm::Value *IsForEH =
+ llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
+ Args.add(RValue::get(IsForEH), ArgTys[0]);
+
+ CodeGenModule &CGM = CGF.CGM;
+ llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
+ llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
+ llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
+ Args.add(RValue::get(FP), ArgTys[1]);
+
+ const CGFunctionInfo &FnInfo =
+ CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
+ CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
}
};
}
@@ -1354,7 +1341,8 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
// See if this is a capture, then recurse.
ConstStmtVisitor<CaptureFinder>::Visit(S);
for (const Stmt *Child : S->children())
- Visit(Child);
+ if (Child)
+ Visit(Child);
}
void VisitDeclRefExpr(const DeclRefExpr *E) {
@@ -1403,12 +1391,16 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
CGM.ErrorUnsupported(VD, "VLA captured by SEH");
continue;
}
-
assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
"captured non-local variable");
- llvm::Value *ParentVar = ParentCGF.LocalDeclMap[VD];
- assert(ParentVar && "capture was not a local decl");
+ // If this decl hasn't been declared yet, it will be declared in the
+ // OutlinedStmt.
+ auto I = ParentCGF.LocalDeclMap.find(VD);
+ if (I == ParentCGF.LocalDeclMap.end())
+ continue;
+ llvm::Value *ParentVar = I->second;
+
llvm::CallInst *RecoverCall = nullptr;
CGBuilderTy Builder(AllocaInsertPt);
if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
@@ -1445,47 +1437,24 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
}
}
-/// Create a stub filter function that will ultimately hold the code of the
-/// filter expression. The EH preparation passes in LLVM will outline the code
-/// from the main function body into this stub.
-llvm::Function *
-CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
- const SEHExceptStmt &Except) {
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+/// Arrange a function prototype that can be called by Windows exception
+/// handling personalities. On Win64, the prototype looks like:
+/// RetTy func(void *EHPtrs, void *ParentFP);
+void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
+ StringRef Name, QualType RetTy,
+ FunctionArgList &Args,
+ const Stmt *OutlinedStmt) {
llvm::Function *ParentFn = ParentCGF.CurFn;
-
- Expr *FilterExpr = Except.getFilterExpr();
-
- // Get the mangled function name.
- SmallString<128> Name;
- {
- llvm::raw_svector_ostream OS(Name);
- const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
- assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
- CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
- }
-
- // Arrange a function with the declaration:
- // int filt(EXCEPTION_POINTERS *exception_pointers, void *frame_pointer)
- QualType RetTy = getContext().IntTy;
- FunctionArgList Args;
- SEHPointersDecl = ImplicitParamDecl::Create(
- getContext(), nullptr, FilterExpr->getLocStart(),
- &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
- Args.push_back(SEHPointersDecl);
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, FilterExpr->getLocStart(),
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
+
llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
- llvm::Function *Fn = llvm::Function::Create(FnTy, ParentFn->getLinkage(),
- Name.str(), &CGM.getModule());
+ llvm::Function *Fn = llvm::Function::Create(
+ FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
// The filter is either in the same comdat as the function, or it's internal.
if (llvm::Comdat *C = ParentFn->getComdat()) {
Fn->setComdat(C);
} else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
- // FIXME: Unreachable with Rafael's changes?
llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
ParentFn->setComdat(C);
Fn->setComdat(C);
@@ -1493,14 +1462,55 @@ CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
}
+ IsOutlinedSEHHelper = true;
+
StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
- FilterExpr->getLocStart(), FilterExpr->getLocStart());
+ OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
- EmitSEHExceptionCodeSave();
+ CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
auto AI = Fn->arg_begin();
++AI;
- EmitCapturedLocals(ParentCGF, FilterExpr, &*AI);
+ EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
+}
+
+/// Create a stub filter function that will ultimately hold the code of the
+/// filter expression. The EH preparation passes in LLVM will outline the code
+/// from the main function body into this stub.
+llvm::Function *
+CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
+ const SEHExceptStmt &Except) {
+ const Expr *FilterExpr = Except.getFilterExpr();
+ SourceLocation StartLoc = FilterExpr->getLocStart();
+
+ SEHPointersDecl = ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
+ FunctionArgList Args;
+ Args.push_back(SEHPointersDecl);
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+
+ // Get the mangled function name.
+ SmallString<128> Name;
+ {
+ llvm::raw_svector_ostream OS(Name);
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+ const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+ assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+ CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
+ }
+
+ startOutlinedSEHHelper(ParentCGF, Name, getContext().IntTy, Args, FilterExpr);
+
+ // Mark finally block calls as nounwind and noinline to make LLVM's job a
+ // little easier.
+ // FIXME: Remove these restrictions in the future.
+ CurFn->addFnAttr(llvm::Attribute::NoUnwind);
+ CurFn->addFnAttr(llvm::Attribute::NoInline);
+
+ EmitSEHExceptionCodeSave();
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
@@ -1510,7 +1520,42 @@ CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
FinishFunction(FilterExpr->getLocEnd());
- return Fn;
+ return CurFn;
+}
+
+llvm::Function *
+CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally) {
+ const Stmt *FinallyBlock = Finally.getBlock();
+ SourceLocation StartLoc = FinallyBlock->getLocStart();
+
+ FunctionArgList Args;
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("abnormal_termination"), getContext().BoolTy));
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, StartLoc,
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+
+ // Get the mangled function name.
+ SmallString<128> Name;
+ {
+ llvm::raw_svector_ostream OS(Name);
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+ const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+ assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+ CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
+ }
+
+ startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
+ FinallyBlock);
+
+ // Emit the original filter expression, convert to i32, and return.
+ EmitStmt(FinallyBlock);
+
+ FinishFunction(FinallyBlock->getLocEnd());
+
+ return CurFn;
}
void CodeGenFunction::EmitSEHExceptionCodeSave() {
@@ -1554,21 +1599,24 @@ llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
- // Load from the abnormal termination slot. It will be uninitialized outside
- // of __finally blocks, which we should warn or error on.
- llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot());
- return Builder.CreateZExt(IsEH, Int32Ty);
+ // Abnormal termination is just the first parameter to the outlined finally
+ // helper.
+ auto AI = CurFn->arg_begin();
+ return Builder.CreateZExt(&*AI, Int32Ty);
}
-void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
- if (S.getFinallyHandler()) {
+void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
+ CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
+ if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
// Push a cleanup for __finally blocks.
- EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, &FI);
+ llvm::Function *FinallyFunc =
+ HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
return;
}
// Otherwise, we must have an __except block.
- SEHExceptStmt *Except = S.getExceptHandler();
+ const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except);
EHCatchScope *CatchScope = EHStack.pushCatch(1);
@@ -1583,40 +1631,17 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
// In general, we have to emit an outlined filter function. Use the function
// in place of the RTTI typeinfo global that C++ EH uses.
- CodeGenFunction FilterCGF(CGM, /*suppressNewContext=*/true);
llvm::Function *FilterFunc =
- FilterCGF.GenerateSEHFilterFunction(*this, *Except);
+ HelperCGF.GenerateSEHFilterFunction(*this, *Except);
llvm::Constant *OpaqueFunc =
llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except"));
}
-void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
+void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
// Just pop the cleanup if it's a __finally block.
- if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
+ if (S.getFinallyHandler()) {
PopCleanupBlock();
- assert(FI.ContBB && "did not emit normal cleanup");
-
- // Emit the code into FinallyBB.
- CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
- Builder.SetInsertPoint(FI.FinallyBB);
- EmitStmt(Finally->getBlock());
-
- if (HaveInsertPoint()) {
- if (FI.ResumeBB) {
- llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot(),
- "abnormal.termination");
- IsEH = Builder.CreateICmpEQ(IsEH, llvm::ConstantInt::get(Int8Ty, 0));
- Builder.CreateCondBr(IsEH, FI.ContBB, FI.ResumeBB);
- } else {
- // There was nothing exceptional in the try body, so we only have normal
- // control flow.
- Builder.CreateBr(FI.ContBB);
- }
- }
-
- Builder.restoreIP(SavedIP);
-
return;
}
@@ -1666,7 +1691,13 @@ void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) {
if (HaveInsertPoint())
EmitStopPoint(&S);
- assert(!SEHTryEpilogueStack.empty() &&
- "sema should have rejected this __leave");
+ // This must be a __leave from a __finally block, which we warn on and is UB.
+ // Just emit unreachable.
+ if (!isSEHTryScope()) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ return;
+ }
+
EmitBranchThroughCleanup(*SEHTryEpilogueStack.back());
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index e4339849ca3..481fdbe2278 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1021,6 +1021,12 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+ // Returning from an outlined SEH helper is UB, and we already warn on it.
+ if (IsOutlinedSEHHelper) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
+ }
+
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 8401d722f42..42c3a423fa0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -40,7 +40,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
CurFn(nullptr), CapturedStmtInfo(nullptr),
SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false),
CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false),
- BlockInfo(nullptr), BlockPointer(nullptr),
+ IsOutlinedSEHHelper(false), BlockInfo(nullptr), BlockPointer(nullptr),
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 087acc7317d..343edc2ebf3 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -263,6 +263,10 @@ public:
/// potentially set the return value.
bool SawAsmBlock;
+ /// True if the current function is an outlined SEH helper. This can be a
+ /// finally block or filter expression.
+ bool IsOutlinedSEHHelper;
+
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -351,17 +355,6 @@ public:
void exit(CodeGenFunction &CGF);
};
- /// Cleanups can be emitted for two reasons: normal control leaving a region
- /// exceptional control flow leaving a region.
- struct SEHFinallyInfo {
- SEHFinallyInfo()
- : FinallyBB(nullptr), ContBB(nullptr), ResumeBB(nullptr) {}
-
- llvm::BasicBlock *FinallyBB;
- llvm::BasicBlock *ContBB;
- llvm::BasicBlock *ResumeBB;
- };
-
/// Returns true inside SEH __try blocks.
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
@@ -1052,10 +1045,6 @@ public:
llvm::Value *getExceptionSlot();
llvm::Value *getEHSelectorSlot();
- /// Stack slot that contains whether a __finally block is being executed as an
- /// EH cleanup or as a normal cleanup.
- llvm::Value *getAbnormalTerminationSlot();
-
/// Returns the contents of the function's exception object and selector
/// slots.
llvm::Value *getExceptionFromSlot();
@@ -2000,12 +1989,19 @@ public:
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
- void EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
- void ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
+ void EnterSEHTryStmt(const SEHTryStmt &S);
+ void ExitSEHTryStmt(const SEHTryStmt &S);
+
+ void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
+ QualType RetTy, FunctionArgList &Args,
+ const Stmt *OutlinedStmt);
llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except);
+ llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
+ const SEHFinallyStmt &Finally);
+
void EmitSEHExceptionCodeSave();
llvm::Value *EmitSEHExceptionCode();
llvm::Value *EmitSEHExceptionInfo();
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index d4e45f1b346..cd3785cd90b 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -387,8 +387,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
StringRef S = A->getValue();
if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||
MsanTrackOrigins > 2) {
- D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args)
- << S;
+ D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
}
}
}
OpenPOWER on IntegriCloud