For thread-safe static initialization of local statics with

destructors, place the __cxa_atexit call after the __cxa_guard_release
call, mimicking GCC/LLVM-GCC behavior. Noticed while debugging
something related.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103088 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-05-05 15:38:32 +00:00
Родитель 4bfe196841
Коммит cc6a44b8bd
2 изменённых файлов: 51 добавлений и 34 удалений

Просмотреть файл

@ -22,7 +22,6 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
assert(!D.getType()->isReferenceType() &&
"Should not call EmitDeclInit on a reference!");
CodeGenModule &CGM = CGF.CGM;
ASTContext &Context = CGF.getContext();
const Expr *Init = D.getInit();
@ -36,6 +35,18 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
}
}
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *DeclPtr) {
CodeGenModule &CGM = CGF.CGM;
ASTContext &Context = CGF.getContext();
const Expr *Init = D.getInit();
QualType T = D.getType();
if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType())
return;
// Avoid generating destructor(s) for initialized objects.
if (!isa<CXXConstructExpr>(Init))
@ -69,7 +80,6 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
}
}
void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
llvm::Constant *DeclPtr) {
@ -79,6 +89,7 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
if (!T->isReferenceType()) {
EmitDeclInit(*this, D, DeclPtr);
EmitDeclDestroy(*this, D, DeclPtr);
return;
}
if (Init->isLvalue(getContext()) == Expr::LV_Valid) {
@ -349,5 +360,9 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
Builder.CreateStore(One, Builder.CreateBitCast(GuardVariable, PtrTy));
}
// Register the call to the destructor.
if (!D.getType()->isReferenceType())
EmitDeclDestroy(*this, D, GV);
EmitBlock(EndBlock);
}

Просмотреть файл

@ -11,7 +11,9 @@ struct A {
};
void f() {
// CHECK: call void @_ZN1AC1Ev(
// CHECK: call i32 @__cxa_guard_acquire
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @__cxa_guard_release
// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @_ZZ1fvE1a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
static A a;
}