Allow for unsigned byte constants (u8)
For int32 constants, we can use something like 0xffffffff in order to
express a 32-bit value. However, byte literals are automatically
converted to 32-bit values. This is consistent with how integral
promotion works in C. However, this can be annoying when trying to
create 8-bit constants. So, the integer literal suffix 'u8' is added in
order to represent byte literals.
Fixes: 203492856
Test: aidl_integration_test, aidl_unittests
Change-Id: Idc9c842306d6410cc979e21b6ad5d3423a87354d
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 3ec6d47..0521cea 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -378,8 +378,15 @@
return false;
}
- const bool isLong = EndsWith(value, 'l') || EndsWith(value, 'L');
- const std::string value_substr = isLong ? value.substr(0, value.size() - 1) : value;
+ std::string_view value_view = value;
+ const bool is_byte = ConsumeSuffix(&value_view, "u8");
+ const bool is_long = ConsumeSuffix(&value_view, "l") || ConsumeSuffix(&value_view, "L");
+ const std::string value_substr = std::string(value_view);
+
+ *parsed_value = 0;
+ *parsed_type = Type::ERROR;
+
+ if (is_byte && is_long) return false;
if (IsHex(value)) {
// AIDL considers 'const int foo = 0xffffffff' as -1, but if we want to
@@ -393,28 +400,38 @@
// Note, for historical consistency, we need to consider small hex values
// as an integral type. Recognizing them as INT8 could break some files,
// even though it would simplify this code.
- if (uint32_t rawValue32;
- !isLong && android::base::ParseUint<uint32_t>(value_substr, &rawValue32)) {
- *parsed_value = static_cast<int32_t>(rawValue32);
+ if (is_byte) {
+ uint8_t raw_value8;
+ if (!android::base::ParseUint<uint8_t>(value_substr, &raw_value8)) {
+ return false;
+ }
+ *parsed_value = static_cast<int8_t>(raw_value8);
+ *parsed_type = Type::INT8;
+ } else if (uint32_t raw_value32;
+ !is_long && android::base::ParseUint<uint32_t>(value_substr, &raw_value32)) {
+ *parsed_value = static_cast<int32_t>(raw_value32);
*parsed_type = Type::INT32;
- } else if (uint64_t rawValue64; android::base::ParseUint<uint64_t>(value_substr, &rawValue64)) {
- *parsed_value = static_cast<int64_t>(rawValue64);
+ } else if (uint64_t raw_value64;
+ android::base::ParseUint<uint64_t>(value_substr, &raw_value64)) {
+ *parsed_value = static_cast<int64_t>(raw_value64);
*parsed_type = Type::INT64;
} else {
- *parsed_value = 0;
- *parsed_type = Type::ERROR;
return false;
}
return true;
}
if (!android::base::ParseInt<int64_t>(value_substr, parsed_value)) {
- *parsed_value = 0;
- *parsed_type = Type::ERROR;
return false;
}
- if (isLong) {
+ if (is_byte) {
+ if (*parsed_value > UINT8_MAX || *parsed_value < 0) {
+ return false;
+ }
+ *parsed_value = static_cast<int8_t>(*parsed_value);
+ *parsed_type = Type::INT8;
+ } else if (is_long) {
*parsed_type = Type::INT64;
} else {
// guess literal type.
@@ -595,7 +612,8 @@
}
AIDL_FATAL_IF(err == 0, this);
- AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string;
+ AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string
+ << " (" << value_ << ")";
return "";
}