llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
25.9k stars 10.57k forks source link

[Clang] -gtemplate-alias assertion failure '!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' #89774

Open OCHyams opened 2 weeks ago

OCHyams commented 2 weeks ago

87623 adds an option -gtemplate-alias which tells Clang to emit type metadata that can be used to build DW_TAG_template_alias DWARF DIEs instead of DW_TAG_typedefs for template aliases. In order to do this we need to create DIType *s for all the template arguments.

This case causes an assertion:

template <int>
using A = int;

template<int I>
struct S {
  using AA = A<I>;
  AA aa;
};

S<0> s;
clang/lib/AST/ExprConstant.cpp:15722: bool clang::Expr::EvaluateAsRValue(clang::Expr::EvalResult&, const clang::ASTContext&, bool) const: Assertion '!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' failed

Remove -Xclang -dump-ast from this Godbolt example to see the assertion: https://godbolt.org/z/dPEcbneba

The TemplateSpecializationType passed to CGDebugInfo::CreateType for S<0>::AA's underlying type A<I> looks like this:

TemplateSpecializationType 0x55911729f2a0 'A<I>' sugar instantiation_dependent alias A
|-TemplateArgument expr
| `-DeclRefExpr 0x55911729f280 'int' NonTypeTemplateParm 0x55911729ee18 'I' 'int'
`-BuiltinType 0x55911724ea30 'int'

I'm trying to fix the issue, but I'm not particularly familiar with the front end or Clang AST.

Is it possible to resolve the dependent expression I in A<I> to 0? S has been instantiated, so it feels like we should have that information available, but I'm not sure where it exists in the AST.

If anyone is able to point me in the right direction or at some documentation that would be greatly appreciated.

llvmbot commented 2 weeks ago

@llvm/issue-subscribers-debuginfo

Author: Orlando Cazalet-Hyams (OCHyams)

#87623 adds an option `-gtemplate-alias` which tells Clang to emit type metadata that can be used to build DW_TAG_template_alias DWARF DIEs instead of DW_TAG_typedefs for template aliases. In order to do this we need to create `DIType *`s for all the template arguments. This case causes an assertion: ``` template <int> using A = int; template<int I> struct S { using AA = A<I>; AA aa; }; S<0> s; ``` `clang/lib/AST/ExprConstant.cpp:15722: bool clang::Expr::EvaluateAsRValue(clang::Expr::EvalResult&, const clang::ASTContext&, bool) const: Assertion '!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' failed` Remove -Xclang -dump-ast from this godbolt example to see the assertion: https://godbolt.org/z/dPEcbneba The `TemplateSpecializationType` passed to `CGDebugInfo::CreateType` for `S<0>::AA`'s underlying type `A<I>` looks like this: ``` TemplateSpecializationType 0x55911729f2a0 'A<I>' sugar instantiation_dependent alias A |-TemplateArgument expr | `-DeclRefExpr 0x55911729f280 'int' NonTypeTemplateParm 0x55911729ee18 'I' 'int' `-BuiltinType 0x55911724ea30 'int' ``` I'm trying to fix the issue, but I'm not particularly familiar with the front end or Clang AST. Is it possible to resolve the dependent expression `I` in `A<I>` to `0`? `S` has been instantiated, so it feels like we should have that information available, but I'm not sure where it exists in the AST. If anyone is able to point me in the right direction or at some documentation that would be greatly appreciated.
OCHyams commented 2 weeks ago

Sorry - I added some "assignees" accidentally (I assumed the box was the same as the pull request "reviewers" one - I wasn't trying to assign this task to anyone).

Michael137 commented 2 weeks ago

@AaronBallman Any idea how, given a TypeAliasTemplateDecl, we might be able to get to the template arguments that the type alias was instantiated with? It looks like all the template arguments are uninstantiated (i.e., dependent on other parameters.

AaronBallman commented 2 weeks ago

The TypeAliasTemplateDecl is the uninstantiated template; it becomes a TypeAliasDecl once it is instantiated. So I think you'd need to look at the ClassTemplateSpecializationDecl for S<0> and that should have a TypeAliasDecl that references A<0>.

OCHyams commented 2 weeks ago

Thank you for your help - I'll look into this shortly. I have a work-around here #90032 to avoid the assertion failure for the time being.

llvmbot commented 2 weeks ago

@llvm/issue-subscribers-clang-codegen

Author: Orlando Cazalet-Hyams (OCHyams)

#87623 adds an option `-gtemplate-alias` which tells Clang to emit type metadata that can be used to build `DW_TAG_template_alias` DWARF DIEs instead of `DW_TAG_typedefs` for template aliases. In order to do this we need to create `DIType *`s for all the template arguments. This case causes an assertion: ```cpp template <int> using A = int; template<int I> struct S { using AA = A<I>; AA aa; }; S<0> s; ``` ```console clang/lib/AST/ExprConstant.cpp:15722: bool clang::Expr::EvaluateAsRValue(clang::Expr::EvalResult&, const clang::ASTContext&, bool) const: Assertion '!isValueDependent() && "Expression evaluator can't be called on a dependent expression."' failed ``` Remove `-Xclang -dump-ast` from this Godbolt example to see the assertion: https://godbolt.org/z/dPEcbneba The `TemplateSpecializationType` passed to `CGDebugInfo::CreateType` for `S<0>::AA`'s underlying type `A<I>` looks like this: ```console TemplateSpecializationType 0x55911729f2a0 'A<I>' sugar instantiation_dependent alias A |-TemplateArgument expr | `-DeclRefExpr 0x55911729f280 'int' NonTypeTemplateParm 0x55911729ee18 'I' 'int' `-BuiltinType 0x55911724ea30 'int' ``` I'm trying to fix the issue, but I'm not particularly familiar with the front end or Clang AST. Is it possible to resolve the dependent expression `I` in `A<I>` to `0`? `S` has been instantiated, so it feels like we should have that information available, but I'm not sure where it exists in the AST. If anyone is able to point me in the right direction or at some documentation that would be greatly appreciated.