[clang] [Clang][Sema] fix crash in codegen stage when an lambda expression declared in an unevaluated context (PR #80802)
Qizhi Hu via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 6 17:52:56 PST 2024
================
@@ -1613,8 +1613,8 @@ namespace {
bool TemplateInstantiator::AlreadyTransformed(QualType T) {
if (T.isNull())
return true;
-
- if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
+ if (T->isInstantiationDependentType() || T->isVariablyModifiedType() ||
+ (SemaRef.getLangOpts().CPlusPlus20 && T->isDecltypeType()))
----------------
jcsxky wrote:
@cor3ntin I use this test case locally:
```cpp
A<double>::Func<long long> f{};
```
AST looks like:
```cpp
Breakpoint 42, clang::DecltypeType::DecltypeType (this=0x39d190, E=0x39cfd0, underlyingType=..., can=...) at /home/huqizhi/Downloads/llvm-project/clang/lib/AST/Type.cpp:3797
3797 E(E), UnderlyingType(underlyingType) {}
(gdb-ChatDBG) p E->dumpColor()
CXXBindTemporaryExpr 0x39cfd0 'class A<double>::(lambda at /home/huqizhi/K.cpp:18:27)' (CXXTemporary 0x39cfd0)
`-LambdaExpr 0x39cfa0 'class A<double>::(lambda at /home/huqizhi/K.cpp:18:27)'
|-CXXRecordDecl 0x39ca60 implicit class definition
| |-DefinitionData lambda pass_in_registers empty standard_layout trivially_copyable trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveConstructor exists simple trivial needs_implicit
| | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial constexpr
| |-CXXMethodDecl 0x39cbc8 constexpr operator() 'auto (void) const -> auto' implicit_instantiation inline instantiated_from 0x37cc18
| | `-CompoundStmt 0x39cd58
| | `-ReturnStmt 0x39cd48
| | `-CXXUnresolvedConstructExpr 0x39cd08 'U' 'U' list
| | `-InitListExpr 0x39ccc8 'void'
| |-CXXConversionDecl 0x39cdf0 implicit constexpr operator auto (*)() 'auto (*(void) const noexcept)(void) -> auto' inline
| |-CXXMethodDecl 0x39ceb0 implicit __invoke 'auto (void) -> auto' static inline
| `-CXXDestructorDecl 0x39cff8 implicit referenced constexpr ~(lambda at /home/huqizhi/K.cpp:18:27) 'void (void) noexcept' inline default trivial
`-CompoundStmt 0x39cd58
`-ReturnStmt 0x39cd48
`-CXXUnresolvedConstructExpr 0x39cd08 'U' 'U' list
`-InitListExpr 0x39ccc8 'void'
```
`CXXBindTemporaryExpr` and `LambdaExpr` both are not `InstantiationDependentType`
```cpp
(gdb-ChatDBG) p E->isInstantiationDependent()
$306 = false
(gdb-ChatDBG) p ((CXXBindTemporaryExpr*)E)->getSubExpr()->isInstantiationDependent()
$308 = false
```
This is because type of the lambda is not `InstantiationDependentType`:
```cpp
(gdb-ChatDBG) p ((LambdaExpr*)(((CXXBindTemporaryExpr*)E)->getSubExpr()))->getType().dump()
RecordType 0x39cba0 'class A<double>::(lambda at /home/huqizhi/K.cpp:18:27)'
`-CXXRecord 0x39ca60 ''
$312 = void
```
I think retransforming all the` decltype` should be right because retransforming should not change the result. But, this may involve some efficiency problem.
Since `CXXUnresolvedConstructExpr` in the lambda expression is `InstantiationDependentType`, Maybe visiting the lambda expression and checking whether it has `InstantiationDependentType` child is a better approach (I think, but more complex).
https://github.com/llvm/llvm-project/pull/80802
More information about the cfe-commits
mailing list