versioner: fix false positive with functions only available as inlines.

Change-Id: I09cc335b4006c6ceafcbd1bec9e50161f8262942
This commit is contained in:
Josh Gao 2016-06-03 13:44:00 -07:00
parent 173e7c0753
commit 958f3b31c4
4 changed files with 49 additions and 10 deletions

View File

@ -272,6 +272,8 @@ static DeclarationDatabase compileHeaders(const std::set<CompilationType>& types
static bool sanityCheck(const std::set<CompilationType>& types,
const DeclarationDatabase& database) {
bool error = false;
std::string cwd = getWorkingDir() + "/";
for (auto outer : database) {
const std::string& symbol_name = outer.first;
CompilationType last_type;
@ -290,7 +292,7 @@ static bool sanityCheck(const std::set<CompilationType>& types,
bool availability_mismatch = false;
DeclarationAvailability current_availability;
// Make sure that all of the availability declarations for this symbol match.
// Ensure that all of the availability declarations for this symbol match.
for (const DeclarationLocation& location : declaration.locations) {
if (!found_availability) {
found_availability = true;
@ -306,7 +308,7 @@ static bool sanityCheck(const std::set<CompilationType>& types,
if (availability_mismatch) {
printf("%s: availability mismatch for %s\n", symbol_name.c_str(), type.describe().c_str());
declaration.dump(getWorkingDir() + "/");
declaration.dump(cwd);
}
if (type.arch != last_type.arch) {
@ -315,7 +317,7 @@ static bool sanityCheck(const std::set<CompilationType>& types,
continue;
}
// Make sure that availability declarations are consistent across API levels for a given arch.
// Ensure that availability declarations are consistent across API levels for a given arch.
if (last_availability != current_availability) {
error = true;
printf("%s: availability mismatch between %s and %s: [%s] before, [%s] after\n",
@ -323,6 +325,23 @@ static bool sanityCheck(const std::set<CompilationType>& types,
last_availability.describe().c_str(), current_availability.describe().c_str());
}
// Ensure that at most one inline definition of a function exists.
std::set<DeclarationLocation> inline_definitions;
for (const DeclarationLocation& location : declaration.locations) {
if (location.is_definition) {
inline_definitions.insert(location);
}
}
if (inline_definitions.size() > 1) {
error = true;
printf("%s: multiple inline definitions found:\n", symbol_name.c_str());
for (const DeclarationLocation& location : declaration.locations) {
location.dump(cwd);
}
}
last_type = type;
}
}
@ -378,13 +397,13 @@ static bool checkVersions(const std::set<CompilationType>& types,
bool symbol_available = symbol_availability_it != platform_availability.end();
if (decl_available) {
if (!symbol_available) {
// Make sure that either it exists in the platform, or an inline definition is visible.
// Ensure that either it exists in the platform, or an inline definition is visible.
if (!declaration.hasDefinition()) {
missing_symbol.insert(type);
continue;
}
} else {
// Make sure that symbols declared as functions/variables actually are.
// Ensure that symbols declared as functions/variables actually are.
switch (declaration.type()) {
case DeclarationType::inconsistent:
printf("%s: inconsistent declaration type\n", symbol_name.c_str());
@ -409,7 +428,7 @@ static bool checkVersions(const std::set<CompilationType>& types,
}
}
} else {
// Make sure it's not available in the platform.
// Ensure that it's not available in the platform.
if (symbol_availability_it != platform_availability.end()) {
printf("%s: symbol should be unavailable in %s (declared with availability %s)\n",
symbol_name.c_str(), type.describe().c_str(), availability.describe().c_str());
@ -472,11 +491,27 @@ static bool checkVersions(const std::set<CompilationType>& types,
break;
}
// Check to see if the symbol is tagged with __INTRODUCED_IN_FUTURE.
bool found_inline_definition = false;
bool future = false;
auto symbol_it = declaration_database.find(symbol_name);
const Declaration& declaration = symbol_it->second.begin()->second;
DeclarationAvailability availability = declaration.locations.begin()->availability;
if (availability.introduced >= 10000) {
// Ignore inline functions and functions that are tagged as __INTRODUCED_IN_FUTURE.
// Ensure that all of the declarations of that function satisfy that.
for (const auto& declaration_pair : symbol_it->second) {
const Declaration& declaration = declaration_pair.second;
DeclarationAvailability availability = declaration.locations.begin()->availability;
if (availability.introduced >= 10000) {
future = true;
}
if (declaration.hasDefinition()) {
found_inline_definition = true;
}
}
if (future || found_inline_definition) {
continue;
}

View File

@ -0,0 +1,3 @@
static int foo() __attribute__((availability(android, introduced = 9))) {
return 0;
}

View File

@ -0,0 +1 @@
versioner -v headers -p platforms -r arm -a 9