diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2281,22 +2281,19 @@ } static bool canUseCtorHoming(const CXXRecordDecl *RD) { - // Constructor homing can be used for classes that have at least one - // constructor and have no trivial or constexpr constructors. + // Constructor homing can be used for classes that cannnot be constructed + // without emitting code for one of their constructors. This is classes that + // don't have trivial or constexpr constructors, or can be created from + // aggregate initialization. Also skip lambda objects. + // Skip this optimization if the class or any of its methods are marked // dllimport. - if (RD->isLambda() || RD->hasConstexprNonCopyMoveConstructor() || - isClassOrMethodDLLImport(RD)) - return false; - - if (RD->ctors().empty()) + if (isClassOrMethodDLLImport(RD)) return false; - for (const auto *Ctor : RD->ctors()) - if (Ctor->isTrivial() && !Ctor->isCopyOrMoveConstructor()) - return false; - - return true; + return !RD->isLambda() && !RD->isAggregate() && + !RD->hasTrivialDefaultConstructor() && + !RD->hasConstexprNonCopyMoveConstructor(); } static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, diff --git a/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp b/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp --- a/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp +++ b/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp @@ -20,14 +20,58 @@ }; D::D() {} +// Test for constexpr constructor. // CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "E"{{.*}}DIFlagTypePassByValue struct E { constexpr E(){}; } TestE; +// Test for trivial constructor. // CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "F"{{.*}}DIFlagTypePassByValue struct F { F() = default; F(int) {} int i; } TestF; + +// Test for trivial constructor. +// CHECK-DAG: ![[G:.*]] ={{.*}}!DICompositeType({{.*}}name: "G"{{.*}}DIFlagTypePassByValue +// CHECK-DAG: !DICompositeType({{.*}}scope: ![[G]], {{.*}}DIFlagTypePassByValue +struct G { + G() : g_(0) {} + struct { + int g_; + }; +} TestG; + +// Test for an aggregate class with an implicit non-trivial default constructor +// that is not instantiated. +// CHECK-DAG: !DICompositeType({{.*}}name: "H",{{.*}}DIFlagTypePassByValue +struct H { + B b; +}; +void f(H h) {} + +// Test for an aggregate class with an implicit non-trivial default constructor +// that is instantiated. +// CHECK-DAG: !DICompositeType({{.*}}name: "J",{{.*}}DIFlagTypePassByValue +struct J { + B b; +}; +void f(decltype(J()) j) {} + +// Test for a class with trivial default constructor that is not instantiated. +// CHECK-DAG: !DICompositeType({{.*}}name: "K",{{.*}}DIFlagTypePassByValue +class K { + int i; +}; +void f(K k) {} + +// Test that we don't use constructor homing on lambdas. +// CHECK-DAG: ![[L:.*]] ={{.*}}!DISubprogram({{.*}}name: "L" +// CHECK-DAG: !DICompositeType({{.*}}scope: ![[L]], {{.*}}DIFlagTypePassByValue +void L() { + auto func = [&]() {}; +} + +