Add whitelisting support for function-based split transition

- Add an attribute property to indicate whether an attribute contains
  a function-based split transition.  This is currently unused but
  will be used in a future CL where we implement function-based split
  transition.

- Add a field/accessor functions in RuleClass that indicates whether a
  rule class has a function transition whitelist.

- Add code in SkylarkRuleClassFunctions to set the function transition
  whitelist field in RuleClass when constructing a skylark rule class.

- Add checks for proper use of function-based split transition and its
  whitelist:

  - The whitelist has the expected name.

  - If a rule has any attribute that has a function-based split
    transition, it must have the _whitelist_function_transition
    attribute.

  - If a rule has the _whitelist_function_transition attribute, it
    must have an attribute that has a function-based split transition.

  - A configured target from a rule that uses a function-based split
    transition is on the whitelist.

PiperOrigin-RevId: 213070838
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index 91a26c2..ef6496c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -248,6 +248,11 @@
      * Whether we should use output_licenses to check the licences on this attribute.
      */
     OUTPUT_LICENSES,
+
+    /**
+     * Has a function-based split transition.
+     */
+    HAS_FUNCTION_TRANSITION,
   }
 
   // TODO(bazel-team): modify this interface to extend Predicate and have an extra error
@@ -593,6 +598,14 @@
     }
 
     /**
+     * Indicate the attribute uses function-based split transition.
+     */
+    public Builder<TYPE> hasFunctionTransition() {
+      return setPropertyFlag(PropertyFlag.HAS_FUNCTION_TRANSITION,
+          "function-based split transition");
+    }
+
+    /**
      * Defines the configuration transition for this attribute.
      */
     public Builder<TYPE> cfg(SplitTransitionProvider splitTransitionProvider) {
@@ -1973,6 +1986,19 @@
           "a late bound default value using the host configuration must use the host transition");
     }
 
+    if (name.equals(FunctionSplitTransitionWhitelist.WHITELIST_ATTRIBUTE_NAME)) {
+      Preconditions.checkArgument(
+          BuildType.isLabelType(type),
+          "_whitelist_function_transition attribute must be a label");
+      Preconditions.checkArgument(
+          defaultValue != null,
+          "_whitelist_function_transition attribute must have a default value");
+      Preconditions.checkArgument(
+          ((Label) defaultValue).equals(FunctionSplitTransitionWhitelist.WHITELIST_LABEL),
+          "_whitelist_function_transition attribute does not have the expected value "
+          + FunctionSplitTransitionWhitelist.WHITELIST_LABEL);
+    }
+
     this.name = name;
     this.type = type;
     this.propertyFlags = propertyFlags;
@@ -2084,6 +2110,14 @@
   }
 
   /**
+   * Returns true if this attribute uses a function-based split transition provider.  See
+   * {@link FunctionSplitTransitionProvider}.
+   */
+  public boolean hasFunctionTransition() {
+    return getPropertyFlag(PropertyFlag.HAS_FUNCTION_TRANSITION);
+  }
+
+  /**
    * Returns the configuration transition for this attribute for label or label
    * list attributes. For other attributes it will always return {@code NONE}.
    */