зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
4bfe196841
Коммит
cc6a44b8bd
|
@ -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,41 +35,52 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
|
|||
CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
|
||||
} else {
|
||||
CGF.EmitAggExpr(Init, DeclPtr, isVolatile);
|
||||
|
||||
// Avoid generating destructor(s) for initialized objects.
|
||||
if (!isa<CXXConstructExpr>(Init))
|
||||
return;
|
||||
|
||||
const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
|
||||
if (Array)
|
||||
T = Context.getBaseElementType(Array);
|
||||
|
||||
const RecordType *RT = T->getAs<RecordType>();
|
||||
if (!RT)
|
||||
return;
|
||||
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (RD->hasTrivialDestructor())
|
||||
return;
|
||||
|
||||
CXXDestructorDecl *Dtor = RD->getDestructor(Context);
|
||||
|
||||
llvm::Constant *DtorFn;
|
||||
if (Array) {
|
||||
DtorFn =
|
||||
CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor,
|
||||
Array,
|
||||
DeclPtr);
|
||||
const llvm::Type *Int8PtrTy =
|
||||
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
|
||||
} else
|
||||
DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
|
||||
|
||||
CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
|
||||
if (Array)
|
||||
T = Context.getBaseElementType(Array);
|
||||
|
||||
const RecordType *RT = T->getAs<RecordType>();
|
||||
if (!RT)
|
||||
return;
|
||||
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (RD->hasTrivialDestructor())
|
||||
return;
|
||||
|
||||
CXXDestructorDecl *Dtor = RD->getDestructor(Context);
|
||||
|
||||
llvm::Constant *DtorFn;
|
||||
if (Array) {
|
||||
DtorFn =
|
||||
CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor,
|
||||
Array,
|
||||
DeclPtr);
|
||||
const llvm::Type *Int8PtrTy =
|
||||
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
|
||||
} else
|
||||
DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче