versioner: allow static inlines that don't conflict.
Bug: http://b/32664285
Test: python run_test.py
Change-Id: I9d050e545390eccd82661325c0ec58055f5f28a3
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 74650d5..2f0656c 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -276,6 +276,21 @@
return result;
}
+static std::set<CompilationType> getCompilationTypes(const Declaration* decl) {
+ std::set<CompilationType> result;
+ for (const auto& it : decl->availability) {
+ result.insert(it.first);
+ }
+ return result;
+}
+
+template<typename T>
+static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
+ std::vector<T> intersection;
+ std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersection));
+ return intersection;
+}
+
// Perform a sanity check on a symbol's declarations, enforcing the following invariants:
// 1. At most one inline definition of the function exists.
// 2. All of the availability declarations for a symbol are compatible.
@@ -287,18 +302,23 @@
static bool checkSymbol(const Symbol& symbol) {
std::string cwd = getWorkingDir() + "/";
- const Declaration* inline_definition = nullptr;
+ std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions;
for (const auto& decl_it : symbol.declarations) {
const Declaration* decl = &decl_it.second;
if (decl->is_definition) {
- if (inline_definition) {
- fprintf(stderr, "versioner: multiple definitions of symbol %s\n", symbol.name.c_str());
- symbol.dump(cwd);
- inline_definition->dump(cwd);
- return false;
+ std::set<CompilationType> compilation_types = getCompilationTypes(decl);
+ for (const auto& inline_def_it : inline_definitions) {
+ auto intersection = Intersection(compilation_types, inline_def_it.second);
+ if (!intersection.empty()) {
+ fprintf(stderr, "versioner: conflicting inline definitions:\n");
+ fprintf(stderr, " declarations visible in: %s\n", Join(intersection, ", ").c_str());
+ decl->dump(cwd, stderr, 4);
+ inline_def_it.first->dump(cwd, stderr, 4);
+ return false;
+ }
}
- inline_definition = decl;
+ inline_definitions[decl] = std::move(compilation_types);
}
DeclarationAvailability availability;
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
new file mode 100644
index 0000000..6c531bd
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/expected_fail
@@ -0,0 +1,7 @@
+versioner: conflicting inline definitions:
+ declarations visible in: arm-9 [fob = 32], arm-9 [fob = 64], arm-12 [fob = 32], arm-12 [fob = 64]
+ static definition @ headers/foo.h:1:1
+ no availability
+ static definition @ headers/bar.h:1:1
+ no availability
+versioner: sanity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/bar.h
@@ -0,0 +1,3 @@
+static int foo() {
+ return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/foo.h
@@ -0,0 +1,3 @@
+static int foo() {
+ return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition/run.sh b/tools/versioner/tests/multiple_definition/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
new file mode 100644
index 0000000..c3c87bb
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 12
+static int foo() {
+ return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
new file mode 100644
index 0000000..9da9b2a
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 9
+static int foo() {
+ return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition_ok/run.sh b/tools/versioner/tests/multiple_definition_ok/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i