Skip to content

[Clang] Fall back to DW_TAG_typedef for instantiation dependent template aliases #90032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 25, 2024

Conversation

OCHyams
Copy link
Contributor

@OCHyams OCHyams commented Apr 25, 2024

Workaround for issue #89774 until it can be properly fixed.

When -gtemplate-alias is specified Clang emits a DW_TAG_template_alias for template aliases. This patch avoids an assertion failure by falling back to the -gno-template-alias (default) behaviour, emitting a DW_TAG_typedef, if the alias is instantiation dependent.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. debuginfo labels Apr 25, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 25, 2024

@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-clang

Author: Orlando Cazalet-Hyams (OCHyams)

Changes

Workaround for issue #89774 until it can be properly fixed.

When -gtemplate-alias is specified Clang emits a DW_TAG_template_alias for template aliases. This patch avoids an assertion failure by falling back to the -gno-template-alias (default) behaviour, emitting a DW_TAG_typedef, if the alias is instantiation dependent.


Full diff: https://github.com/llvm/llvm-project/pull/90032.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+20-1)
  • (added) clang/test/CodeGenCXX/dependent-template-alias.cpp (+21)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 539ded5cca5e1b..787db350487417 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1372,7 +1372,26 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
 
   SourceLocation Loc = AliasDecl->getLocation();
 
-  if (CGM.getCodeGenOpts().DebugTemplateAlias) {
+  if (CGM.getCodeGenOpts().DebugTemplateAlias &&
+      // The TemplateSpecializationType doesn't contain any instantiation
+      // information; dependent template arguments can't be resolved. For now,
+      // fall back to DW_TAG_typedefs for template aliases that are
+      // instantiation dependent, e.g.:
+      // ```
+      // template <int>
+      // using A = int;
+      //
+      // template<int I>
+      // struct S {
+      //   using AA = A<I>; // Instantiation dependent.
+      //   AA aa;
+      // };
+      //
+      // S<0> s;
+      // ```
+      // S::AA's underlying type A<I> is dependent on I so will be emitted as a
+      // DW_TAG_typedef.
+      !Ty->isInstantiationDependentType()) {
     auto ArgVector = ::GetTemplateArgs(TD, Ty);
     TemplateArgs Args = {TD->getTemplateParameters(), ArgVector};
 
diff --git a/clang/test/CodeGenCXX/dependent-template-alias.cpp b/clang/test/CodeGenCXX/dependent-template-alias.cpp
new file mode 100644
index 00000000000000..deb243f9fc88d0
--- /dev/null
+++ b/clang/test/CodeGenCXX/dependent-template-alias.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \
+// RUN: | FileCheck %s
+
+//// Check that -gtemplate-alias falls back to DW_TAG_typedef emission
+//// for instantiation dependent type aliases.
+
+template <int>
+using A = int;
+
+template<int I>
+struct S {
+  using AA = A<I>;
+  AA aa;
+};
+
+S<0> s;
+
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "aa", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[AA:[0-9]+]], size: 32)
+// CHECK: [[AA]] = !DIDerivedType(tag: DW_TAG_typedef, name: "AA", file: ![[#]], line: [[#]], baseType: ![[A:[0-9]+]])
+// CHECK: [[A]] = !DIDerivedType(tag: DW_TAG_typedef, name: "A<I>", file: ![[#]], line: [[#]], baseType: ![[int:[0-9]+]])
+// CHECK: [[int]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

@OCHyams OCHyams merged commit 87ec4ab into llvm:main Apr 25, 2024
@dwblaikie
Copy link
Collaborator

Comment in the code should probably mention this as a FIXME and include a reference to the issue?

Also, there's another bug here - the DW_TAG_typedef is in the CU scope, instead of the struct scope. But if the struct is a non-template, the typedef is in the struct scope as it should be, not the CU scope...

@OCHyams
Copy link
Contributor Author

OCHyams commented Apr 30, 2024

Comment in the code should probably mention this as a FIXME and include a reference to the issue?

Sure, added in f78949a

Also, there's another bug here - the DW_TAG_typedef is in the CU scope, instead of the struct scope. But if the struct is a non-template, the typedef is in the struct scope as it should be, not the CU scope...

That does looks odd - I can reproduce it with normal (language-level) typedefs too (rather than with template aliases): https://godbolt.org/z/GsGKqhKzz. I can open a separate issue?

Now that I think about it, I recall @CarlosAlbertoEnciso running into something similar a while ago... I'm sure a bug was filed about something similar but I can't find it. Does this ring any bells @CarlosAlbertoEnciso?

@OCHyams OCHyams deleted the template-alias-crash-workaround branch April 30, 2024 08:33
@dwblaikie
Copy link
Collaborator

Comment in the code should probably mention this as a FIXME and include a reference to the issue?

Sure, added in f78949a

Thanks!

Also, there's another bug here - the DW_TAG_typedef is in the CU scope, instead of the struct scope. But if the struct is a non-template, the typedef is in the struct scope as it should be, not the CU scope...

That does looks odd - I can reproduce it with normal (language-level) typedefs too (rather than with template aliases): https://godbolt.org/z/GsGKqhKzz. I can open a separate issue?

Yep!

@OCHyams
Copy link
Contributor Author

OCHyams commented May 8, 2024

Here's that issue - #91451.

Carlos pointed me to bz44884 (#44229) which may be related

mizvekov added a commit that referenced this pull request Jun 8, 2025
The dependency from the type sugar of the underlying type of a
Typedef were not being considered for the dependency of the TypedefType
itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute
to the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have
performance consequences, as otherwise non-dependent typedef
declarations would need to be transformed during instantiation as well.

This removes the workaround added in #90032

Fixes #89774
mizvekov added a commit that referenced this pull request Jun 8, 2025
The dependency from the type sugar of the underlying type of a
Typedef were not being considered for the dependency of the TypedefType
itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute
to the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have
performance consequences, as otherwise non-dependent typedef
declarations would need to be transformed during instantiation as well.

This removes the workaround added in #90032

Fixes #89774
mizvekov added a commit that referenced this pull request Jun 8, 2025
The dependency from the type sugar of the underlying type of a Typedef
were not being considered for the dependency of the TypedefType itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute to
the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have performance
consequences, as otherwise non-dependent typedef declarations would need
to be transformed during instantiation as well.

This removes the workaround added in
#90032

Fixes #89774
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 8, 2025
…#143291)

The dependency from the type sugar of the underlying type of a Typedef
were not being considered for the dependency of the TypedefType itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute to
the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have performance
consequences, as otherwise non-dependent typedef declarations would need
to be transformed during instantiation as well.

This removes the workaround added in
llvm/llvm-project#90032

Fixes llvm/llvm-project#89774
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
The dependency from the type sugar of the underlying type of a Typedef
were not being considered for the dependency of the TypedefType itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute to
the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have performance
consequences, as otherwise non-dependent typedef declarations would need
to be transformed during instantiation as well.

This removes the workaround added in
llvm#90032

Fixes llvm#89774
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
The dependency from the type sugar of the underlying type of a Typedef
were not being considered for the dependency of the TypedefType itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute to
the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have performance
consequences, as otherwise non-dependent typedef declarations would need
to be transformed during instantiation as well.

This removes the workaround added in
llvm#90032

Fixes llvm#89774
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
The dependency from the type sugar of the underlying type of a Typedef
were not being considered for the dependency of the TypedefType itself.

A TypedefType should be instantiation dependent if it involves
non-instantiated template parameters, even if they don't contribute to
the canonical type.

Besides, a TypedefType should be instantiation dependent if it is
declared in a dependent context, but fixing that would have performance
consequences, as otherwise non-dependent typedef declarations would need
to be transformed during instantiation as well.

This removes the workaround added in
llvm#90032

Fixes llvm#89774
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category debuginfo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants