From 8973da380a7c458535623265c509cb7cde3126e7 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 10 Mar 2023 16:46:47 +0000 Subject: [PATCH 1/3] [clang][DebugInfo] Emit DW_AT_type of preferred name if available With this patch, whenever we emit a `DW_AT_type` for some declaration and the type is a template class with a `clang::PreferredNameAttr`, we will emit the typedef that the attribute refers to instead. I.e., ``` 0x123 DW_TAG_variable DW_AT_name "var" DW_AT_type (0x123 "basic_string") 0x124 DW_TAG_structure_type DW_AT_name "basic_string" ``` ...becomes ``` 0x123 DW_TAG_variable DW_AT_name "var" DW_AT_type (0x124 "std::string") 0x124 DW_TAG_structure_type DW_AT_name "basic_string" 0x125 DW_TAG_typedef DW_AT_name "std::string" DW_AT_type (0x124 "basic_string") ``` We do this by returning the preferred name typedef `DIType` when we create a structure definition. In some cases, e.g., with `-gmodules`, we don't complete the structure definition immediately but do so later via `completeClassData`, which overwrites the `TypeCache`. In such cases we don't actually want to rewrite the cache with the preferred name. We handle this by returning both the definition and the preferred typedef from `CreateTypeDefinition` and let the callee decide what to do with it. Essentially we set up the types as: ``` TypeCache[Record] => DICompositeType ReplaceMap[Record] => DIDerivedType(baseType: DICompositeType) ``` For now we keep this behind LLDB tuning. **Testing** - Added clang unit-test - `check-llvm`, `check-clang` pass - Confirmed that this change correctly repoints `basic_string` references in some of my test programs. - Will add follow-up LLDB API tests Differential Revision: https://reviews.llvm.org/D145803 (cherry picked from commit 19cc390ba239a7037f4df62f31ec4a9bf91924a7) --- clang/lib/CodeGen/CGDebugInfo.cpp | 41 +++++++-- clang/lib/CodeGen/CGDebugInfo.h | 16 +++- clang/test/CodeGen/preferred_name-chain.cpp | 65 ++++++++++++++ clang/test/CodeGen/preferred_name.cpp | 89 +++++++++++++++++++ .../Inputs/gmodules-preferred-name-alias.h | 8 ++ .../gmodules-preferred-name-alias.modulemap | 4 + .../Inputs/gmodules-preferred-name-typedef.h | 7 ++ .../gmodules-preferred-name-typedef.modulemap | 4 + .../Modules/gmodules-preferred-name-alias.cpp | 12 +++ .../gmodules-preferred-name-typedef.cpp | 12 +++ .../TestDataFormatterLibcxxSharedPtr.py | 2 +- .../TestDataFormatterLibcxxUniquePtr.py | 2 +- 12 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 clang/test/CodeGen/preferred_name-chain.cpp create mode 100644 clang/test/CodeGen/preferred_name.cpp create mode 100644 clang/test/Modules/Inputs/gmodules-preferred-name-alias.h create mode 100644 clang/test/Modules/Inputs/gmodules-preferred-name-alias.modulemap create mode 100644 clang/test/Modules/Inputs/gmodules-preferred-name-typedef.h create mode 100644 clang/test/Modules/Inputs/gmodules-preferred-name-typedef.modulemap create mode 100644 clang/test/Modules/gmodules-preferred-name-alias.cpp create mode 100644 clang/test/Modules/gmodules-preferred-name-typedef.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0a1f72f9f07d2..63235d792b1df 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2451,7 +2451,11 @@ void CGDebugInfo::completeClass(const RecordDecl *RD) { auto I = TypeCache.find(TyPtr); if (I != TypeCache.end() && !cast(I->second)->isForwardDecl()) return; - llvm::DIType *Res = CreateTypeDefinition(Ty->castAs()); + + // We want the canonical definition of the structure to not + // be the typedef. Since that would lead to circular typedef + // metadata. + auto [Res, PrefRes] = CreateTypeDefinition(Ty->castAs()); assert(!Res->isForwardDecl()); TypeCache[TyPtr].reset(Res); } @@ -2562,10 +2566,25 @@ llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { return T; } - return CreateTypeDefinition(Ty); + auto [Def, Pref] = CreateTypeDefinition(Ty); + + return Pref ? Pref : Def; } -llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { +llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD, + llvm::DIFile *Unit) { + if (!RD) + return nullptr; + + auto const *PNA = RD->getAttr(); + if (!PNA) + return nullptr; + + return getOrCreateType(PNA->getTypedefType(), Unit); +} + +std::pair +CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); // Get overall information about the record type for the debug info. @@ -2581,7 +2600,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { const RecordDecl *D = RD->getDefinition(); if (!D || !D->isCompleteDefinition()) - return FwdDecl; + return {FwdDecl, nullptr}; if (const auto *CXXDecl = dyn_cast(RD)) CollectContainingType(CXXDecl, FwdDecl); @@ -2620,7 +2639,12 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl)); RegionMap[Ty->getDecl()].reset(FwdDecl); - return FwdDecl; + + if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB) + if (auto *PrefDI = GetPreferredNameType(CXXDecl, DefUnit)) + return {FwdDecl, PrefDI}; + + return {FwdDecl, nullptr}; } llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty, @@ -3645,7 +3669,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType *RealDecl) { // A class's primary base or the class itself contains the vtable. - llvm::DICompositeType *ContainingType = nullptr; + llvm::DIType *ContainingType = nullptr; const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { // Seek non-virtual primary base root. @@ -3657,9 +3681,8 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, else break; } - ContainingType = cast( - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), - getOrCreateFile(RD->getLocation()))); + ContainingType = getOrCreateType(QualType(PBase->getTypeForDecl(), 0), + getOrCreateFile(RD->getLocation())); } else if (RD->isDynamicClass()) ContainingType = RealDecl; diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 4ab3aa573e750..03408f474330e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -190,7 +190,15 @@ class CGDebugInfo { llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F); /// Get structure or union type. llvm::DIType *CreateType(const RecordType *Tyg); - llvm::DIType *CreateTypeDefinition(const RecordType *Ty); + + /// Create definition for the specified 'Ty'. + /// + /// \returns A pair of 'llvm::DIType's. The first is the definition + /// of the 'Ty'. The second is the type specified by the preferred_name + /// attribute on 'Ty', which can be a nullptr if no such attribute + /// exists. + std::pair + CreateTypeDefinition(const RecordType *Ty); llvm::DICompositeType *CreateLimitedType(const RecordType *Ty); void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType *CT); @@ -274,6 +282,12 @@ class CGDebugInfo { llvm::DenseSet> &SeenTypes, llvm::DINode::DIFlags StartingFlags); + /// Helper function that returns the llvm::DIType that the + /// PreferredNameAttr attribute on \ref RD refers to. If no such + /// attribute exists, returns nullptr. + llvm::DIType *GetPreferredNameType(const CXXRecordDecl *RD, + llvm::DIFile *Unit); + struct TemplateArgs { const TemplateParameterList *TList; llvm::ArrayRef Args; diff --git a/clang/test/CodeGen/preferred_name-chain.cpp b/clang/test/CodeGen/preferred_name-chain.cpp new file mode 100644 index 0000000000000..3108caef02dd7 --- /dev/null +++ b/clang/test/CodeGen/preferred_name-chain.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -debugger-tuning=lldb %s | FileCheck %s --check-prefixes=COMMON,LLDB +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -debugger-tuning=gdb %s | FileCheck %s --check-prefixes=COMMON,GDB + +template +struct Foo; + +typedef Foo BarIntBase; +typedef BarIntBase BarIntTmp; +typedef BarIntTmp BarInt; + +template +using BarBase = Foo; + +template +using BarTmp = BarBase; + +template +using Bar = BarTmp; + +template +struct [[clang::preferred_name(BarInt), + clang::preferred_name(Bar)]] Foo{ + }; + +int main() { + Foo varInt; + +// COMMON: !DILocalVariable(name: "varInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_INT_TY:[0-9]+]]) +// LLDB: ![[BAR_INT_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarInt", file: ![[#]], line: [[#]], baseType: ![[BAR_INT_TMP:[0-9]+]]) +// LLDB: ![[BAR_INT_TMP]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarIntTmp", file: ![[#]], line: [[#]], baseType: ![[BAR_INT_BASE:[0-9]+]]) +// LLDB: ![[BAR_INT_BASE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarIntBase", file: ![[#]], line: [[#]], baseType: ![[FOO_INT:[0-9]+]]) +// LLDB: ![[FOO_INT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: ![[#]], line: [[#]], size: [[#]] +// GDB: ![[BAR_INT_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: ![[#]], line: [[#]], size: [[#]] + + Foo varChar; + +// COMMON: !DILocalVariable(name: "varChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TY:[0-9]+]]) +// LLDB: ![[BAR_CHAR_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_TMP:[0-9]+]]) +// LLDB: ![[BAR_CHAR_TMP]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarTmp", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_BASE:[0-9]+]]) +// LLDB: ![[BAR_CHAR_BASE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarBase", file: ![[#]], line: [[#]], baseType: ![[FOO_CHAR:[0-9]+]]) +// LLDB: ![[FOO_CHAR]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" +// GDB: ![[BAR_CHAR_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + + Foo> varFooInt; + +// COMMON: !DILocalVariable(name: "varFooInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[FOO_BAR_INT_TY:[0-9]+]]) +// COMMON: ![[FOO_BAR_INT_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo >" +// COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] +// COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} +// GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) + + Foo> varFooChar; + +// COMMON: !DILocalVariable(name: "varFooChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[FOO_BAR_CHAR_TY:[0-9]+]]) +// COMMON: ![[FOO_BAR_CHAR_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo >" +// COMMON-SAME: templateParams: ![[CHAR_PARAM:[0-9]+]] +// COMMON: ![[CHAR_PARAM]] = !{![[CHAR_TEMPL_TYPE_PARAM:[0-9]+]]} +// GDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) +// LLDB: ![[CHAR_TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_CHAR_TY]]) + + return 0; +} + + diff --git a/clang/test/CodeGen/preferred_name.cpp b/clang/test/CodeGen/preferred_name.cpp new file mode 100644 index 0000000000000..9b3f532faf978 --- /dev/null +++ b/clang/test/CodeGen/preferred_name.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -debugger-tuning=lldb %s | FileCheck %s --check-prefixes=COMMON,LLDB +// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -debugger-tuning=gdb %s | FileCheck %s --check-prefixes=COMMON,GDB + +template +struct Foo; + +typedef Foo BarInt; +typedef Foo BarDouble; + +template +using Bar = Foo; + +template +struct [[clang::preferred_name(BarInt), + clang::preferred_name(BarDouble), + clang::preferred_name(Bar), + clang::preferred_name(Bar)]] Foo{ + }; + +int main() { + Foo varInt; + +// COMMON: !DILocalVariable(name: "varInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_INT_TY:[0-9]+]]) +// LLDB: ![[BAR_INT_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarInt", file: ![[#]], line: [[#]], baseType: ![[BAR_INT_BASE:[0-9]+]]) +// LLDB: ![[BAR_INT_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: ![[#]], line: [[#]], size: [[#]] +// GDB: ![[BAR_INT_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: ![[#]], line: [[#]], size: [[#]] + + Foo varDouble; + +// COMMON: !DILocalVariable(name: "varDouble", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_DOUBLE_TY:[0-9]+]]) +// LLDB: ![[BAR_DOUBLE_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarDouble", file: ![[#]], line: [[#]], baseType: ![[BAR_DOUBLE_BASE:[0-9]+]]) +// LLDB: ![[BAR_DOUBLE_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" +// GDB: ![[BAR_DOUBLE_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + + Foo varShort; + +// COMMON: !DILocalVariable(name: "varShort", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_SHORT_TY:[0-9]+]]) +// LLDB: ![[BAR_SHORT_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: ![[#]], line: [[#]], baseType: ![[BAR_SHORT_BASE:[0-9]+]]) +// LLDB: ![[BAR_SHORT_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" +// GDB: ![[BAR_SHORT_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + + Foo varChar; + +// COMMON: !DILocalVariable(name: "varChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TY:[0-9]+]]) +// LLDB: ![[BAR_CHAR_TY]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_BASE:[0-9]+]]) +// LLDB: ![[BAR_CHAR_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" +// GDB: ![[BAR_CHAR_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + + Foo> varFooInt; + +// COMMON: !DILocalVariable(name: "varFooInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[FOO_BAR_INT_TY:[0-9]+]]) +// COMMON: ![[FOO_BAR_INT_TY]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo >" +// COMMON-SAME: templateParams: ![[PARAM:[0-9]+]] +// COMMON: ![[PARAM]] = !{![[TEMPL_TYPE_PARAM:[0-9]+]]} +// GDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) +// LLDB: ![[TEMPL_TYPE_PARAM]] = !DITemplateTypeParameter(name: "T", type: ![[BAR_INT_TY]]) + + BarInt barInt; + +// LLDB: !DILocalVariable(name: "barInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_INT_TY]]) +// GDB: !DILocalVariable(name: "barInt", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_INT_TYPEDEF:[0-9]+]]) +// GDB: ![[BAR_INT_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarInt" + + BarDouble barDouble; + +// LLDB: !DILocalVariable(name: "barDouble", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_DOUBLE_TY]]) +// GDB: !DILocalVariable(name: "barDouble", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_DOUBLE_TYPEDEF:[0-9]+]]) +// GDB: ![[BAR_DOUBLE_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "BarDouble" + + Bar barShort; + +// LLDB: !DILocalVariable(name: "barShort", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_SHORT_TY_2:[0-9]+]]) +// GDB: !DILocalVariable(name: "barShort", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_SHORT_TYPEDEF:[0-9]+]]) +// GDB: ![[BAR_SHORT_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar" + + Bar barChar; + +// LLDB: ![[BAR_SHORT_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: ![[#]], line: [[#]], baseType: ![[BAR_SHORT_TY]]) + +// LLDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TY_2:[0-9]+]]) +// GDB: !DILocalVariable(name: "barChar", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[BAR_CHAR_TYPEDEF:[0-9]+]]) +// GDB: ![[BAR_CHAR_TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar" + +// LLDB: ![[BAR_CHAR_TY_2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", file: ![[#]], line: [[#]], baseType: ![[BAR_CHAR_TY]]) + + return 0; +} + + diff --git a/clang/test/Modules/Inputs/gmodules-preferred-name-alias.h b/clang/test/Modules/Inputs/gmodules-preferred-name-alias.h new file mode 100644 index 0000000000000..086046955991f --- /dev/null +++ b/clang/test/Modules/Inputs/gmodules-preferred-name-alias.h @@ -0,0 +1,8 @@ +template struct Foo; + +template +using Bar = Foo; + +template struct [[clang::preferred_name(Bar)]] Foo {}; + +template struct Baz { Foo member; }; diff --git a/clang/test/Modules/Inputs/gmodules-preferred-name-alias.modulemap b/clang/test/Modules/Inputs/gmodules-preferred-name-alias.modulemap new file mode 100644 index 0000000000000..13f7712b2a6b9 --- /dev/null +++ b/clang/test/Modules/Inputs/gmodules-preferred-name-alias.modulemap @@ -0,0 +1,4 @@ +module PreferredNameModule { + header "gmodules-preferred-name-alias.h" + export * +} diff --git a/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.h b/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.h new file mode 100644 index 0000000000000..0072a1d7b79eb --- /dev/null +++ b/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.h @@ -0,0 +1,7 @@ +template struct Foo; + +typedef Foo Bar; + +template struct [[clang::preferred_name(Bar)]] Foo {}; + +template struct Baz { Foo member; }; diff --git a/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.modulemap b/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.modulemap new file mode 100644 index 0000000000000..8de9308eb1cab --- /dev/null +++ b/clang/test/Modules/Inputs/gmodules-preferred-name-typedef.modulemap @@ -0,0 +1,4 @@ +module PreferredNameModule { + header "gmodules-preferred-name-typedef.h" + export * +} diff --git a/clang/test/Modules/gmodules-preferred-name-alias.cpp b/clang/test/Modules/gmodules-preferred-name-alias.cpp new file mode 100644 index 0000000000000..4eba07c7d2594 --- /dev/null +++ b/clang/test/Modules/gmodules-preferred-name-alias.cpp @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -dwarf-ext-refs -fmodule-format=obj \ +// RUN: -fmodule-map-file=%S/Inputs/gmodules-preferred-name-alias.modulemap \ +// RUN: -fmodules-cache-path=%t -debug-info-kind=standalone -debugger-tuning=lldb \ +// RUN: -fmodules -mllvm -debug-only=pchcontainer -x c++ \ +// RUN: -I %S/Inputs %s &> %t.ll +// RUN: cat %t.ll | FileCheck %s + +#include "gmodules-preferred-name-alias.h" + +// CHECK: ![[#]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[PREF_BASE:[0-9]+]]) +// CHECK: ![[PREF_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" diff --git a/clang/test/Modules/gmodules-preferred-name-typedef.cpp b/clang/test/Modules/gmodules-preferred-name-typedef.cpp new file mode 100644 index 0000000000000..e4738089d9893 --- /dev/null +++ b/clang/test/Modules/gmodules-preferred-name-typedef.cpp @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -dwarf-ext-refs -fmodule-format=obj \ +// RUN: -fmodule-map-file=%S/Inputs/gmodules-preferred-name-typedef.modulemap \ +// RUN: -fmodules-cache-path=%t -debug-info-kind=standalone -debugger-tuning=lldb \ +// RUN: -fmodules -mllvm -debug-only=pchcontainer -x c++ \ +// RUN: -I %S/Inputs %s &> %t.ll +// RUN: cat %t.ll | FileCheck %s + +#include "gmodules-preferred-name-typedef.h" + +// CHECK: ![[#]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Bar", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[PREF_BASE:[0-9]+]]) +// CHECK: ![[PREF_BASE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py index 7ab4c9db2c1a3..b4de2aa9146a9 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py @@ -60,7 +60,7 @@ def test_shared_ptr_variables(self): valobj = self.expect_var_path( "sp_str", - type="std::shared_ptr >", + type="std::shared_ptr", children=[ValueCheck(name="__ptr_", summary='"hello"')], ) self.assertRegex(valobj.summary, r'^"hello"( strong=1)? weak=1$') diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py index a0d12b4f2061d..252c39c6067e2 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py @@ -60,7 +60,7 @@ def test_unique_ptr_variables(self): valobj = self.expect_var_path( "up_str", - type="std::unique_ptr >", + type="std::unique_ptr", summary='"hello"', children=[ValueCheck(name="__value_", summary='"hello"')], ) From 6c8267828832d3bd3dd8e04af2d4a2ee57c943b7 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 6 Apr 2023 11:06:54 +0100 Subject: [PATCH 2/3] [ReleaseNotes] DebugInfo: preferred_name attribute changes Describes changes made in D145803. Differential Revision: https://reviews.llvm.org/D147695 (cherry picked from commit 80fe7358f6f4811d2619cf4c09fb246b6b6c764b) --- llvm/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index c4fdabc20fc74..3121b1cdc2157 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -169,6 +169,11 @@ Changes to the Debug Info During this release ... +* When a template class annotated with the ``[[clang::preferred_name]]`` attribute + were to appear in a ``DW_AT_type``, the type will now be that of the preferred_name + instead. This is only enabled when tuned for LLDB at the moment. + (`D145803 `_) + Changes to the LLVM tools --------------------------------- From 3e95d3e2d0e3268a0812a223f7d363a102e8fe58 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Sat, 11 Mar 2023 00:48:53 +0000 Subject: [PATCH 3/3] [lldb][test] Add tests for clang::PreferredNameAttr formatting Add some tests to make sure we're formatting structures with preferred names correctly. Differential Revision: https://reviews.llvm.org/D145832 (cherry picked from commit 1eaf3b746dab1eb139e1f0a4ded7f15cb44d936a) --- .../test/API/lang/cpp/preferred_name/Makefile | 3 ++ .../cpp/preferred_name/TestPreferredName.py | 42 +++++++++++++++++++ .../test/API/lang/cpp/preferred_name/main.cpp | 26 ++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 lldb/test/API/lang/cpp/preferred_name/Makefile create mode 100644 lldb/test/API/lang/cpp/preferred_name/TestPreferredName.py create mode 100644 lldb/test/API/lang/cpp/preferred_name/main.cpp diff --git a/lldb/test/API/lang/cpp/preferred_name/Makefile b/lldb/test/API/lang/cpp/preferred_name/Makefile new file mode 100644 index 0000000000000..36117723fd1df --- /dev/null +++ b/lldb/test/API/lang/cpp/preferred_name/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -std=c++20 -glldb +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/preferred_name/TestPreferredName.py b/lldb/test/API/lang/cpp/preferred_name/TestPreferredName.py new file mode 100644 index 0000000000000..ce8be32099711 --- /dev/null +++ b/lldb/test/API/lang/cpp/preferred_name/TestPreferredName.py @@ -0,0 +1,42 @@ +""" +Test formatting of types annotated with +[[clang::preferred_name]] attributes. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test import decorators + + +class TestPreferredName(TestBase): + + def test_frame_var(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "return", lldb.SBFileSpec("main.cpp")) + + self.expect("frame variable barInt", substrs=["BarInt"]) + self.expect("frame variable barDouble", substrs=["BarDouble"]) + self.expect("frame variable barShort", substrs=["Bar"]) + self.expect("frame variable barChar", substrs=["Bar"]) + + self.expect("frame variable varInt", substrs=["BarInt"]) + self.expect("frame variable varDouble", substrs=["BarDouble"]) + self.expect("frame variable varShort", substrs=["Bar"]) + self.expect("frame variable varChar", substrs=["Bar"]) + self.expect("frame variable varFooInt", substrs=["Foo"]) + + def test_expr(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "return", lldb.SBFileSpec("main.cpp")) + + self.expect_expr("barInt", result_type="BarInt") + self.expect_expr("barDouble", result_type="BarDouble") + self.expect_expr("barShort", result_type="Bar") + self.expect_expr("barChar", result_type="Bar") + + self.expect_expr("varInt", result_type="BarInt") + self.expect_expr("varDouble", result_type="BarDouble") + self.expect_expr("varShort", result_type="Bar") + self.expect_expr("varChar", result_type="Bar") + self.expect_expr("varFooInt", result_type="Foo") diff --git a/lldb/test/API/lang/cpp/preferred_name/main.cpp b/lldb/test/API/lang/cpp/preferred_name/main.cpp new file mode 100644 index 0000000000000..dd9cf22d94b2d --- /dev/null +++ b/lldb/test/API/lang/cpp/preferred_name/main.cpp @@ -0,0 +1,26 @@ +template struct Foo; + +typedef Foo BarInt; +typedef Foo BarDouble; + +template using Bar = Foo; + +template +struct [[clang::preferred_name(BarInt), clang::preferred_name(BarDouble), + clang::preferred_name(Bar), clang::preferred_name(Bar), + clang::preferred_name(Bar), + clang::preferred_name(Bar)]] Foo{}; + +int main() { + BarInt barInt; + BarDouble barDouble; + Bar barShort; + Bar barChar; + + Foo varInt; + Foo varDouble; + Foo varShort; + Foo varChar; + Foo> varFooInt; + return 0; +}