From c8df781e54a43593eafd993a5a5cd647866955f8 Mon Sep 17 00:00:00 2001 From: Amy Huang Date: Wed, 16 Sep 2020 09:58:39 -0700 Subject: [PATCH] [DebugInfo] Fix bug in constructor homing with classes with trivial constructors. This changes the code to avoid using constructor homing for aggregate classes and classes with trivial default constructors, instead of trying to loop through the constructors. Differential Revision: https://reviews.llvm.org/D87808 --- clang/lib/CodeGen/CGDebugInfo.cpp | 22 ++++++------ clang/test/CodeGenCXX/debug-info-limited-ctor.cpp | 42 +++++++++++++++++++++++ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 1fdb681..27c584f 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2281,22 +2281,20 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I, } 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 because they don't call + // constructors. + // 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 index 89dd2b1..cf2e89e 100644 --- a/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp +++ b/clang/test/CodeGenCXX/debug-info-limited-ctor.cpp @@ -20,14 +20,56 @@ struct D { }; 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 = [&]() {}; +} -- 2.7.4