Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
/// Enables emitting Import Call sections on supported targets that can be used
/// by the Windows kernel to enable import call optimization.
CODEGENOPT(ImportCallOptimization, 1, 0)
CODEGENOPT(DebugTemplateParameterAsType, 1, 0)

/// FIXME: Make DebugOptions its own top-level .def file.
#include "DebugOptions.def"
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -9028,3 +9028,8 @@ def wasm_opt : Flag<["--"], "wasm-opt">,
Group<m_Group>,
HelpText<"Enable the wasm-opt optimizer (default)">,
MarshallingInfoNegativeFlag<LangOpts<"NoWasmOpt">>;
defm debug_template_parameter_as_type
: BoolFOption<"debug-template-parameter-as-type",
CodeGenOpts<"DebugTemplateParameterAsType">,
DefaultFalse, PosFlag<SetTrue>, NegFlag<SetFalse>,
BothFlags<[], [CC1Option]>>;
61 changes: 46 additions & 15 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,17 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return DBuilder.createBasicType(BTName, Size, Encoding);
}

llvm::DIType *CGDebugInfo::CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *U) {
llvm::DIType *debugType = getOrCreateType(Ty->getReplacementType(), U);
llvm::DIScope *Scope = static_cast<llvm::DIScope *>(U);
if (auto *Tty =
dyn_cast<ClassTemplateSpecializationDecl>(Ty->getAssociatedDecl()))
Scope = CGDebugInfo::getOrCreateType(QualType(Tty->getTypeForDecl(), 0), U);
return DBuilder.createTemplateTypeParameterAsType(
Scope, Ty->getReplacedParameter()->getName(), debugType);
}

llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {

StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt";
Expand Down Expand Up @@ -1240,8 +1251,9 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
Identifier);
if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
CollectCXXTemplateParams(TSpecial, DefUnit));
DBuilder.replaceArrays(
RetTy, llvm::DINodeArray(),
CollectCXXTemplateParams(TSpecial, DefUnit, RetTy));
ReplaceMap.emplace_back(
std::piecewise_construct, std::make_tuple(Ty),
std::make_tuple(static_cast<llvm::Metadata *>(RetTy)));
Expand Down Expand Up @@ -2275,12 +2287,14 @@ void CGDebugInfo::CollectCXXBasesAux(

llvm::DINodeArray
CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,
llvm::DIFile *Unit) {
llvm::DIFile *Unit,
llvm::DICompositeType *RealDecl) {
if (!OArgs)
return llvm::DINodeArray();
TemplateArgs &Args = *OArgs;
SmallVector<llvm::Metadata *, 16> TemplateParams;
for (unsigned i = 0, e = Args.Args.size(); i != e; ++i) {

const TemplateArgument &TA = Args.Args[i];
StringRef Name;
const bool defaultParameter = TA.getIsDefaulted();
Expand All @@ -2289,10 +2303,19 @@ CGDebugInfo::CollectTemplateParams(std::optional<TemplateArgs> OArgs,

switch (TA.getKind()) {
case TemplateArgument::Type: {
llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
TheCU, Name, TTy, defaultParameter));

if (CGM.getCodeGenOpts().DebugTemplateParameterAsType) {
llvm::DIType *debugType = getOrCreateType(TA.getAsType(), Unit);
llvm::DIScope *Scope = RealDecl != nullptr
? static_cast<llvm::DIScope *>(RealDecl)
: static_cast<llvm::DIScope *>(Unit);
llvm::DIType *TemplateType =
DBuilder.createTemplateTypeParameterAsType(Scope, Name, debugType);
TemplateParams.push_back(TemplateType);
} else {
llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
TheCU, Name, TTy, defaultParameter));
}
} break;
case TemplateArgument::Integral: {
llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);
Expand Down Expand Up @@ -2457,9 +2480,10 @@ llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
return CollectTemplateParams(GetTemplateArgs(VL), Unit);
}

llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD,
llvm::DIFile *Unit) {
return CollectTemplateParams(GetTemplateArgs(RD), Unit);
llvm::DINodeArray
CGDebugInfo::CollectCXXTemplateParams(const RecordDecl *RD, llvm::DIFile *Unit,
llvm::DICompositeType *RealDecl) {
return CollectTemplateParams(GetTemplateArgs(RD), Unit, RealDecl);
}

llvm::DINodeArray CGDebugInfo::CollectBTFDeclTagAnnotations(const Decl *D) {
Expand Down Expand Up @@ -3611,7 +3635,8 @@ llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
/*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
}

static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
static QualType UnwrapTypeForDebugInfo(QualType T, const CodeGenModule &CGM) {
const ASTContext &C = CGM.getContext();
Qualifiers Quals;
do {
Qualifiers InnerQuals = T.getLocalQualifiers();
Expand Down Expand Up @@ -3664,6 +3689,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<MacroQualifiedType>(T)->getUnderlyingType();
break;
case Type::SubstTemplateTypeParm:
if (CGM.getCodeGenOpts().DebugTemplateParameterAsType)
return C.getQualifiedType(T.getTypePtr(), Quals);
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
case Type::Auto:
Expand All @@ -3690,7 +3717,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
}

llvm::DIType *CGDebugInfo::getTypeOrNull(QualType Ty) {
assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM.getContext()));
assert(Ty == UnwrapTypeForDebugInfo(Ty, CGM));
auto It = TypeCache.find(Ty.getAsOpaquePtr());
if (It != TypeCache.end()) {
// Verify that the debug info still exists.
Expand Down Expand Up @@ -3729,7 +3756,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
});

// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
Ty = UnwrapTypeForDebugInfo(Ty, CGM);

if (auto *T = getTypeOrNull(Ty))
return T;
Expand Down Expand Up @@ -3866,6 +3893,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Decltype:
case Type::PackIndexing:
case Type::UnaryTransform:
if (Ty->getTypeClass() == Type::SubstTemplateTypeParm &&
CGM.getCodeGenOpts().DebugTemplateParameterAsType)
return CreateType(cast<SubstTemplateTypeParmType>(Ty), Unit);
break;
}

Expand Down Expand Up @@ -3990,8 +4020,9 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);

if (const auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
DBuilder.replaceArrays(RealDecl, llvm::DINodeArray(),
CollectCXXTemplateParams(TSpecial, DefUnit));
DBuilder.replaceArrays(
RealDecl, llvm::DINodeArray(),
CollectCXXTemplateParams(TSpecial, DefUnit, RealDecl));
return RealDecl;
}

Expand Down
12 changes: 8 additions & 4 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ class CGDebugInfo {
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const SubstTemplateTypeParmType *Ty,
llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
Expand Down Expand Up @@ -303,8 +305,9 @@ class CGDebugInfo {
llvm::ArrayRef<TemplateArgument> Args;
};
/// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(std::optional<TemplateArgs> Args,
llvm::DIFile *Unit);
llvm::DINodeArray
CollectTemplateParams(std::optional<TemplateArgs> Args, llvm::DIFile *Unit,
llvm::DICompositeType *RealDecl = nullptr);
/// A helper function to collect debug info for function template
/// parameters.
llvm::DINodeArray CollectFunctionTemplateParams(const FunctionDecl *FD,
Expand All @@ -321,8 +324,9 @@ class CGDebugInfo {

/// A helper function to collect debug info for template
/// parameters.
llvm::DINodeArray CollectCXXTemplateParams(const RecordDecl *TS,
llvm::DIFile *F);
llvm::DINodeArray
CollectCXXTemplateParams(const RecordDecl *TS, llvm::DIFile *F,
llvm::DICompositeType *RealDecl = nullptr);

/// A helper function to collect debug info for btf_decl_tag annotations.
llvm::DINodeArray CollectBTFDeclTagAnnotations(const Decl *D);
Expand Down
53 changes: 53 additions & 0 deletions clang/test/CodeGenCXX/debug-info-temp-param-as-type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -fdebug-template-parameter-as-type -triple x86_64-apple-darwin %s -o - | FileCheck %s


template <typename T>
struct TClass {
TClass();
void foo();
T val_;
int val2_;
};

template <typename T>
void TClass<T>::foo() {
T tVar = 1;
T* pT = &tVar;
tVar++;
}

template <typename T>
T bar(T tp) {
return tp;
}

int main () {
TClass<int> a;
a.val2_ = 3;
a.foo();
auto A = bar(42);
TClass<double> b;
return 0;
}

// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<int>"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM:![0-9]+]]
// CHECK: [[TPARAM]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val2_",{{.*}}baseType: [[INT]]

// CHECK: !DILocalVariable(name: "A",{{.*}}type: [[TPARAM3:![0-9]+]])
// CHECK: [[TPARAM3]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[INT]])

// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TClass<double>"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "val_",{{.*}}baseType: [[TPARAM2:![0-9]+]]
// CHECK: [[TPARAM2]] = !DIDerivedType(tag: DW_TAG_template_type_parameter, name: "T", {{.*}}baseType: [[DOUBLE:![0-9]+]])
// CHECK: [[DOUBLE]] = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)

// CHECK: distinct !DISubprogram(name: "foo"
// CHECK: !DILocalVariable(name: "tVar",{{.*}}type: [[TPARAM]])
// CHECK: !DILocalVariable(name: "pT",{{.*}}type: [[TPTR:![0-9]+]]
// CHECK: [[TPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[TPARAM]]

// CHECK: distinct !DISubprogram(name: "bar<int>"
// CHECK: !DILocalVariable(name: "tp",{{.*}}type: [[TPARAM3]])
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,12 @@ namespace llvm {
StringRef Name,
DIType *Ty,
bool IsDefault);
/// \param Scope Scope in which this type is defined.
/// \param Name Type parameter name.
/// \param Ty Parameter type.
DIDerivedType *createTemplateTypeParameterAsType(DIScope *Scope,
StringRef Name,
DIType *Ty);

/// Create debugging information for template
/// value parameter.
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,8 @@ void DwarfUnit::addTemplateParams(DIE &Buffer, DINodeArray TParams) {
constructTemplateTypeParameterDIE(Buffer, TTP);
else if (auto *TVP = dyn_cast<DITemplateValueParameter>(Element))
constructTemplateValueParameterDIE(Buffer, TVP);
else if (auto *TDT = dyn_cast<DIDerivedType>(Element))
createTypeDIE(TDT->getScope(), Buffer, TDT);
}
}

Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/IR/DIBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,15 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
SetterName, PropertyAttributes, Ty);
}

DIDerivedType *DIBuilder::createTemplateTypeParameterAsType(DIScope *Context,
StringRef Name,
DIType *Ty) {
return DIDerivedType::get(VMContext, dwarf::DW_TAG_template_type_parameter,
Name, nullptr, 0, Context, Ty, 0, 0, 0,
std::nullopt, std::nullopt, DINode::FlagZero,
nullptr);
}

DITemplateTypeParameter *
DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,
DIType *Ty, bool isDefault) {
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_friend ||
N.getTag() == dwarf::DW_TAG_set_type ||
N.getTag() == dwarf::DW_TAG_template_type_parameter ||
N.getTag() == dwarf::DW_TAG_template_alias,
"invalid tag", &N);
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
Expand Down Expand Up @@ -1288,8 +1289,11 @@ void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
auto *Params = dyn_cast<MDTuple>(&RawParams);
CheckDI(Params, "invalid template params", &N, &RawParams);
for (Metadata *Op : Params->operands()) {
CheckDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",
&N, Params, Op);
CheckDI(((Op) && (isa<DITemplateParameter>(Op))) ||
((isa<DIDerivedType>(Op)) &&
(dyn_cast<DIDerivedType>(Op)->getTag() ==
dwarf::DW_TAG_template_type_parameter)),
"invalid template parameter", &N, Params, Op);
}
}

Expand Down
Loading