Version 2.17.4

* Cherry-pick refs/changes/32/247332/1 to stable
* Cherry-pick a801368f80f85553682816c67c9e7dc3ea90337d to stable
* Cherry-pick refs/changes/61/249161/2 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1291f6..0699684 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,14 @@
+<<<<<<< HEAD
+## 2.17.4 - 2022-06-20
+
+This is a patch release that fixes:
+
+- Improve analysis of enums and switch (issue [#49188]).
+- Fix compiler crash when initializing Finalizable objects (issue [#49075]).
+
+[#49188]: https://github.com/dart-lang/sdk/issues/49188
+[#49075]: https://github.com/dart-lang/sdk/issues/49075
+
 ## 2.17.3 - 2022-06-01
 
 This is a patch release that fixes:
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b93727e..bd4b330 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3273,7 +3273,7 @@
       var enumElement = expressionType.element;
       if (enumElement.isEnum) {
         var constantNames = enumElement.fields
-            .where((field) => field.isStatic && !field.isSynthetic)
+            .where((field) => field.isEnumConstant)
             .map((field) => field.name)
             .toSet();
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 78180a7..a0e5fa3 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3824,6 +3824,8 @@
       return expression.staticElement;
     } else if (expression is PropertyAccess) {
       return expression.propertyName.staticElement;
+    } else if (expression is SimpleIdentifier) {
+      return expression.staticElement;
     }
     return null;
   }
diff --git a/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart b/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart
index 973910e..649225f 100644
--- a/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/body_might_complete_normally_test.dart
@@ -15,6 +15,42 @@
 
 @reflectiveTest
 class BodyMayCompleteNormallyTest extends PubPackageResolutionTest {
+  test_enum_method_nonNullable_blockBody_switchStatement_notNullable_exhaustive() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  a;
+
+  static const b = 0;
+  static final c = 0;
+
+  int get value {
+    switch (this) {
+      case a:
+        return 0;
+    }
+  }
+}
+''');
+  }
+
+  test_enum_method_nonNullable_blockBody_switchStatement_notNullable_notExhaustive() async {
+    await assertErrorsInCode(r'''
+enum E {
+  a, b;
+
+  int get value {
+    switch (this) {
+      case a:
+        return 0;
+    }
+  }
+}
+''', [
+      error(CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY, 28, 5),
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 40, 13),
+    ]);
+  }
+
   test_factoryConstructor_named_blockBody() async {
     await assertErrorsInCode(r'''
 class A {
@@ -92,6 +128,24 @@
 ''');
   }
 
+  test_function_nonNullable_blockBody_switchStatement_notNullable_exhaustive_enhanced() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  a;
+
+  static const b = 0;
+  static final c = 0;
+}
+
+int f(E e) {
+  switch (e) {
+    case E.a:
+      return 0;
+  }
+}
+''');
+  }
+
   test_function_nonNullable_blockBody_switchStatement_notNullable_notExhaustive() async {
     await assertErrorsInCode(r'''
 enum Foo { a, b }
@@ -108,6 +162,26 @@
     ]);
   }
 
+  test_function_nonNullable_blockBody_switchStatement_notNullable_notExhaustive_enhanced() async {
+    await assertErrorsInCode(r'''
+enum E {
+  a, b;
+
+  static const c = 0;
+}
+
+int f(E e) {
+  switch (e) {
+    case E.a:
+      return 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY, 47, 1),
+      error(StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH, 58, 10),
+    ]);
+  }
+
   test_function_nonNullable_blockBody_switchStatement_nullable_exhaustive_default() async {
     await assertNoErrorsInCode(r'''
 enum Foo { a, b }
diff --git a/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart b/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart
index 7ea8972..dd74912 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_enum_constant_in_switch_test.dart
@@ -17,6 +17,25 @@
 @reflectiveTest
 class MissingEnumConstantInSwitchTest extends PubPackageResolutionTest
     with MissingEnumConstantInSwitchTestCases {
+  test_all_enhanced() async {
+    await assertNoErrorsInCode('''
+enum E {
+  one, two;
+
+  static const x = 0;
+}
+
+void f(E e) {
+  switch (e) {
+    case E.one:
+      break;
+    case E.two:
+      break;
+  }
+}
+''');
+  }
+
   test_nullable() async {
     await assertErrorsInCode('''
 enum E { one, two }
diff --git a/pkg/vm/lib/transformations/ffi/finalizable.dart b/pkg/vm/lib/transformations/ffi/finalizable.dart
index 84b1469..4fe96f3 100644
--- a/pkg/vm/lib/transformations/ffi/finalizable.dart
+++ b/pkg/vm/lib/transformations/ffi/finalizable.dart
@@ -220,14 +220,15 @@
 
   @override
   TreeNode visitVariableDeclaration(VariableDeclaration node) {
+    node = super.visitVariableDeclaration(node) as VariableDeclaration;
     if (_currentScope == null) {
       // Global variable.
-      return super.visitVariableDeclaration(node);
+      return node;
     }
     if (_isFinalizable(node.type)) {
       _currentScope!.addDeclaration(node);
     }
-    return super.visitVariableDeclaration(node);
+    return node;
   }
 
   @override
diff --git a/pkg/vm/testcases/transformations/ffi/regress_49075.dart b/pkg/vm/testcases/transformations/ffi/regress_49075.dart
new file mode 100644
index 0000000..0046fd8
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/regress_49075.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+Future<void> main(List<String> arguments) async {
+  // ignore: unused_local_variable
+  final myFinalizable = await MyFinalizable();
+}
+
+class MyFinalizable implements Finalizable {
+  MyFinalizable();
+}
diff --git a/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect b/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect
new file mode 100644
index 0000000..2974867
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/regress_49075.dart.expect
@@ -0,0 +1,45 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+import "dart:async" as asy;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  constructor •() → self::MyFinalizable
+    : super core::Object::•() {
+    ;
+    _in::reachabilityFence(this);
+  }
+}
+static method main(core::List<core::String> arguments) → asy::Future<void> /* futureValueType= void */ /* originally async */ {
+  final asy::_Future<void> :async_future = new asy::_Future::•<void>();
+  core::bool* :is_sync = false;
+  void :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding 
+    try {
+      #L1:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFinalizable::•(), :async_op_then, :async_op_error) in null;
+        final self::MyFinalizable myFinalizable = _in::unsafeCast<self::MyFinalizable>(:result_or_exception);
+        _in::reachabilityFence(myFinalizable);
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(null, null){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/tools/VERSION b/tools/VERSION
index a2075a5..f9aa7cc 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
 CHANNEL stable
 MAJOR 2
 MINOR 17
-PATCH 3
+PATCH 4
 PRERELEASE 0
 PRERELEASE_PATCH 0
\ No newline at end of file