Author: David Blaikie Date: 2021-09-14T00:04:40-07:00 New Revision: db4ff98bf9733605c713e75ab6677523e6d267cb
URL: https://github.com/llvm/llvm-project/commit/db4ff98bf9733605c713e75ab6677523e6d267cb DIFF: https://github.com/llvm/llvm-project/commit/db4ff98bf9733605c713e75ab6677523e6d267cb.diff LOG: DebugInfo: Add support for template parameters with qualifiers eg: t1<void () const> - DWARF doesn't have a particularly nice way to encode this, for real member function types (like `void (t1::*)() const`) the const-ness is encoded in the type of the artificial first parameter. But `void () const` has no parameters, so encode it like a normal const-qualified type, using DW_TAG_const_type. (similarly for restrict and volatile) Reference qualifiers (& and &&) coming in a separate commit shortly. Added: Modified: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/test/CodeGenCXX/debug-info-template.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 0b10343f29a61..b7a6cd4fdf845 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -915,29 +915,41 @@ llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { return DBuilder.createBasicType("complex", Size, Encoding); } +static void stripUnusedQualifiers(Qualifiers &Q) { + // Ignore these qualifiers for now. + Q.removeObjCGCAttr(); + Q.removeAddressSpace(); + Q.removeObjCLifetime(); + Q.removeUnaligned(); +} + +static llvm::dwarf::Tag getNextQualifier(Qualifiers &Q) { + if (Q.hasConst()) { + Q.removeConst(); + return llvm::dwarf::DW_TAG_const_type; + } + if (Q.hasVolatile()) { + Q.removeVolatile(); + return llvm::dwarf::DW_TAG_volatile_type; + } + if (Q.hasRestrict()) { + Q.removeRestrict(); + return llvm::dwarf::DW_TAG_restrict_type; + } + return (llvm::dwarf::Tag)0; +} + llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit) { QualifierCollector Qc; const Type *T = Qc.strip(Ty); - // Ignore these qualifiers for now. - Qc.removeObjCGCAttr(); - Qc.removeAddressSpace(); - Qc.removeObjCLifetime(); + stripUnusedQualifiers(Qc); // We will create one Derived type for one qualifier and recurse to handle any // additional ones. - llvm::dwarf::Tag Tag; - if (Qc.hasConst()) { - Tag = llvm::dwarf::DW_TAG_const_type; - Qc.removeConst(); - } else if (Qc.hasVolatile()) { - Tag = llvm::dwarf::DW_TAG_volatile_type; - Qc.removeVolatile(); - } else if (Qc.hasRestrict()) { - Tag = llvm::dwarf::DW_TAG_restrict_type; - Qc.removeRestrict(); - } else { + llvm::dwarf::Tag Tag = getNextQualifier(Qc); + if (!Tag) { assert(Qc.empty() && "Unknown type qualifier for debug info"); return getOrCreateType(QualType(T, 0), Unit); } @@ -949,6 +961,30 @@ llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, return DBuilder.createQualifiedType(Tag, FromTy); } +llvm::DIType *CGDebugInfo::CreateQualifiedType(const FunctionProtoType *F, + llvm::DIFile *Unit) { + FunctionProtoType::ExtProtoInfo EPI = F->getExtProtoInfo(); + Qualifiers &Q = EPI.TypeQuals; + stripUnusedQualifiers(Q); + + // We will create one Derived type for one qualifier and recurse to handle any + // additional ones. + llvm::dwarf::Tag Tag = getNextQualifier(Q); + if (!Tag) { + assert(Q.empty() && "Unknown type qualifier for debug info"); + return nullptr; + } + + auto *FromTy = + getOrCreateType(CGM.getContext().getFunctionType(F->getReturnType(), + F->getParamTypes(), EPI), + Unit); + + // No need to fill in the Name, Line, Size, Alignment, Offset in case of + // CVR derived types. + return DBuilder.createQualifiedType(Tag, FromTy); +} + llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *Unit) { @@ -1304,6 +1340,14 @@ static unsigned getDwarfCC(CallingConv CC) { llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIFile *Unit) { + const auto *FPT = dyn_cast<FunctionProtoType>(Ty); + if (FPT) { + if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit)) + return QTy; + } + + // Create the type without any qualifiers + SmallVector<llvm::Metadata *, 16> EltTys; // Add the result type at least. @@ -1311,9 +1355,9 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, // Set up remainder of arguments if there is a prototype. // otherwise emit it as a variadic function. - if (isa<FunctionNoProtoType>(Ty)) + if (!FPT) EltTys.push_back(DBuilder.createUnspecifiedParameter()); - else if (const auto *FPT = dyn_cast<FunctionProtoType>(Ty)) { + else { for (const QualType &ParamType : FPT->param_types()) EltTys.push_back(getOrCreateType(ParamType, Unit)); if (FPT->isVariadic()) @@ -1321,8 +1365,9 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, } llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, + llvm::DIType *F = DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, getDwarfCC(Ty->getCallConv())); + return F; } /// Convert an AccessSpecifier into the corresponding DINode flag. @@ -1587,9 +1632,22 @@ llvm::DISubroutineType * CGDebugInfo::getOrCreateInstanceMethodType(QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile *Unit, bool decl) { + FunctionProtoType::ExtProtoInfo EPI = Func->getExtProtoInfo(); + Qualifiers &Qc = EPI.TypeQuals; + Qc.removeConst(); + Qc.removeVolatile(); + Qc.removeRestrict(); + Qc.removeUnaligned(); + // Keep the removed qualifiers in sync with + // CreateQualifiedType(const FunctionPrototype*, DIFile *Unit) + // Add "this" pointer. llvm::DITypeRefArray Args( - cast<llvm::DISubroutineType>(getOrCreateType(QualType(Func, 0), Unit)) + cast<llvm::DISubroutineType>( + getOrCreateType( + CGM.getContext().getFunctionType(Func->getReturnType(), + Func->getParamTypes(), EPI), + Unit)) ->getTypeArray()); assert(Args.size() && "Invalid number of arguments!"); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 6e873aab91400..6c1e65f608627 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -179,6 +179,8 @@ class CGDebugInfo { llvm::DIType *CreateType(const AutoType *Ty); llvm::DIType *CreateType(const ExtIntType *Ty); llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg); + llvm::DIType *CreateQualifiedType(const FunctionProtoType *Ty, + llvm::DIFile *Fg); llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg); llvm::DIType *CreateType(const TemplateSpecializationType *Ty, llvm::DIFile *Fg); diff --git a/clang/test/CodeGenCXX/debug-info-template.cpp b/clang/test/CodeGenCXX/debug-info-template.cpp index 7e8ccbcc5e5d7..0abb669b65353 100644 --- a/clang/test/CodeGenCXX/debug-info-template.cpp +++ b/clang/test/CodeGenCXX/debug-info-template.cpp @@ -215,3 +215,22 @@ void f1() { template void f1<>(); // CHECK: !DISubprogram(name: "f1<int>", } // namespace EmptyInnerPack + +namespace RawFuncQual { +struct t1; // use this to ensure the type parameter doesn't shift due to other test cases in this file +template<typename T1, typename T2> +void f1() { } +template void f1<t1 () volatile, t1 () const volatile>(); +// CHECK: !DISubprogram(name: "f1<RawFuncQual::t1 () volatile, RawFuncQual::t1 () const volatile>", +// CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]], + +// CHECK: ![[RAW_FUNC_QUAL_ARGS]] = !{![[RAW_FUNC_QUAL_T1:[0-9]*]], ![[RAW_FUNC_QUAL_T2:[0-9]*]]} +// CHECK: ![[RAW_FUNC_QUAL_T1]] = !DITemplateTypeParameter(name: "T1", type: ![[RAW_FUNC_QUAL_VOL:[0-9]*]]) +// CHECK: ![[RAW_FUNC_QUAL_VOL]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[RAW_FUNC_QUAL_TYPE:[0-9]*]]) +// CHECK: ![[RAW_FUNC_QUAL_TYPE]] = !DISubroutineType(types: ![[RAW_FUNC_QUAL_LIST:[0-9]*]] +// CHECK: ![[RAW_FUNC_QUAL_LIST]] = !{![[RAW_FUNC_QUAL_STRUCT:[0-9]*]]} +// CHECK: ![[RAW_FUNC_QUAL_STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "t1" +// CHECK: ![[RAW_FUNC_QUAL_T2]] = !DITemplateTypeParameter(name: "T2", type: ![[RAW_FUNC_QUAL_CNST:[0-9]*]]) +// CHECK: ![[RAW_FUNC_QUAL_CNST]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[RAW_FUNC_QUAL_TYPE:[0-9]*]]) + +} // namespace RawFuncQual _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits