[clang] db4ff98 - DebugInfo: Add support for template parameters with qualifiers
David Blaikie via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 14 00:04:56 PDT 2021
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
More information about the cfe-commits
mailing list