Snap for 5925869 from d2a5c6d5f261a4a748c6d1b26fcd98984dcfffe1 to sdk-release

Change-Id: If3ef1ced9c641d7767f578ad4d3a5cc51d6a496f
diff --git a/.travis.yml b/.travis.yml
index c39ad38..706e469 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@
     - "1.10"
     - "1.11"
     - "1.12"
+    - "1.13"
 
 cache:
     directories:
diff --git a/Blueprints b/Blueprints
index d58169e..c3c8975 100644
--- a/Blueprints
+++ b/Blueprints
@@ -79,6 +79,7 @@
         "proptools/clone.go",
         "proptools/escape.go",
         "proptools/extend.go",
+        "proptools/filter.go",
         "proptools/proptools.go",
         "proptools/tag.go",
         "proptools/typeequal.go",
@@ -87,6 +88,7 @@
         "proptools/clone_test.go",
         "proptools/escape_test.go",
         "proptools/extend_test.go",
+        "proptools/filter_test.go",
         "proptools/tag_test.go",
         "proptools/typeequal_test.go",
     ],
diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go
index 3464c0b..1799e68 100644
--- a/bootstrap/bootstrap.go
+++ b/bootstrap/bootstrap.go
@@ -437,7 +437,7 @@
 			name, srcs, genSrcs, testSrcs)
 	}
 
-	buildGoPackage(ctx, objDir, name, archiveFile, srcs, genSrcs)
+	buildGoPackage(ctx, objDir, "main", archiveFile, srcs, genSrcs)
 
 	var linkDeps []string
 	var libDirFlags []string
diff --git a/context.go b/context.go
index 42b2df1..cedf3d8 100644
--- a/context.go
+++ b/context.go
@@ -1410,12 +1410,21 @@
 
 // findMatchingVariant searches the moduleGroup for a module with the same variant as module,
 // and returns the matching module, or nil if one is not found.
-func (c *Context) findMatchingVariant(module *moduleInfo, possible []*moduleInfo) *moduleInfo {
+func (c *Context) findMatchingVariant(module *moduleInfo, possible []*moduleInfo, reverse bool) *moduleInfo {
 	if len(possible) == 1 {
 		return possible[0]
 	} else {
+		var variantToMatch variationMap
+		if !reverse {
+			// For forward dependency, ignore local variants by matching against
+			// dependencyVariant which doesn't have the local variants
+			variantToMatch = module.dependencyVariant
+		} else {
+			// For reverse dependency, use all the variants
+			variantToMatch = module.variant
+		}
 		for _, m := range possible {
-			if m.variant.equal(module.dependencyVariant) {
+			if m.variant.equal(variantToMatch) {
 				return m
 			}
 		}
@@ -1441,7 +1450,7 @@
 		return c.discoveredMissingDependencies(module, depName)
 	}
 
-	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
+	if m := c.findMatchingVariant(module, possibleDeps, false); m != nil {
 		module.newDirectDeps = append(module.newDirectDeps, depInfo{m, tag})
 		atomic.AddUint32(&c.depsModified, 1)
 		return nil
@@ -1479,7 +1488,7 @@
 		}}
 	}
 
-	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
+	if m := c.findMatchingVariant(module, possibleDeps, true); m != nil {
 		return m, nil
 	}
 
diff --git a/go.mod b/go.mod
index 933cd12..fe96d45 100644
--- a/go.mod
+++ b/go.mod
@@ -1 +1,3 @@
 module github.com/google/blueprint
+
+go 1.13
diff --git a/module_ctx.go b/module_ctx.go
index bc05787..be5d974 100644
--- a/module_ctx.go
+++ b/module_ctx.go
@@ -712,7 +712,7 @@
 
 	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
 	// the specified property structs to it as if the properties were set in a blueprint file.
-	CreateModule(ModuleFactory, ...interface{})
+	CreateModule(ModuleFactory, ...interface{}) Module
 }
 
 type BottomUpMutatorContext interface {
@@ -934,7 +934,7 @@
 	mctx.rename = append(mctx.rename, rename{mctx.module.group, name})
 }
 
-func (mctx *mutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) {
+func (mctx *mutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
 	module := mctx.context.newModule(factory)
 
 	module.relBlueprintsFile = mctx.module.relBlueprintsFile
@@ -950,6 +950,8 @@
 	}
 
 	mctx.newModules = append(mctx.newModules, module)
+
+	return module.logicModule
 }
 
 // SimpleName is an embeddable object to implement the ModuleContext.Name method using a property
diff --git a/package_ctx.go b/package_ctx.go
index e0a03c8..c55152a 100644
--- a/package_ctx.go
+++ b/package_ctx.go
@@ -158,8 +158,9 @@
 	if n != 1 {
 		return "", "", false
 	}
-
-	f := runtime.FuncForPC(pc[0]).Name()
+	frames := runtime.CallersFrames(pc[:])
+	frame, _ := frames.Next()
+	f := frame.Function
 	s := pkgPathRe.FindStringSubmatch(f)
 	if len(s) < 3 {
 		panic(fmt.Errorf("failed to extract package path and function name from %q", f))
diff --git a/proptools/filter.go b/proptools/filter.go
new file mode 100644
index 0000000..7a61b02
--- /dev/null
+++ b/proptools/filter.go
@@ -0,0 +1,159 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package proptools
+
+import (
+	"reflect"
+)
+
+type FilterFieldPredicate func(field reflect.StructField, string string) (bool, reflect.StructField)
+
+func filterPropertyStructFields(fields []reflect.StructField, prefix string, predicate FilterFieldPredicate) (filteredFields []reflect.StructField, filtered bool) {
+	for _, field := range fields {
+		var keep bool
+		if keep, field = predicate(field, prefix); !keep {
+			filtered = true
+			continue
+		}
+
+		subPrefix := field.Name
+		if prefix != "" {
+			subPrefix = prefix + "." + subPrefix
+		}
+
+		// Recurse into structs
+		switch field.Type.Kind() {
+		case reflect.Struct:
+			var subFiltered bool
+			field.Type, subFiltered = filterPropertyStruct(field.Type, subPrefix, predicate)
+			filtered = filtered || subFiltered
+			if field.Type == nil {
+				continue
+			}
+		case reflect.Ptr:
+			if field.Type.Elem().Kind() == reflect.Struct {
+				nestedType, subFiltered := filterPropertyStruct(field.Type.Elem(), subPrefix, predicate)
+				filtered = filtered || subFiltered
+				if nestedType == nil {
+					continue
+				}
+				field.Type = reflect.PtrTo(nestedType)
+			}
+		case reflect.Interface:
+			panic("Interfaces are not supported in filtered property structs")
+		}
+
+		filteredFields = append(filteredFields, field)
+	}
+
+	return filteredFields, filtered
+}
+
+// FilterPropertyStruct takes a reflect.Type that is either a struct or a pointer to a struct, and returns a
+// reflect.Type that only contains the fields in the original type for which predicate returns true, and a bool
+// that is true if the new struct type has fewer fields than the original type.  If there are no fields in the
+// original type for which predicate returns true it returns nil and true.
+func FilterPropertyStruct(prop reflect.Type, predicate FilterFieldPredicate) (filteredProp reflect.Type, filtered bool) {
+	return filterPropertyStruct(prop, "", predicate)
+}
+
+func filterPropertyStruct(prop reflect.Type, prefix string, predicate FilterFieldPredicate) (filteredProp reflect.Type, filtered bool) {
+	var fields []reflect.StructField
+
+	ptr := prop.Kind() == reflect.Ptr
+	if ptr {
+		prop = prop.Elem()
+	}
+
+	for i := 0; i < prop.NumField(); i++ {
+		fields = append(fields, prop.Field(i))
+	}
+
+	filteredFields, filtered := filterPropertyStructFields(fields, prefix, predicate)
+
+	if len(filteredFields) == 0 {
+		return nil, true
+	}
+
+	if !filtered {
+		if ptr {
+			return reflect.PtrTo(prop), false
+		}
+		return prop, false
+	}
+
+	ret := reflect.StructOf(filteredFields)
+	if ptr {
+		ret = reflect.PtrTo(ret)
+	}
+
+	return ret, true
+}
+
+// FilterPropertyStructSharded takes a reflect.Type that is either a sturct or a pointer to a struct, and returns a list
+// of reflect.Type that only contains the fields in the original type for which predicate returns true, and a bool that
+// is true if the new struct type has fewer fields than the original type.  If there are no fields in the original type
+// for which predicate returns true it returns nil and true.  Each returned struct type will have a maximum of 10 top
+// level fields in it to attempt to avoid hitting the 65535 byte type name length limit in reflect.StructOf
+// (reflect.nameFrom: name too long), although the limit can still be reached with a single struct field with many
+// fields in it.
+func FilterPropertyStructSharded(prop reflect.Type, predicate FilterFieldPredicate) (filteredProp []reflect.Type, filtered bool) {
+	var fields []reflect.StructField
+
+	ptr := prop.Kind() == reflect.Ptr
+	if ptr {
+		prop = prop.Elem()
+	}
+
+	for i := 0; i < prop.NumField(); i++ {
+		fields = append(fields, prop.Field(i))
+	}
+
+	fields, filtered = filterPropertyStructFields(fields, "", predicate)
+	if !filtered {
+		if ptr {
+			return []reflect.Type{reflect.PtrTo(prop)}, false
+		}
+		return []reflect.Type{prop}, false
+	}
+
+	if len(fields) == 0 {
+		return nil, true
+	}
+
+	shards := shardFields(fields, 10)
+
+	for _, shard := range shards {
+		s := reflect.StructOf(shard)
+		if ptr {
+			s = reflect.PtrTo(s)
+		}
+		filteredProp = append(filteredProp, s)
+	}
+
+	return filteredProp, true
+}
+
+func shardFields(fields []reflect.StructField, shardSize int) [][]reflect.StructField {
+	ret := make([][]reflect.StructField, 0, (len(fields)+shardSize-1)/shardSize)
+	for len(fields) > shardSize {
+		ret = append(ret, fields[0:shardSize])
+		fields = fields[shardSize:]
+	}
+	if len(fields) > 0 {
+		ret = append(ret, fields)
+	}
+	return ret
+}
diff --git a/proptools/filter_test.go b/proptools/filter_test.go
new file mode 100644
index 0000000..695549a
--- /dev/null
+++ b/proptools/filter_test.go
@@ -0,0 +1,239 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package proptools
+
+import (
+	"reflect"
+	"testing"
+)
+
+type Named struct {
+	A *string `keep:"true"`
+	B *string
+}
+
+type NamedAllFiltered struct {
+	A *string
+}
+
+type NamedNoneFiltered struct {
+	A *string `keep:"true"`
+}
+
+func TestFilterPropertyStruct(t *testing.T) {
+	tests := []struct {
+		name     string
+		in       interface{}
+		out      interface{}
+		filtered bool
+	}{
+		// Property tests
+		{
+			name: "basic",
+			in: &struct {
+				A *string `keep:"true"`
+				B *string
+			}{},
+			out: &struct {
+				A *string
+			}{},
+			filtered: true,
+		},
+		{
+			name: "all filtered",
+			in: &struct {
+				A *string
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "none filtered",
+			in: &struct {
+				A *string `keep:"true"`
+			}{},
+			out: &struct {
+				A *string `keep:"true"`
+			}{},
+			filtered: false,
+		},
+
+		// Sub-struct tests
+		{
+			name: "substruct",
+			in: &struct {
+				A struct {
+					A *string `keep:"true"`
+					B *string
+				} `keep:"true"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "substruct all filtered",
+			in: &struct {
+				A struct {
+					A *string
+				} `keep:"true"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "substruct none filtered",
+			in: &struct {
+				A struct {
+					A *string `keep:"true"`
+				} `keep:"true"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string `keep:"true"`
+				} `keep:"true"`
+			}{},
+			filtered: false,
+		},
+
+		// Named sub-struct tests
+		{
+			name: "named substruct",
+			in: &struct {
+				A Named `keep:"true"`
+			}{},
+			out: &struct {
+				A struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "substruct all filtered",
+			in: &struct {
+				A NamedAllFiltered `keep:"true"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "substruct none filtered",
+			in: &struct {
+				A NamedNoneFiltered `keep:"true"`
+			}{},
+			out: &struct {
+				A NamedNoneFiltered `keep:"true"`
+			}{},
+			filtered: false,
+		},
+
+		// Pointer to sub-struct tests
+		{
+			name: "pointer substruct",
+			in: &struct {
+				A *struct {
+					A *string `keep:"true"`
+					B *string
+				} `keep:"true"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "pointer substruct all filtered",
+			in: &struct {
+				A *struct {
+					A *string
+				} `keep:"true"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "pointer substruct none filtered",
+			in: &struct {
+				A *struct {
+					A *string `keep:"true"`
+				} `keep:"true"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string `keep:"true"`
+				} `keep:"true"`
+			}{},
+			filtered: false,
+		},
+
+		// Pointer to named sub-struct tests
+		{
+			name: "pointer named substruct",
+			in: &struct {
+				A *Named `keep:"true"`
+			}{},
+			out: &struct {
+				A *struct {
+					A *string
+				}
+			}{},
+			filtered: true,
+		},
+		{
+			name: "pointer substruct all filtered",
+			in: &struct {
+				A *NamedAllFiltered `keep:"true"`
+			}{},
+			out:      nil,
+			filtered: true,
+		},
+		{
+			name: "pointer substruct none filtered",
+			in: &struct {
+				A *NamedNoneFiltered `keep:"true"`
+			}{},
+			out: &struct {
+				A *NamedNoneFiltered `keep:"true"`
+			}{},
+			filtered: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			out, filtered := FilterPropertyStruct(reflect.TypeOf(test.in),
+				func(field reflect.StructField, prefix string) (bool, reflect.StructField) {
+					if HasTag(field, "keep", "true") {
+						field.Tag = ""
+						return true, field
+					}
+					return false, field
+				})
+			if filtered != test.filtered {
+				t.Errorf("expected filtered %v, got %v", test.filtered, filtered)
+			}
+			expected := reflect.TypeOf(test.out)
+			if out != expected {
+				t.Errorf("expected type %v, got %v", expected, out)
+			}
+		})
+	}
+}
diff --git a/proptools/proptools.go b/proptools/proptools.go
index e6e3ae7..6881828 100644
--- a/proptools/proptools.go
+++ b/proptools/proptools.go
@@ -82,3 +82,18 @@
 func String(s *string) string {
 	return StringDefault(s, "")
 }
+
+// IntDefault takes a pointer to an int64 and returns the value pointed to by the pointer cast to int
+// if it is non-nil, or def if the pointer is nil.
+func IntDefault(i *int64, def int) int {
+	if i != nil {
+		return int(*i)
+	}
+	return def
+}
+
+// Int takes a pointer to an int64 and returns the value pointed to by the pointer cast to int
+// if it is non-nil, or 0 if the pointer is nil.
+func Int(i *int64) int {
+	return IntDefault(i, 0)
+}
diff --git a/singleton_ctx.go b/singleton_ctx.go
index cc58e06..3c0a24c 100644
--- a/singleton_ctx.go
+++ b/singleton_ctx.go
@@ -93,6 +93,23 @@
 	// true calls visit.
 	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
 
+	// VisitDirectDeps calls visit for each direct dependency of the Module.  If there are
+	// multiple direct dependencies on the same module visit will be called multiple times on
+	// that module and OtherModuleDependencyTag will return a different tag for each.
+	//
+	// The Module passed to the visit function should not be retained outside of the visit
+	// function, it may be invalidated by future mutators.
+	VisitDirectDeps(module Module, visit func(Module))
+
+	// VisitDirectDepsIf calls pred for each direct dependency of the Module, and if pred
+	// returns true calls visit.  If there are multiple direct dependencies on the same module
+	// pred and visit will be called multiple times on that module and OtherModuleDependencyTag
+	// will return a different tag for each.
+	//
+	// The Module passed to the visit function should not be retained outside of the visit
+	// function, it may be invalidated by future mutators.
+	VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))
+
 	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
 	// order. visit will only be called once for any given module, even if there are multiple paths through the
 	// dependency tree to the module or multiple direct dependencies with different tags.
@@ -289,6 +306,14 @@
 	s.context.VisitAllModulesIf(pred, visit)
 }
 
+func (s *singletonContext) VisitDirectDeps(module Module, visit func(Module)) {
+	s.context.VisitDirectDeps(module, visit)
+}
+
+func (s *singletonContext) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
+	s.context.VisitDirectDepsIf(module, pred, visit)
+}
+
 func (s *singletonContext) VisitDepsDepthFirst(module Module,
 	visit func(Module)) {