Switch to C++20 for CMake builds

Capture `this` explicitly in lambdas. Implicitly capturing `this` is
deprecated in C++20.

Change-Id: Id700049da26f85c20ad37ed32628b0d83cec7833
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/139260
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 449f1ae..a191271 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,7 +32,7 @@
 
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
 set(CMAKE_DEBUG_POSTFIX "")
 
 if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
@@ -450,7 +450,6 @@
     target_compile_definitions(dawn_internal_config INTERFACE "NOMINMAX" "WIN32_LEAN_AND_MEAN")
 endif()
 
-set(CMAKE_CXX_STANDARD "17")
 
 ################################################################################
 # Tint
diff --git a/src/dawn/node/CMakeLists.txt b/src/dawn/node/CMakeLists.txt
index 18edfa1..c81f07d 100644
--- a/src/dawn/node/CMakeLists.txt
+++ b/src/dawn/node/CMakeLists.txt
@@ -69,7 +69,7 @@
     ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}"
     RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}"
     LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}"
-    CXX_STANDARD 17
+    CXX_STANDARD 20
 )
 target_link_libraries(dawn_node dawn_node_binding dawn_node_interop dawn_native dawncpp dawn_proc
                       libtint)
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 44b24e1..c473d2c 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -1050,7 +1050,7 @@
 }
 
 auto Eval::SqrtFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto v) -> Eval::Result {
+    return [=, this](auto v) -> Eval::Result {
         if (auto r = Sqrt(source, v)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1072,7 +1072,7 @@
 }
 
 auto Eval::ClampFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto e, auto low, auto high) -> Eval::Result {
+    return [=, this](auto e, auto low, auto high) -> Eval::Result {
         if (auto r = Clamp(source, e, low, high)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1081,7 +1081,7 @@
 }
 
 auto Eval::AddFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2) -> Eval::Result {
+    return [=, this](auto a1, auto a2) -> Eval::Result {
         if (auto r = Add(source, a1, a2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1090,7 +1090,7 @@
 }
 
 auto Eval::SubFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2) -> Eval::Result {
+    return [=, this](auto a1, auto a2) -> Eval::Result {
         if (auto r = Sub(source, a1, a2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1099,7 +1099,7 @@
 }
 
 auto Eval::MulFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2) -> Eval::Result {
+    return [=, this](auto a1, auto a2) -> Eval::Result {
         if (auto r = Mul(source, a1, a2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1108,7 +1108,7 @@
 }
 
 auto Eval::DivFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2) -> Eval::Result {
+    return [=, this](auto a1, auto a2) -> Eval::Result {
         if (auto r = Div(source, a1, a2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1117,7 +1117,7 @@
 }
 
 auto Eval::ModFunc(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2) -> Eval::Result {
+    return [=, this](auto a1, auto a2) -> Eval::Result {
         if (auto r = Mod(source, a1, a2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1126,7 +1126,7 @@
 }
 
 auto Eval::Dot2Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2, auto b1, auto b2) -> Eval::Result {
+    return [=, this](auto a1, auto a2, auto b1, auto b2) -> Eval::Result {
         if (auto r = Dot2(source, a1, a2, b1, b2)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1135,7 +1135,7 @@
 }
 
 auto Eval::Dot3Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2, auto a3, auto b1, auto b2, auto b3) -> Eval::Result {
+    return [=, this](auto a1, auto a2, auto a3, auto b1, auto b2, auto b3) -> Eval::Result {
         if (auto r = Dot3(source, a1, a2, a3, b1, b2, b3)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1144,8 +1144,8 @@
 }
 
 auto Eval::Dot4Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a1, auto a2, auto a3, auto a4, auto b1, auto b2, auto b3,
-               auto b4) -> Eval::Result {
+    return [=, this](auto a1, auto a2, auto a3, auto a4, auto b1, auto b2, auto b3,
+                     auto b4) -> Eval::Result {
         if (auto r = Dot4(source, a1, a2, a3, a4, b1, b2, b3, b4)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1218,7 +1218,7 @@
 }
 
 auto Eval::Det2Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a, auto b, auto c, auto d) -> Eval::Result {
+    return [=, this](auto a, auto b, auto c, auto d) -> Eval::Result {
         if (auto r = Det2(source, a, b, c, d)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1227,8 +1227,8 @@
 }
 
 auto Eval::Det3Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h,
-               auto i) -> Eval::Result {
+    return [=, this](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h,
+                     auto i) -> Eval::Result {
         if (auto r = Det3(source, a, b, c, d, e, f, g, h, i)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
@@ -1237,8 +1237,8 @@
 }
 
 auto Eval::Det4Func(const Source& source, const core::type::Type* elem_ty) {
-    return [=](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, auto i, auto j,
-               auto k, auto l, auto m, auto n, auto o, auto p) -> Eval::Result {
+    return [=, this](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, auto i, auto j,
+                     auto k, auto l, auto m, auto n, auto o, auto p) -> Eval::Result {
         if (auto r = Det4(source, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)) {
             return CreateScalar(source, elem_ty, r.Get());
         }
diff --git a/src/tint/lang/spirv/reader/ast_parser/function.cc b/src/tint/lang/spirv/reader/ast_parser/function.cc
index cf41b48..499f65e 100644
--- a/src/tint/lang/spirv/reader/ast_parser/function.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/function.cc
@@ -873,7 +873,7 @@
     auto* cond = builder_.Expr(Source{}, guard_name);
     auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
 
-    PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
+    PushNewStatementBlock(top.GetConstruct(), end_id, [=, this](const StatementList& stmts) {
         builder->body = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
     });
 }
@@ -885,7 +885,7 @@
     auto* cond = MakeTrue(Source{});
     auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
 
-    PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
+    PushNewStatementBlock(top.GetConstruct(), end_id, [=, this](const StatementList& stmts) {
         builder->body = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
     });
 }
@@ -2902,7 +2902,7 @@
     // But make sure we do it in the right order.
     auto push_else = [this, builder, else_end, construct, false_is_break, false_is_continue] {
         // Push the else clause onto the stack first.
-        PushNewStatementBlock(construct, else_end, [=](const StatementList& stmts) {
+        PushNewStatementBlock(construct, else_end, [=, this](const StatementList& stmts) {
             // Only set the else-clause if there are statements to fill it.
             if (!stmts.IsEmpty()) {
                 // The "else" consists of the statement list from the top of
@@ -2953,7 +2953,7 @@
         }
 
         // Push the then clause onto the stack.
-        PushNewStatementBlock(construct, then_end, [=](const StatementList& stmts) {
+        PushNewStatementBlock(construct, then_end, [=, this](const StatementList& stmts) {
             builder->body = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
         });
         if (true_is_break) {
@@ -3066,7 +3066,7 @@
         // for the case, and fill the case clause once the block is generated.
         auto case_idx = swch->cases.Length();
         swch->cases.Push(nullptr);
-        PushNewStatementBlock(construct, end_id, [=](const StatementList& stmts) {
+        PushNewStatementBlock(construct, end_id, [=, this](const StatementList& stmts) {
             auto* body = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
             swch->cases[case_idx] = create<ast::CaseStatement>(Source{}, selectors, body);
         });
@@ -3081,7 +3081,7 @@
 
 bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
     auto* builder = AddStatementBuilder<LoopStatementBuilder>();
-    PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
+    PushNewStatementBlock(construct, construct->end_id, [=, this](const StatementList& stmts) {
         builder->body = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
     });
     return success();
@@ -3096,7 +3096,7 @@
         return Fail() << "internal error: starting continue construct, "
                          "expected loop on top of stack";
     }
-    PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
+    PushNewStatementBlock(construct, construct->end_id, [=, this](const StatementList& stmts) {
         loop->continuing = create<ast::BlockStatement>(Source{}, stmts, tint::Empty);
     });
 
diff --git a/src/tint/lang/spirv/writer/ast_printer/builder.cc b/src/tint/lang/spirv/writer/ast_printer/builder.cc
index 7b0afae..f6ba46e 100644
--- a/src/tint/lang/spirv/writer/ast_printer/builder.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/builder.cc
@@ -2656,7 +2656,7 @@
             auto* f32 = builder_.create<core::type::F32>();
             auto* spirv_result_type = builder_.create<core::type::Vector>(f32, 4u);
             auto spirv_result = result_op();
-            post_emission = [=] {
+            post_emission = [=, this] {
                 return push_function_inst(spv::Op::OpCompositeExtract,
                                           {result_type, result_id, spirv_result, Operand(0u)});
             };
@@ -2687,7 +2687,7 @@
             auto* spirv_result_type =
                 builder_.create<core::type::Vector>(element_type, spirv_result_width);
             if (swizzle.size() > 1) {
-                post_emission = [=] {
+                post_emission = [=, this] {
                     OperandList operands{
                         result_type,
                         result_id,
@@ -2700,7 +2700,7 @@
                     return push_function_inst(spv::Op::OpVectorShuffle, operands);
                 };
             } else {
-                post_emission = [=] {
+                post_emission = [=, this] {
                     return push_function_inst(
                         spv::Op::OpCompositeExtract,
                         {result_type, result_id, spirv_result, Operand(swizzle[0])});
diff --git a/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc b/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
index 30dbbb7..c5a375f 100644
--- a/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
+++ b/src/tint/lang/wgsl/ast/transform/direct_variable_access.cc
@@ -541,7 +541,7 @@
 
             // The dynamic index needs to be hoisted (if it hasn't been already).
             auto fn = FnInfoFor(idx->Stmt()->Function());
-            fn->hoisted_exprs.GetOrCreate(idx, [=] {
+            fn->hoisted_exprs.GetOrCreate(idx, [=, this] {
                 // Create a name for the new 'let'
                 auto name = b.Symbols().New("ptr_index_save");
                 // Insert a new 'let' just above the dynamic index statement.
diff --git a/src/tint/lang/wgsl/ast/transform/spirv_atomic.cc b/src/tint/lang/wgsl/ast/transform/spirv_atomic.cc
index 4074bac..3ab254f 100644
--- a/src/tint/lang/wgsl/ast/transform/spirv_atomic.cc
+++ b/src/tint/lang/wgsl/ast/transform/spirv_atomic.cc
@@ -256,7 +256,7 @@
                     [&](const AssignmentStatement* assign) {
                         auto* sem_lhs = ctx.src->Sem().GetVal(assign->lhs);
                         if (is_ref_to_atomic_var(sem_lhs)) {
-                            ctx.Replace(assign, [=] {
+                            ctx.Replace(assign, [=, this] {
                                 auto* lhs = ctx.CloneWithoutTransform(assign->lhs);
                                 auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
                                 auto* call = b.Call(core::str(core::Function::kAtomicStore),
@@ -268,7 +268,7 @@
 
                         auto sem_rhs = ctx.src->Sem().GetVal(assign->rhs);
                         if (is_ref_to_atomic_var(sem_rhs->UnwrapLoad())) {
-                            ctx.Replace(assign->rhs, [=] {
+                            ctx.Replace(assign->rhs, [=, this] {
                                 auto* rhs = ctx.CloneWithoutTransform(assign->rhs);
                                 return b.Call(core::str(core::Function::kAtomicLoad),
                                               b.AddressOf(rhs));
@@ -280,7 +280,7 @@
                         auto* var = decl->variable;
                         if (auto* sem_init = ctx.src->Sem().GetVal(var->initializer)) {
                             if (is_ref_to_atomic_var(sem_init->UnwrapLoad())) {
-                                ctx.Replace(var->initializer, [=] {
+                                ctx.Replace(var->initializer, [=, this] {
                                     auto* rhs = ctx.CloneWithoutTransform(var->initializer);
                                     return b.Call(core::str(core::Function::kAtomicLoad),
                                                   b.AddressOf(rhs));
diff --git a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
index a14d218..e1a2ca6 100644
--- a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
@@ -166,7 +166,7 @@
             if (auto* builtin_attr = GetAttribute<BuiltinAttribute>(param->attributes)) {
                 auto builtin = sem.Get(builtin_attr)->Value();
                 if (builtin == core::BuiltinValue::kLocalInvocationIndex) {
-                    local_index = [=] { return b.Expr(ctx.Clone(param->name->symbol)); };
+                    local_index = [=, this] { return b.Expr(ctx.Clone(param->name->symbol)); };
                     break;
                 }
             }
@@ -174,7 +174,7 @@
             if (auto* str = sem.Get(param)->Type()->As<core::type::Struct>()) {
                 for (auto* member : str->Members()) {
                     if (member->Attributes().builtin == core::BuiltinValue::kLocalInvocationIndex) {
-                        local_index = [=] {
+                        local_index = [=, this] {
                             auto* param_expr = b.Expr(ctx.Clone(param->name->symbol));
                             auto member_name = ctx.Clone(member->Name());
                             return b.MemberAccessor(param_expr, member_name);
@@ -190,7 +190,7 @@
             auto* local_invocation_index = b.Builtin(core::BuiltinValue::kLocalInvocationIndex);
             auto* param = b.Param(param_name, b.ty.u32(), tint::Vector{local_invocation_index});
             ctx.InsertBack(fn->params, param);
-            local_index = [=] { return b.Expr(param->name->symbol); };
+            local_index = [=, this] { return b.Expr(param->name->symbol); };
         }
 
         // Take the zeroing statements and bin them by the number of iterations
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 1464464..3192aa4 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -1229,38 +1229,38 @@
                     [&](const ast::BinaryExpression* e) {
                         if (e->op == core::BinaryOp::kLogicalAnd ||
                             e->op == core::BinaryOp::kLogicalOr) {
-                            tasks.Push([=] { EndShortCircuit(e); });
-                            tasks.Push([=] { Process(e->rhs); });
-                            tasks.Push([=] { BeginShortCircuit(e); });
-                            tasks.Push([=] { Process(e->lhs); });
+                            tasks.Push([=, this] { EndShortCircuit(e); });
+                            tasks.Push([=, this] { Process(e->rhs); });
+                            tasks.Push([=, this] { BeginShortCircuit(e); });
+                            tasks.Push([=, this] { Process(e->lhs); });
                         } else {
-                            tasks.Push([=] { EmitBinary(e); });
-                            tasks.Push([=] { Process(e->rhs); });
-                            tasks.Push([=] { Process(e->lhs); });
+                            tasks.Push([=, this] { EmitBinary(e); });
+                            tasks.Push([=, this] { Process(e->rhs); });
+                            tasks.Push([=, this] { Process(e->lhs); });
                         }
                     },
                     [&](const ast::IndexAccessorExpression* e) {
-                        tasks.Push([=] { EmitAccess(e); });
-                        tasks.Push([=] { Process(e->index); });
-                        tasks.Push([=] { Process(e->object); });
+                        tasks.Push([=, this] { EmitAccess(e); });
+                        tasks.Push([=, this] { Process(e->index); });
+                        tasks.Push([=, this] { Process(e->object); });
                     },
                     [&](const ast::MemberAccessorExpression* e) {
-                        tasks.Push([=] { EmitAccess(e); });
-                        tasks.Push([=] { Process(e->object); });
+                        tasks.Push([=, this] { EmitAccess(e); });
+                        tasks.Push([=, this] { Process(e->object); });
                     },
                     [&](const ast::UnaryOpExpression* e) {
-                        tasks.Push([=] { EmitUnary(e); });
-                        tasks.Push([=] { Process(e->expr); });
+                        tasks.Push([=, this] { EmitUnary(e); });
+                        tasks.Push([=, this] { Process(e->expr); });
                     },
                     [&](const ast::CallExpression* e) {
-                        tasks.Push([=] { EmitCall(e); });
+                        tasks.Push([=, this] { EmitCall(e); });
                         for (auto* arg : tint::Reverse(e->args)) {
-                            tasks.Push([=] { Process(arg); });
+                            tasks.Push([=, this] { Process(arg); });
                         }
                     },
                     [&](const ast::BitcastExpression* e) {
-                        tasks.Push([=] { EmitBitcast(e); });
-                        tasks.Push([=] { Process(e->expr); });
+                        tasks.Push([=, this] { EmitBitcast(e); });
+                        tasks.Push([=, this] { Process(e->expr); });
                     },
                     [&](const ast::LiteralExpression* e) { EmitLiteral(e); },
                     [&](const ast::IdentifierExpression* e) { EmitIdentifier(e); },