From 13b6f31548784452990da6dba555af8d7a061958 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 15 Feb 2022 17:55:35 -0800 Subject: [PATCH] Fix crash when deserializing a lambda expression in a decltype. --- clang/lib/AST/StmtProfile.cpp | 12 ++++++++++-- clang/test/PCH/cxx20-unevaluated-lambda.cpp | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 clang/test/PCH/cxx20-unevaluated-lambda.cpp diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 09853e0f0e49..b590f4a00263 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -38,6 +38,10 @@ namespace { void VisitStmt(const Stmt *S); + void VisitStmtNoChildren(const Stmt *S) { + HandleStmtClass(S->getStmtClass()); + } + virtual void HandleStmtClass(Stmt::StmtClass SC) = 0; #define STMT(Node, Base) void Visit##Node(const Node *S); @@ -218,7 +222,7 @@ namespace { void StmtProfiler::VisitStmt(const Stmt *S) { assert(S && "Requires non-null Stmt pointer"); - HandleStmtClass(S->getStmtClass()); + VisitStmtNoChildren(S); for (const Stmt *SubStmt : S->children()) { if (SubStmt) @@ -1945,7 +1949,11 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { void StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) { - VisitExpr(S); + // Do not recursively visit the children of this expression. Profiling the + // body would result in unnecessary work, and is not safe to do during + // deserialization. + VisitStmtNoChildren(S); + // C++20 [temp.over.link]p5: // Two lambda-expressions are never considered equivalent. VisitDecl(S->getLambdaClass()); diff --git a/clang/test/PCH/cxx20-unevaluated-lambda.cpp b/clang/test/PCH/cxx20-unevaluated-lambda.cpp new file mode 100644 index 000000000000..29af5e61c330 --- /dev/null +++ b/clang/test/PCH/cxx20-unevaluated-lambda.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++20 -include %s %s -o %t + +// RUN: %clang_cc1 -std=c++20 -emit-pch %s -o %t +// RUN: %clang_cc1 -std=c++20 -include-pch %t -verify %s + +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +template auto f() -> decltype([]{ return T(42); }); + +#else /*included pch*/ + +static_assert(decltype(f())()() == 42); + +#endif // HEADER