[clang] Fix __try/__finally blocks in C++ constructors.

We were crashing trying to convert a GlobalDecl from a
CXXConstructorDecl.  Instead of trying to do that conversion, just pass
down the original GlobalDecl.

I think we could actually compute the correct constructor/destructor
kind from the context, given the way Microsoft mangling works, but it's
simpler to just pass through the correct constructor/destructor kind.

Differential Revision: https://reviews.llvm.org/D136776
This commit is contained in:
Eli Friedman 2022-11-16 15:13:33 -08:00
parent 55f56cdc33
commit 0fcb26c5b6
7 changed files with 32 additions and 21 deletions

View File

@ -166,10 +166,10 @@ public:
virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &) = 0;
virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
raw_ostream &Out) = 0;
virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
raw_ostream &Out) = 0;
/// Generates a unique string for an externally visible type for use with TBAA

View File

@ -118,9 +118,9 @@ public:
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
raw_ostream &Out) override;
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
@ -6430,23 +6430,25 @@ void ItaniumMangleContextImpl::mangleDynamicStermFinalizer(const VarDecl *D,
}
void ItaniumMangleContextImpl::mangleSEHFilterExpression(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
GlobalDecl EnclosingDecl, raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "__filt_";
if (shouldMangleDeclName(EnclosingDecl))
auto *EnclosingFD = cast<FunctionDecl>(EnclosingDecl.getDecl());
if (shouldMangleDeclName(EnclosingFD))
Mangler.mangle(EnclosingDecl);
else
Mangler.getStream() << EnclosingDecl->getName();
Mangler.getStream() << EnclosingFD->getName();
}
void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
GlobalDecl EnclosingDecl, raw_ostream &Out) {
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "__fin_";
if (shouldMangleDeclName(EnclosingDecl))
auto *EnclosingFD = cast<FunctionDecl>(EnclosingDecl.getDecl());
if (shouldMangleDeclName(EnclosingFD))
Mangler.mangle(EnclosingDecl);
else
Mangler.getStream() << EnclosingDecl->getName();
Mangler.getStream() << EnclosingFD->getName();
}
void ItaniumMangleContextImpl::mangleItaniumThreadLocalInit(const VarDecl *D,

View File

@ -142,8 +142,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
llvm::DenseMap<GlobalDecl, unsigned> SEHFilterIds;
llvm::DenseMap<GlobalDecl, unsigned> SEHFinallyIds;
SmallString<16> AnonymousNamespaceHash;
public:
@ -201,9 +201,9 @@ public:
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
raw_ostream &Out) override;
void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
@ -3730,7 +3730,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
GlobalDecl EnclosingDecl, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
// The function body is in the same comdat as the function with the handler,
@ -3742,7 +3742,7 @@ void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
}
void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
const NamedDecl *EnclosingDecl, raw_ostream &Out) {
GlobalDecl EnclosingDecl, raw_ostream &Out) {
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);
// The function body is in the same comdat as the function with the handler,

View File

@ -249,7 +249,7 @@ const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
// For outlined finallys and filters, use the SEH personality in case they
// contain more SEH. This mostly only affects finallys. Filters could
// hypothetically use gnu statement expressions to sneak in nested SEH.
FD = FD ? FD : CGF.CurSEHParent;
FD = FD ? FD : CGF.CurSEHParent.getDecl();
return get(CGF.CGM, dyn_cast_or_null<FunctionDecl>(FD));
}
@ -2005,7 +2005,7 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
const NamedDecl *ParentSEHFn = ParentCGF.CurSEHParent;
GlobalDecl ParentSEHFn = ParentCGF.CurSEHParent;
assert(ParentSEHFn && "No CurSEHParent!");
MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
if (IsFilter)

View File

@ -701,7 +701,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
CurCodeDecl = D;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (FD && FD->usesSEHTry())
CurSEHParent = FD;
CurSEHParent = GD;
CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
FnRetTy = RetTy;
CurFn = Fn;

View File

@ -539,7 +539,7 @@ public:
/// potentially set the return value.
bool SawAsmBlock = false;
const NamedDecl *CurSEHParent = nullptr;
GlobalDecl CurSEHParent;
/// True if the current function is an outlined SEH helper. This can be a
/// finally block or filter expression.
@ -2021,7 +2021,7 @@ public:
return getInvokeDestImpl();
}
bool currentFunctionUsesSEHTry() const { return CurSEHParent != nullptr; }
bool currentFunctionUsesSEHTry() const { return !!CurSEHParent; }
const TargetInfo &getTarget() const { return Target; }
llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); }

View File

@ -121,6 +121,15 @@ void use_seh_in_lambda() {
// CHECK: invoke void @might_throw() #[[NOINLINE]]
// CHECK: catchpad
class use_seh_in_constructor { use_seh_in_constructor(); };
use_seh_in_constructor::use_seh_in_constructor(){
__try {
} __finally {
}
}
// CHECK: define internal void @"?fin$0@0@?0use_seh_in_constructor@@"
static int my_unique_global;
extern "C" inline void use_seh_in_inline_func() {