aprantl created this revision. aprantl added reviewers: echristo, dblaikie, probinson. aprantl added a project: debug-info. Herald added a subscriber: JDevlieghere.
This implements the DWARF 5 feature described at http://www.dwarfstd.org/ShowIssue.php?issue=141215.1 This allows a consumer to understand whether a composite data type is trivially copyable and thus should be passed by value instead of by reference. The canonical example is being able to distinguish the following two types: // S is not trivially copyable because of the explicit destructor. struct S { ~S() {} }; // T is a POD type. struct T { ~T() = default; }; To avoid bloating the debug info with calling convention attributes, this patch only adds them were the calling convention is not obvious from the context. Implicitly by value is everything that clearly looks like a C struct, i.e.: - Non-C++ record types. - Types that define none of destructor, copy/move constructor, copy/move assignment operator. Implicitly by reference is everything clearly looks like a non-pod type: - Types that define a destructor, a copy constructor, and a copy assignment operator. Repository: rL LLVM https://reviews.llvm.org/D41743 Files: lib/CodeGen/CGDebugInfo.cpp test/CodeGenCXX/debug-info-composite-cc.cpp
Index: test/CodeGenCXX/debug-info-composite-cc.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/debug-info-composite-cc.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple %itanium_abi_triple %s -o - | FileCheck %s + +// Not trivially copyable because of the explicit destructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefDtor",{{.*size: [0-9]+, elem}} +struct RefDtor { + int i; + ~RefDtor() {} +} refDtor; + +// Not trivially copyable because of the explicit copy constructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefCopy",{{.*size: [0-9]+, elem}} +struct RefCopy { + int i; + RefCopy() {} + RefCopy(RefCopy &Copy) {} +} refCopy; + +// Not trivially copyable because of the explicit move constructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefMove",{{.*}}flags: DIFlagTypePassByReference +struct RefMove { + int i; + RefMove(){} + RefMove(RefMove &&Move) {} +} refMove; + +// Not trivially copyable because of the explicit copy assignment. +// CHECK-DAG: !DICompositeType({{.*}}, name: "RefCopyAss",{{.*size: [0-9]+, elem}} +struct RefCopyAss { + int i; + RefCopyAss &operator= (RefCopyAss &Copy) { return *this; } +} refCopyAss; + + +// POD-like type even though it defines a destructor. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Podlike", {{.*}}flags: DIFlagTypePassByValue +struct Podlike { + int i; + Podlike() = default; + Podlike(Podlike &&Move) = default; + ~Podlike() = default; +} podlike; + + +// This is a POD type. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Pod",{{.*size: [0-9]+, elem}} +struct Pod { + int i; +} pod; + +// This is definitely not a POD type. +// CHECK-DAG: !DICompositeType({{.*}}, name: "Complex",{{.*size: [0-9]+, elem}} +struct Complex { + Complex() {} + Complex(Complex &Copy) : i(Copy.i) {}; + int i; +} complex; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -2803,9 +2803,35 @@ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); + // Explicitly record the calling convention unless it is obvious + // from context. + // Implicitly by value is everything that clearly looks like a C struct, i.e.: + // - Non-C++ record types. + // - Types that define none of destructor, copy/move constructor, + // copy/move assignment operator. + // Implicitly by reference is everything clearly looks like a non-pod type: + // - Types that define a destructor, a copy constructor, and a copy + // assignment operator. + auto Flags = llvm::DINode::FlagZero; + if (auto CXXRD = dyn_cast<CXXRecordDecl>(RD)) { + if (CXXRD->isTriviallyCopyable()) { + if (CXXRD->hasUserDeclaredDestructor() || + CXXRD->hasUserDeclaredCopyConstructor() || + CXXRD->hasUserDeclaredMoveConstructor() || + CXXRD->hasUserDeclaredCopyAssignment() || + CXXRD->hasUserDeclaredMoveAssignment()) + Flags |= llvm::DINode::FlagTypePassByValue; + } else { + if (!CXXRD->hasUserDeclaredDestructor() && + !CXXRD->hasUserDeclaredCopyConstructor() && + !CXXRD->hasUserDeclaredCopyAssignment()) + Flags |= llvm::DINode::FlagTypePassByReference; + } + } + llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, - llvm::DINode::FlagZero, FullName); + Flags, FullName); // Elements of composite types usually have back to the type, creating // uniquing cycles. Distinct nodes are more efficient.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits