Replace API level codename with number

This CL fixes a bug when Soong pass `-target` with a non-digit suffix in Clang. As mentioned in b/236753843, Clang's version parsing expects to see an integer in the target string so it ignores the
S suffix.

Test: m gwp_asan_crash_handler && make sure -target is aarch64-linux-androidS instead of aarch64-linux-android31
Test: go test -run ^TestNonDigitMinSdkVersionInClangTriple$ android/soong/cc
Bug: 236753843
Change-Id: I258ecc52083dbf3471d23cf310e0ad54440f1908
diff --git a/android/api_levels.go b/android/api_levels.go
index 8163894..41b338c 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -184,17 +184,9 @@
 // a core-for-system-modules.jar for the module-lib API scope.
 var LastWithoutModuleLibCoreSystemModules = uncheckedFinalApiLevel(31)
 
-// If the `raw` input is the codename of an API level has been finalized, this
-// function returns the API level number associated with that API level. If the
-// input is *not* a finalized codename, the input is returned unmodified.
-//
-// For example, at the time of writing, R has been finalized as API level 30,
-// but S is in development so it has no number assigned. For the following
-// inputs:
-//
-// * "30" -> "30"
-// * "R" -> "30"
-// * "S" -> "S"
+// ReplaceFinalizedCodenames returns the API level number associated with that API level
+// if the `raw` input is the codename of an API level has been finalized.
+// If the input is *not* a finalized codename, the input is returned unmodified.
 func ReplaceFinalizedCodenames(config Config, raw string) string {
 	num, ok := getFinalCodenamesMap(config)[raw]
 	if !ok {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 38f6383..9430434 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3722,6 +3722,25 @@
 	android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
 }
 
+func TestNonDigitMinSdkVersionInClangTriple(t *testing.T) {
+	bp := `
+		cc_library_shared {
+			name: "libfoo",
+			srcs: ["foo.c"],
+			min_sdk_version: "S",
+		}
+	`
+	result := android.GroupFixturePreparers(
+		prepareForCcTest,
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Platform_version_active_codenames = []string{"UpsideDownCake", "Tiramisu"}
+		}),
+	).RunTestWithBp(t, bp)
+	ctx := result.TestContext
+	cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+	android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android31")
+}
+
 func TestIncludeDirsExporting(t *testing.T) {
 
 	// Trim spaces from the beginning, end and immediately after any newline characters. Leaves
diff --git a/cc/compiler.go b/cc/compiler.go
index cd1d92c..72797eb 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -457,7 +457,8 @@
 		if version == "" || version == "current" {
 			target += strconv.Itoa(android.FutureApiLevelInt)
 		} else {
-			target += version
+			apiLevel := nativeApiLevelOrPanic(ctx, version)
+			target += apiLevel.String()
 		}
 	}