androidmk: Update LOCAL_SANITIZE* support

Change-Id: Ib3d5473869f69e9e3a74ebb403653e5918ad240a
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index d26808b..eb89f19 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -48,8 +48,7 @@
 	"LOCAL_LDLIBS":                  {"host_ldlibs", bpparser.List},
 	"LOCAL_CLANG_CFLAGS":            {"clang_cflags", bpparser.List},
 	"LOCAL_YACCFLAGS":               {"yaccflags", bpparser.List},
-	"LOCAL_SANITIZE":                {"sanitize", bpparser.List},
-	"LOCAL_SANITIZE_RECOVER":        {"sanitize_recover", bpparser.List},
+	"LOCAL_SANITIZE_RECOVER":        {"sanitize.recover", bpparser.List},
 	"LOCAL_LOGTAGS_FILES":           {"logtags", bpparser.List},
 
 	"LOCAL_JAVA_RESOURCE_DIRS":    {"java_resource_dirs", bpparser.List},
@@ -83,6 +82,7 @@
 	"LOCAL_MODULE_STEM":           {stem},
 	"LOCAL_MODULE_HOST_OS":        {hostOs},
 	"LOCAL_SRC_FILES":             {srcFiles},
+	"LOCAL_SANITIZE":              {sanitize},
 }
 
 type listSplitFunc func(bpparser.Value) (string, *bpparser.Value, error)
@@ -366,6 +366,62 @@
 	return nil
 }
 
+func sanitize(file *bpFile, prefix string, mkvalue *mkparser.MakeString, appendVariable bool) error {
+	val, err := makeVariableToBlueprint(file, mkvalue, bpparser.List)
+	if err != nil {
+		return err
+	}
+
+	lists, err := splitBpList(val, func(value bpparser.Value) (string, *bpparser.Value, error) {
+		if value.Variable != "" {
+			return "vars", &value, nil
+		}
+
+		if value.Expression != nil {
+			file.errorf(mkvalue, "unknown sanitize expression")
+			return "unknown", &value, nil
+		}
+
+		switch value.StringValue {
+		case "never", "address", "coverage", "integer", "thread", "undefined":
+			bpTrue := bpparser.Value{
+				Type:      bpparser.Bool,
+				BoolValue: true,
+			}
+			return value.StringValue, &bpTrue, nil
+		default:
+			file.errorf(mkvalue, "unknown sanitize argument: %s", value.StringValue)
+			return "unknown", &value, nil
+		}
+	})
+	if err != nil {
+		return err
+	}
+
+	for k, v := range lists {
+		if emptyList(v) {
+			continue
+		}
+
+		switch k {
+		case "never", "address", "coverage", "integer", "thread", "undefined":
+			err = setVariable(file, false, prefix, "sanitize."+k, &lists[k].ListValue[0], true)
+		case "unknown":
+			// Nothing, we already added the error above
+		case "vars":
+			fallthrough
+		default:
+			err = setVariable(file, true, prefix, "sanitize", v, true)
+		}
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return err
+}
+
 var deleteProperties = map[string]struct{}{
 	"LOCAL_CPP_EXTENSION": struct{}{},
 }
diff --git a/androidmk/cmd/androidmk/test.go b/androidmk/cmd/androidmk/test.go
index 965da2b..579578e 100644
--- a/androidmk/cmd/androidmk/test.go
+++ b/androidmk/cmd/androidmk/test.go
@@ -267,6 +267,70 @@
 }
 `,
 	},
+	{
+		desc: "LOCAL_SANITIZE := never",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_SANITIZE := never
+include $(BUILD_SHARED_LIBRARY)
+`,
+		expected: `
+cc_library_shared {
+    sanitize: {
+        never: true,
+    },
+}
+`,
+	},
+	{
+		desc: "LOCAL_SANITIZE unknown parameter",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_SANITIZE := integer asdf
+LOCAL_SANITIZE_RECOVER := qwert
+include $(BUILD_SHARED_LIBRARY)
+`,
+		expected: `
+cc_library_shared {
+    // ANDROIDMK TRANSLATION ERROR: unknown sanitize argument: asdf
+    // integer asdf
+    sanitize: {
+	integer: true,
+	recover: ["qwert"],
+    },
+}
+`,
+	},
+	{
+		desc: "LOCAL_SANITIZE using variable",
+		in: `
+sanitize_var := never
+include $(CLEAR_VARS)
+LOCAL_SANITIZE := $(sanitize_var)
+include $(BUILD_SHARED_LIBRARY)
+`,
+		expected: `
+sanitize_var = ["never"]
+cc_library_shared {
+    sanitize: sanitize_var,
+}
+`,
+	},
+	{
+		desc: "LOCAL_SANITIZE_RECOVER",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_SANITIZE_RECOVER := shift-exponent
+include $(BUILD_SHARED_LIBRARY)
+`,
+		expected: `
+cc_library_shared {
+    sanitize: {
+	recover: ["shift-exponent"],
+    },
+}
+`,
+	},
 }
 
 func reformatBlueprint(input string) string {