[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