Merge "Fix the internal type of enum values" am: 74e23a1ec1

Original change: https://android-review.googlesource.com/c/platform/development/+/2530761

Change-Id: I6b5df899cf359e4898bf87d583012898f9832766
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hsin-Yi Chen
2023-04-17 03:12:21 +00:00
committed by Automerger Merge Worker
12 changed files with 259 additions and 17 deletions

View File

@@ -882,8 +882,12 @@ bool EnumDeclWrapper::SetupEnumFields(repr::EnumTypeIR *enump) {
clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin(); clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin();
while (enum_it != enum_decl_->enumerator_end()) { while (enum_it != enum_decl_->enumerator_end()) {
std::string name = enum_it->getQualifiedNameAsString(); std::string name = enum_it->getQualifiedNameAsString();
uint64_t field_value = enum_it->getInitVal().getExtValue(); const llvm::APSInt &value = enum_it->getInitVal();
enump->AddEnumField(repr::EnumFieldIR(name, field_value)); if (value.isUnsigned()) {
enump->AddEnumField(repr::EnumFieldIR(name, value.getZExtValue()));
} else {
enump->AddEnumField(repr::EnumFieldIR(name, value.getSExtValue()));
}
enum_it++; enum_it++;
} }
return true; return true;

View File

@@ -147,9 +147,10 @@ void AbiDiffHelper::CompareEnumFields(
utils::FindCommonElements(old_fields_map, new_fields_map); utils::FindCommonElements(old_fields_map, new_fields_map);
std::vector<EnumFieldDiffIR> enum_field_diffs; std::vector<EnumFieldDiffIR> enum_field_diffs;
for (auto &&common_fields : cf) { for (auto &&common_fields : cf) {
if (common_fields.first->GetValue() != common_fields.second->GetValue()) { if (common_fields.first->GetSignedValue() !=
common_fields.second->GetSignedValue()) {
EnumFieldDiffIR enum_field_diff_ir(common_fields.first, EnumFieldDiffIR enum_field_diff_ir(common_fields.first,
common_fields.second); common_fields.second);
enum_field_diffs.emplace_back(std::move(enum_field_diff_ir)); enum_field_diffs.emplace_back(std::move(enum_field_diff_ir));
} }
} }

View File

@@ -447,20 +447,29 @@ class RecordTypeIR : public TypeIR, public TemplatedArtifactIR {
class EnumFieldIR { class EnumFieldIR {
public: public:
EnumFieldIR(const std::string &name, int value) EnumFieldIR(const std::string &name, int64_t value)
: name_(name), value_(value) {} : name_(name), signed_value_(value), is_signed_(true) {}
EnumFieldIR(const std::string &name, uint64_t value)
: name_(name), unsigned_value_(value), is_signed_(false) {}
const std::string &GetName() const { const std::string &GetName() const {
return name_; return name_;
} }
int GetValue() const { bool IsSigned() const { return is_signed_; }
return value_;
} int64_t GetSignedValue() const { return signed_value_; }
uint64_t GetUnsignedValue() const { return unsigned_value_; }
protected: protected:
std::string name_; std::string name_;
int value_ = 0; union {
int64_t signed_value_;
uint64_t unsigned_value_;
};
bool is_signed_;
}; };
class EnumTypeIR : public TypeIR { class EnumTypeIR : public TypeIR {

View File

@@ -203,7 +203,12 @@ static JsonObject ConvertEnumFieldIR(const EnumFieldIR *enum_field_ir) {
JsonObject enum_field; JsonObject enum_field;
enum_field.Set("name", enum_field_ir->GetName()); enum_field.Set("name", enum_field_ir->GetName());
// Never omit enum values. // Never omit enum values.
enum_field["enum_field_value"] = Json::Int64(enum_field_ir->GetValue()); Json::Value &enum_field_value = enum_field["enum_field_value"];
if (enum_field_ir->IsSigned()) {
enum_field_value = Json::Int64(enum_field_ir->GetSignedValue());
} else {
enum_field_value = Json::UInt64(enum_field_ir->GetUnsignedValue());
}
return enum_field; return enum_field;
} }

View File

@@ -76,11 +76,16 @@ bool JsonObjectRef::GetBool(const std::string &key) const {
} }
int64_t JsonObjectRef::GetInt(const std::string &key) const { int64_t JsonObjectRef::GetInt(const std::string &key) const {
return Get(key, json_0, &Json::Value::isIntegral).asInt64(); return Get(key, json_0, &Json::Value::isInt64).asInt64();
} }
uint64_t JsonObjectRef::GetUint(const std::string &key) const { uint64_t JsonObjectRef::GetUint(const std::string &key) const {
return Get(key, json_0, &Json::Value::isIntegral).asUInt64(); return Get(key, json_0, &Json::Value::isUInt64).asUInt64();
}
const Json::Value &JsonObjectRef::GetIntegralValue(
const std::string &key) const {
return Get(key, json_0, &Json::Value::isIntegral);
} }
std::string JsonObjectRef::GetString(const std::string &key) const { std::string JsonObjectRef::GetString(const std::string &key) const {
@@ -248,9 +253,13 @@ void JsonIRReader::ReadVTableLayout(const JsonObjectRef &record_type,
void JsonIRReader::ReadEnumFields(const JsonObjectRef &enum_type, void JsonIRReader::ReadEnumFields(const JsonObjectRef &enum_type,
EnumTypeIR *enum_ir) { EnumTypeIR *enum_ir) {
for (auto &&field : enum_type.GetObjects("enum_fields")) { for (auto &&field : enum_type.GetObjects("enum_fields")) {
EnumFieldIR enum_field_ir(field.GetString("name"), std::string name = field.GetString("name");
field.GetInt("enum_field_value")); const Json::Value &value = field.GetIntegralValue("enum_field_value");
enum_ir->AddEnumField(std::move(enum_field_ir)); if (value.isUInt64()) {
enum_ir->AddEnumField(EnumFieldIR(name, value.asUInt64()));
} else {
enum_ir->AddEnumField(EnumFieldIR(name, value.asInt64()));
}
} }
} }

View File

@@ -46,6 +46,9 @@ class JsonObjectRef {
// Default to 0. // Default to 0.
uint64_t GetUint(const std::string &key) const; uint64_t GetUint(const std::string &key) const;
// Default to 0.
const Json::Value &GetIntegralValue(const std::string &key) const;
// Default to "". // Default to "".
std::string GetString(const std::string &key) const; std::string GetString(const std::string &key) const;

View File

@@ -356,7 +356,11 @@ inline bool SetIRToProtobufEnumField(
return true; return true;
} }
enum_field_protobuf->set_name(enum_field_ir->GetName()); enum_field_protobuf->set_name(enum_field_ir->GetName());
enum_field_protobuf->set_enum_field_value(enum_field_ir->GetValue()); // The "enum_field_value" in the .proto is a signed 64-bit integer. An
// unsigned integer >= (1 << 63) is represented with a negative integer in the
// dump file. Despite the wrong representation, the diff result isn't affected
// because every integer has a unique representation.
enum_field_protobuf->set_enum_field_value(enum_field_ir->GetSignedValue());
return true; return true;
} }

View File

@@ -0,0 +1,23 @@
#include <cstdint>
enum Int8 : int8_t {
ZERO = 0,
MINUS_1 = (int8_t)-1,
};
enum Uint8 : uint8_t {
UNSIGNED_255 = UINT8_MAX,
};
enum Int64 : int64_t {
SIGNED_MAX = INT64_MAX,
SIGNED_MIN = INT64_MIN,
};
enum Uint64 : uint64_t {
UNSIGNED_MAX = UINT64_MAX,
};
extern "C" {
void function(Int8, Uint8, Int64, Uint64);
}

View File

@@ -0,0 +1,4 @@
libenum {
global:
function;
};

View File

@@ -789,6 +789,16 @@ TEST_MODULES = [
export_include_dirs=['integration/union/include'], export_include_dirs=['integration/union/include'],
linker_flags=['-output-format', 'Json'], linker_flags=['-output-format', 'Json'],
), ),
LsdumpModule(
name='libenum',
arch='arm64',
srcs=['integration/enum/include/base.h'],
version_script='integration/enum/map.txt',
export_include_dirs=['integration/enum/include'],
dumper_flags=['-output-format', 'Json'],
linker_flags=['-input-format', 'Json', '-output-format', 'Json'],
has_reference_dump=True,
),
] ]
TEST_MODULES = {m.name: m for m in TEST_MODULES} TEST_MODULES = {m.name: m for m in TEST_MODULES}

View File

@@ -0,0 +1,167 @@
{
"array_types" : [],
"builtin_types" :
[
{
"alignment" : 1,
"is_integral" : true,
"linker_set_key" : "_ZTIa",
"name" : "signed char",
"referenced_type" : "_ZTIa",
"self_type" : "_ZTIa",
"size" : 1
},
{
"alignment" : 1,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIh",
"name" : "unsigned char",
"referenced_type" : "_ZTIh",
"self_type" : "_ZTIh",
"size" : 1
},
{
"alignment" : 8,
"is_integral" : true,
"linker_set_key" : "_ZTIl",
"name" : "long",
"referenced_type" : "_ZTIl",
"self_type" : "_ZTIl",
"size" : 8
},
{
"alignment" : 8,
"is_integral" : true,
"is_unsigned" : true,
"linker_set_key" : "_ZTIm",
"name" : "unsigned long",
"referenced_type" : "_ZTIm",
"self_type" : "_ZTIm",
"size" : 8
},
{
"linker_set_key" : "_ZTIv",
"name" : "void",
"referenced_type" : "_ZTIv",
"self_type" : "_ZTIv"
}
],
"elf_functions" :
[
{
"name" : "function"
}
],
"elf_objects" : [],
"enum_types" :
[
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 0,
"name" : "ZERO"
},
{
"enum_field_value" : -1,
"name" : "MINUS_1"
}
],
"linker_set_key" : "_ZTI4Int8",
"name" : "Int8",
"referenced_type" : "_ZTI4Int8",
"self_type" : "_ZTI4Int8",
"size" : 1,
"source_file" : "development/vndk/tools/header-checker/tests/integration/enum/include/base.h",
"underlying_type" : "_ZTIa"
},
{
"alignment" : 8,
"enum_fields" :
[
{
"enum_field_value" : 9223372036854775807,
"name" : "SIGNED_MAX"
},
{
"enum_field_value" : -9223372036854775808,
"name" : "SIGNED_MIN"
}
],
"linker_set_key" : "_ZTI5Int64",
"name" : "Int64",
"referenced_type" : "_ZTI5Int64",
"self_type" : "_ZTI5Int64",
"size" : 8,
"source_file" : "development/vndk/tools/header-checker/tests/integration/enum/include/base.h",
"underlying_type" : "_ZTIl"
},
{
"alignment" : 1,
"enum_fields" :
[
{
"enum_field_value" : 255,
"name" : "UNSIGNED_255"
}
],
"linker_set_key" : "_ZTI5Uint8",
"name" : "Uint8",
"referenced_type" : "_ZTI5Uint8",
"self_type" : "_ZTI5Uint8",
"size" : 1,
"source_file" : "development/vndk/tools/header-checker/tests/integration/enum/include/base.h",
"underlying_type" : "_ZTIh"
},
{
"alignment" : 8,
"enum_fields" :
[
{
"enum_field_value" : 18446744073709551615,
"name" : "UNSIGNED_MAX"
}
],
"linker_set_key" : "_ZTI6Uint64",
"name" : "Uint64",
"referenced_type" : "_ZTI6Uint64",
"self_type" : "_ZTI6Uint64",
"size" : 8,
"source_file" : "development/vndk/tools/header-checker/tests/integration/enum/include/base.h",
"underlying_type" : "_ZTIm"
}
],
"function_types" : [],
"functions" :
[
{
"function_name" : "function",
"linker_set_key" : "function",
"parameters" :
[
{
"referenced_type" : "_ZTI4Int8"
},
{
"referenced_type" : "_ZTI5Uint8"
},
{
"referenced_type" : "_ZTI5Int64"
},
{
"referenced_type" : "_ZTI6Uint64"
}
],
"return_type" : "_ZTIv",
"source_file" : "development/vndk/tools/header-checker/tests/integration/enum/include/base.h"
}
],
"global_vars" : [],
"lvalue_reference_types" : [],
"pointer_types" : [],
"qualified_types" : [],
"record_types" : [],
"rvalue_reference_types" : []
}

View File

@@ -485,6 +485,9 @@ class HeaderCheckerTest(unittest.TestCase):
self.assertNotIn("fields_added", diff) self.assertNotIn("fields_added", diff)
self.assertNotIn("fields_removed", diff) self.assertNotIn("fields_removed", diff)
def test_enum_diff(self):
self.prepare_and_absolute_diff_all_archs("libenum", "libenum")
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()