diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2f7288109c0e..577dd0adaf2f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7446,27 +7446,20 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) return false; - // Structs that have non-trivial constructors or destructors are required. - - // FIXME: Handle references. - // FIXME: Be more selective about which constructors we care about. - if (const RecordType *RT = VD->getType()->getAs()) { - if (const CXXRecordDecl *RD = dyn_cast(RT->getDecl())) { - if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() && - RD->hasTrivialCopyConstructor() && - RD->hasTrivialMoveConstructor() && - RD->hasTrivialDestructor())) - return true; - } - } - + // Variables that can be needed in other TUs are required. GVALinkage L = GetGVALinkageForVariable(VD); - if (L == GVA_Internal || L == GVA_TemplateInstantiation) { - if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this))) - return false; - } + if (L != GVA_Internal && L != GVA_TemplateInstantiation) + return true; - return true; + // Variables that have destruction with side-effects are required. + if (VD->getType().isDestructedType()) + return true; + + // Variables that have initialization with side-effects are required. + if (VD->getInit() && VD->getInit()->HasSideEffects(*this)) + return true; + + return false; } CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { diff --git a/clang/test/CodeGenCXX/global-array-destruction.cpp b/clang/test/CodeGenCXX/global-array-destruction.cpp index 076ef942201d..b86432228cf0 100644 --- a/clang/test/CodeGenCXX/global-array-destruction.cpp +++ b/clang/test/CodeGenCXX/global-array-destruction.cpp @@ -43,3 +43,11 @@ T t[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; // CHECK: call void @_ZN1TD1Ev // CHECK: icmp eq {{.*}} @t // CHECK: br i1 {{.*}} + +static T t2[2][3] = { 1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10, 11.0, 12 }; + +// CHECK: call {{.*}} @__cxa_atexit +// CHECK: getelementptr inbounds ({{.*}} bitcast {{.*}}* @_ZL2t2 to %struct.T*), i64 6 +// CHECK: call void @_ZN1TD1Ev +// CHECK: icmp eq {{.*}} @_ZL2t +// CHECK: br i1 {{.*}} diff --git a/clang/test/CodeGenCXX/trivial-constructor-init.cpp b/clang/test/CodeGenCXX/trivial-constructor-init.cpp index 343dc6575a71..4922a9ee090e 100644 --- a/clang/test/CodeGenCXX/trivial-constructor-init.cpp +++ b/clang/test/CodeGenCXX/trivial-constructor-init.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -S %s -o %t-64.s -// RUN: %clang_cc1 -S %s -o %t-32.s +// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -std=c++11 | FileCheck %s extern "C" int printf(...); @@ -16,5 +16,20 @@ struct A { A a; +struct B { + B() = default; + B(const B&); +}; + +// CHECK-NOT: _ZL1b +static B b; + +struct C { + ~C(); +}; + +// CHECK: _ZL1c +static C c[4]; + int main() { }