Merge "Allow extending qualifiers of function parameters and return values" am: 82b8191b50
Original change: https://android-review.googlesource.com/c/platform/development/+/2337410 Change-Id: I4884d914a5f60d89ab5c99e0b6e0ea337c896584 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -93,7 +93,8 @@ bool DiffWrapper<repr::FunctionIR>::DumpDiff(
|
||||
repr::FunctionIR new_function = *newp_;
|
||||
ReplaceTypeIdsWithTypeNames(old_types_, &old_function);
|
||||
ReplaceTypeIdsWithTypeNames(new_types_, &new_function);
|
||||
repr::FunctionDiffIR function_diff_ir(&old_function, &new_function);
|
||||
repr::FunctionDiffIR function_diff_ir(&old_function, &new_function,
|
||||
function_type_diff.IsExtension());
|
||||
function_diff_ir.SetName(oldp_->GetName());
|
||||
return ir_diff_dumper_->AddDiffMessageIR(&function_diff_ir,
|
||||
Unwind(&type_queue), diff_kind);
|
||||
|
||||
@@ -281,20 +281,6 @@ static bool CompareSizeAndAlignment(const TypeIR *old_type,
|
||||
old_type->GetAlignment() == new_type->GetAlignment();
|
||||
}
|
||||
|
||||
bool AbiDiffHelper::AreTypeSizeAndAlignmentEqual(
|
||||
const std::string &old_type_id, const std::string &new_type_id) const {
|
||||
AbiElementMap<const TypeIR *>::const_iterator old_it =
|
||||
old_types_.find(old_type_id);
|
||||
AbiElementMap<const TypeIR *>::const_iterator new_it =
|
||||
new_types_.find(new_type_id);
|
||||
|
||||
if (old_it == old_types_.end() || new_it == new_types_.end()) {
|
||||
return AreOpaqueTypesEqual(old_type_id, new_type_id);
|
||||
}
|
||||
|
||||
return CompareSizeAndAlignment(old_it->second, new_it->second);
|
||||
}
|
||||
|
||||
DiffStatusPair<std::unique_ptr<RecordFieldDiffIR>>
|
||||
AbiDiffHelper::CompareCommonRecordFields(
|
||||
const RecordFieldIR *old_field,
|
||||
@@ -522,14 +508,13 @@ AbiDiffHelper::FixupDiffedFieldTypeIds(
|
||||
DiffStatus AbiDiffHelper::CompareFunctionTypes(
|
||||
const CFunctionLikeIR *old_type, const CFunctionLikeIR *new_type,
|
||||
std::deque<std::string> *type_queue, DiffMessageIR::DiffKind diff_kind) {
|
||||
DiffStatus param_diffs = CompareFunctionParameters(old_type->GetParameters(),
|
||||
new_type->GetParameters(),
|
||||
type_queue, diff_kind);
|
||||
DiffStatus return_type_diff = CompareParameterOrReturnType(
|
||||
old_type->GetReturnType(), new_type->GetReturnType(), type_queue,
|
||||
diff_kind);
|
||||
|
||||
return param_diffs.CombineWith(return_type_diff);
|
||||
DiffStatus status = CompareFunctionParameters(old_type->GetParameters(),
|
||||
new_type->GetParameters(),
|
||||
type_queue, diff_kind);
|
||||
status.CombineWith(CompareReturnTypes(old_type->GetReturnType(),
|
||||
new_type->GetReturnType(), type_queue,
|
||||
diff_kind));
|
||||
return status;
|
||||
}
|
||||
|
||||
DiffStatus AbiDiffHelper::CompareRecordTypes(
|
||||
@@ -696,36 +681,186 @@ DiffStatus AbiDiffHelper::CompareBuiltinTypes(
|
||||
DiffStatus AbiDiffHelper::CompareFunctionParameters(
|
||||
const std::vector<ParamIR> &old_parameters,
|
||||
const std::vector<ParamIR> &new_parameters,
|
||||
std::deque<std::string> *type_queue,
|
||||
DiffMessageIR::DiffKind diff_kind) {
|
||||
std::deque<std::string> *type_queue, DiffMessageIR::DiffKind diff_kind) {
|
||||
size_t old_parameters_size = old_parameters.size();
|
||||
if (old_parameters_size != new_parameters.size()) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
}
|
||||
uint64_t i = 0;
|
||||
while (i < old_parameters_size) {
|
||||
DiffStatus result = DiffStatus::kNoDiff;
|
||||
for (uint64_t i = 0; i < old_parameters_size; i++) {
|
||||
const ParamIR &old_parameter = old_parameters.at(i);
|
||||
const ParamIR &new_parameter = new_parameters.at(i);
|
||||
if (CompareParameterOrReturnType(old_parameter.GetReferencedType(),
|
||||
new_parameter.GetReferencedType(),
|
||||
type_queue, diff_kind)
|
||||
.IsDirectDiff() ||
|
||||
(old_parameter.GetIsDefault() != new_parameter.GetIsDefault())) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
result.CombineWith(CompareParameterTypes(old_parameter.GetReferencedType(),
|
||||
new_parameter.GetReferencedType(),
|
||||
type_queue, diff_kind));
|
||||
if (old_parameter.GetIsDefault() != new_parameter.GetIsDefault()) {
|
||||
result.CombineWith(DiffStatus::kDirectDiff);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return DiffStatus::kNoDiff;
|
||||
return result;
|
||||
}
|
||||
|
||||
DiffStatus AbiDiffHelper::CompareParameterOrReturnType(
|
||||
static const TypeIR *FindTypeById(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
const std::string &type_id) {
|
||||
auto it = type_graph.find(type_id);
|
||||
return it == type_graph.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
struct Qualifiers {
|
||||
bool is_const = false;
|
||||
bool is_restricted = false;
|
||||
bool is_volatile = false;
|
||||
|
||||
bool operator==(const Qualifiers &other) const {
|
||||
return (is_const == other.is_const &&
|
||||
is_restricted == other.is_restricted &&
|
||||
is_volatile == other.is_volatile);
|
||||
}
|
||||
|
||||
bool operator!=(const Qualifiers &other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
// This function returns the qualifiers and sets type_id to the unqalified or
|
||||
// opaque type.
|
||||
static Qualifiers ResolveQualifiers(const AbiElementMap<const TypeIR *> &types,
|
||||
std::string &type_id) {
|
||||
Qualifiers qual;
|
||||
while (true) {
|
||||
const TypeIR *type_ir = FindTypeById(types, type_id);
|
||||
if (type_ir == nullptr ||
|
||||
type_ir->GetKind() != LinkableMessageKind::QualifiedTypeKind) {
|
||||
return qual;
|
||||
}
|
||||
const QualifiedTypeIR *qualified_type_ir =
|
||||
static_cast<const QualifiedTypeIR *>(type_ir);
|
||||
qual.is_const |= qualified_type_ir->IsConst();
|
||||
qual.is_restricted |= qualified_type_ir->IsRestricted();
|
||||
qual.is_volatile |= qualified_type_ir->IsVolatile();
|
||||
type_id = qualified_type_ir->GetReferencedType();
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns whether the old_type can be implicitly casted to
|
||||
// new_type. It resolves qualified pointers and references until it reaches a
|
||||
// type that does not reference other types. It does not compare the final
|
||||
// referenced types.
|
||||
//
|
||||
// If this function returns true, old_type_id and new_type_id are set to the
|
||||
// final referenced types. are_qualifiers_equal represents whether the
|
||||
// qualifiers are exactly the same.
|
||||
//
|
||||
// If this function returns false, old_type_id, new_type_id, and
|
||||
// are_qualifiers_equal do not have valid values.
|
||||
//
|
||||
// This function follows C++ standard to determine whether qualifiers can be
|
||||
// casted. The rules are described in
|
||||
// Section 7.5 Qualification conversions [conv.qual] in C++17 standard
|
||||
// and
|
||||
// https://en.cppreference.com/w/cpp/language/implicit_conversion#Qualification_conversions
|
||||
// Additionally, __restrict__ follows the same rules as const and volatile.
|
||||
static bool ResolveImplicitlyConvertibleQualifiedReferences(
|
||||
const AbiElementMap<const TypeIR *> &old_types,
|
||||
const AbiElementMap<const TypeIR *> &new_types, std::string &old_type_id,
|
||||
std::string &new_type_id, bool &are_qualifiers_equal) {
|
||||
are_qualifiers_equal = true;
|
||||
bool is_first_level = true;
|
||||
bool is_const_since_second_level = true;
|
||||
while (true) {
|
||||
// Check qualifiers.
|
||||
const Qualifiers old_qual = ResolveQualifiers(old_types, old_type_id);
|
||||
const Qualifiers new_qual = ResolveQualifiers(new_types, new_type_id);
|
||||
are_qualifiers_equal &= (old_qual == new_qual);
|
||||
if (is_first_level) {
|
||||
is_first_level = false;
|
||||
} else {
|
||||
if ((old_qual.is_const && !new_qual.is_const) ||
|
||||
(old_qual.is_restricted && !new_qual.is_restricted) ||
|
||||
(old_qual.is_volatile && !new_qual.is_volatile)) {
|
||||
return false;
|
||||
}
|
||||
if (!is_const_since_second_level && old_qual != new_qual) {
|
||||
return false;
|
||||
}
|
||||
is_const_since_second_level &= new_qual.is_const;
|
||||
}
|
||||
// Stop if the unqualified types differ or don't reference other types.
|
||||
const TypeIR *old_type = FindTypeById(old_types, old_type_id);
|
||||
const TypeIR *new_type = FindTypeById(new_types, new_type_id);
|
||||
if (old_type == nullptr || new_type == nullptr) {
|
||||
return true;
|
||||
}
|
||||
const LinkableMessageKind kind = old_type->GetKind();
|
||||
if (kind != new_type->GetKind()) {
|
||||
return true;
|
||||
}
|
||||
if (kind != LinkableMessageKind::PointerTypeKind &&
|
||||
kind != LinkableMessageKind::LvalueReferenceTypeKind &&
|
||||
kind != LinkableMessageKind::RvalueReferenceTypeKind) {
|
||||
return true;
|
||||
}
|
||||
// Get the referenced types.
|
||||
old_type_id = old_type->GetReferencedType();
|
||||
new_type_id = new_type->GetReferencedType();
|
||||
}
|
||||
}
|
||||
|
||||
DiffStatus AbiDiffHelper::CompareParameterTypes(
|
||||
const std::string &old_type_id, const std::string &new_type_id,
|
||||
std::deque<std::string> *type_queue, DiffMessageIR::DiffKind diff_kind) {
|
||||
if (!AreTypeSizeAndAlignmentEqual(old_type_id, new_type_id)) {
|
||||
// Compare size and alignment.
|
||||
const TypeIR *old_type_ir = FindTypeById(old_types_, old_type_id);
|
||||
const TypeIR *new_type_ir = FindTypeById(new_types_, new_type_id);
|
||||
if (old_type_ir != nullptr && new_type_ir != nullptr &&
|
||||
!CompareSizeAndAlignment(old_type_ir, new_type_ir)) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
}
|
||||
return CompareAndDumpTypeDiff(old_type_id, new_type_id, type_queue,
|
||||
diff_kind);
|
||||
// Allow the new parameter to be more qualified than the old parameter.
|
||||
std::string old_referenced_type_id = old_type_id;
|
||||
std::string new_referenced_type_id = new_type_id;
|
||||
bool are_qualifiers_equal;
|
||||
if (!ResolveImplicitlyConvertibleQualifiedReferences(
|
||||
old_types_, new_types_, old_referenced_type_id,
|
||||
new_referenced_type_id, are_qualifiers_equal)) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
}
|
||||
// Compare the unqualified referenced types.
|
||||
DiffStatus result = CompareAndDumpTypeDiff(
|
||||
old_referenced_type_id, new_referenced_type_id, type_queue, diff_kind);
|
||||
if (!are_qualifiers_equal) {
|
||||
result.CombineWith(DiffStatus::kDirectExt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function is the same as CompareParameterTypes except for the arguments
|
||||
// to ResolveImplicitlyConvertibleQualifiedReferences.
|
||||
DiffStatus AbiDiffHelper::CompareReturnTypes(
|
||||
const std::string &old_type_id, const std::string &new_type_id,
|
||||
std::deque<std::string> *type_queue, DiffMessageIR::DiffKind diff_kind) {
|
||||
// Compare size and alignment.
|
||||
const TypeIR *old_type_ir = FindTypeById(old_types_, old_type_id);
|
||||
const TypeIR *new_type_ir = FindTypeById(new_types_, new_type_id);
|
||||
if (old_type_ir != nullptr && new_type_ir != nullptr &&
|
||||
!CompareSizeAndAlignment(old_type_ir, new_type_ir)) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
}
|
||||
// Allow the new return type to be less qualified than the old return type.
|
||||
std::string old_referenced_type_id = old_type_id;
|
||||
std::string new_referenced_type_id = new_type_id;
|
||||
bool are_qualifiers_equal;
|
||||
if (!ResolveImplicitlyConvertibleQualifiedReferences(
|
||||
new_types_, old_types_, new_referenced_type_id,
|
||||
old_referenced_type_id, are_qualifiers_equal)) {
|
||||
return DiffStatus::kDirectDiff;
|
||||
}
|
||||
// Compare the unqualified referenced types.
|
||||
DiffStatus result = CompareAndDumpTypeDiff(
|
||||
old_referenced_type_id, new_referenced_type_id, type_queue, diff_kind);
|
||||
if (!are_qualifiers_equal) {
|
||||
result.CombineWith(DiffStatus::kDirectExt);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DiffStatus AbiDiffHelper::CompareAndDumpTypeDiff(
|
||||
@@ -786,10 +921,14 @@ DiffStatus AbiDiffHelper::CompareAndDumpTypeDiff(
|
||||
}
|
||||
|
||||
if (kind == LinkableMessageKind::FunctionTypeKind) {
|
||||
return CompareFunctionTypes(
|
||||
DiffStatus result = CompareFunctionTypes(
|
||||
static_cast<const FunctionTypeIR *>(old_type),
|
||||
static_cast<const FunctionTypeIR *>(new_type),
|
||||
type_queue, diff_kind);
|
||||
static_cast<const FunctionTypeIR *>(new_type), type_queue, diff_kind);
|
||||
// Do not allow extending function pointers, function references, etc.
|
||||
if (result.IsExtension()) {
|
||||
result.CombineWith(DiffStatus::kDirectDiff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return DiffStatus::kNoDiff;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,11 @@ class DiffStatus {
|
||||
kNoDiff = 0,
|
||||
// The diff has been added to the IRDiffDumper.
|
||||
kIndirectDiff = 1,
|
||||
// The diff has not been added to the IRDiffDumper, and the new ABI is
|
||||
// an extension to the old ABI.
|
||||
kDirectExt = 2,
|
||||
// The diff has not been added to the IRDiffDumper.
|
||||
kDirectDiff = 2,
|
||||
kDirectDiff = 3,
|
||||
};
|
||||
|
||||
// Allow implicit conversion.
|
||||
@@ -45,7 +48,11 @@ class DiffStatus {
|
||||
|
||||
bool HasDiff() const { return status_ != kNoDiff; }
|
||||
|
||||
bool IsDirectDiff() const { return status_ == kDirectDiff; }
|
||||
bool IsDirectDiff() const {
|
||||
return status_ == kDirectDiff || status_ == kDirectExt;
|
||||
}
|
||||
|
||||
bool IsExtension() const { return status_ == kDirectExt; }
|
||||
|
||||
DiffStatus &CombineWith(DiffStatus other) {
|
||||
status_ = std::max(status_, other.status_);
|
||||
@@ -93,9 +100,6 @@ class AbiDiffHelper {
|
||||
bool AreOpaqueTypesEqual(const std::string &old_type_str,
|
||||
const std::string &new_type_str) const;
|
||||
|
||||
bool AreTypeSizeAndAlignmentEqual(const std::string &old_type_str,
|
||||
const std::string &new_type_str) const;
|
||||
|
||||
DiffStatus CompareAndDumpTypeDiff(
|
||||
const std::string &old_type_str, const std::string &new_type_str,
|
||||
std::deque<std::string> *type_queue = nullptr,
|
||||
@@ -123,17 +127,6 @@ class AbiDiffHelper {
|
||||
std::deque<std::string> *type_queue,
|
||||
DiffMessageIR::DiffKind diff_kind);
|
||||
|
||||
DiffStatus CompareFunctionParameters(
|
||||
const std::vector<ParamIR> &old_parameters,
|
||||
const std::vector<ParamIR> &new_parameters,
|
||||
std::deque<std::string> *type_queue,
|
||||
IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
DiffStatus CompareParameterOrReturnType(const std::string &old_type_id,
|
||||
const std::string &new_type_id,
|
||||
std::deque<std::string> *type_queue,
|
||||
IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
DiffStatus CompareTemplateInfo(
|
||||
const std::vector<TemplateElementIR> &old_template_elements,
|
||||
const std::vector<TemplateElementIR> &new_template_elements,
|
||||
@@ -211,6 +204,21 @@ class AbiDiffHelper {
|
||||
const VTableComponentIR &old_component,
|
||||
const VTableComponentIR &new_component);
|
||||
|
||||
DiffStatus CompareFunctionParameters(
|
||||
const std::vector<ParamIR> &old_parameters,
|
||||
const std::vector<ParamIR> &new_parameters,
|
||||
std::deque<std::string> *type_queue, IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
DiffStatus CompareParameterTypes(const std::string &old_type_id,
|
||||
const std::string &new_type_id,
|
||||
std::deque<std::string> *type_queue,
|
||||
IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
DiffStatus CompareReturnTypes(const std::string &old_type_id,
|
||||
const std::string &new_type_id,
|
||||
std::deque<std::string> *type_queue,
|
||||
IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
template <typename DiffType, typename DiffElement>
|
||||
bool AddToDiff(DiffType *mutable_diff, const DiffElement *oldp,
|
||||
const DiffElement *newp,
|
||||
|
||||
@@ -347,9 +347,11 @@ class GlobalVarDiffIR : public DiffMessageIR {
|
||||
|
||||
class FunctionDiffIR : public DiffMessageIR {
|
||||
public:
|
||||
FunctionDiffIR(const FunctionIR *old_function,
|
||||
const FunctionIR *new_function)
|
||||
: old_function_(old_function), new_function_(new_function) {}
|
||||
FunctionDiffIR(const FunctionIR *old_function, const FunctionIR *new_function,
|
||||
bool is_extended)
|
||||
: old_function_(old_function),
|
||||
new_function_(new_function),
|
||||
is_extended_(is_extended) {}
|
||||
|
||||
LinkableMessageKind Kind() const override {
|
||||
return LinkableMessageKind::FunctionKind;
|
||||
@@ -363,9 +365,12 @@ class FunctionDiffIR : public DiffMessageIR {
|
||||
return new_function_;
|
||||
}
|
||||
|
||||
bool IsExtended() const { return is_extended_; }
|
||||
|
||||
protected:
|
||||
const FunctionIR *old_function_;
|
||||
const FunctionIR *new_function_;
|
||||
const bool is_extended_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ CompatibilityStatusIR ProtobufIRDiffDumper::GetCompatibilityStatusIR() {
|
||||
if (diff_tu_->enum_type_extension_diffs().size() != 0 ||
|
||||
diff_tu_->functions_added().size() != 0 ||
|
||||
diff_tu_->global_vars_added().size() != 0 ||
|
||||
diff_tu_->record_type_extension_diffs().size() != 0) {
|
||||
diff_tu_->record_type_extension_diffs().size() != 0 ||
|
||||
diff_tu_->function_extension_diffs().size() != 0) {
|
||||
combined_status = combined_status | CompatibilityStatusIR::Extension;
|
||||
}
|
||||
|
||||
@@ -315,7 +316,8 @@ bool ProtobufIRDiffDumper::AddFunctionDiffIR(
|
||||
const FunctionDiffIR *function_diff_ir, const std::string &type_stack,
|
||||
DiffKind diff_kind) {
|
||||
abi_diff::FunctionDeclDiff *added_function_diff =
|
||||
diff_tu_->add_function_diffs();
|
||||
function_diff_ir->IsExtended() ? diff_tu_->add_function_extension_diffs()
|
||||
: diff_tu_->add_function_diffs();
|
||||
if (!added_function_diff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ message TranslationUnitDiff {
|
||||
|
||||
// Functions and Global variables.
|
||||
repeated FunctionDeclDiff function_diffs = 13;
|
||||
repeated FunctionDeclDiff function_extension_diffs = 26;
|
||||
repeated GlobalVarDeclDiff global_var_diffs = 14;
|
||||
|
||||
repeated abi_dump.FunctionDecl functions_removed = 15;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
struct Struct;
|
||||
|
||||
extern "C" {
|
||||
void ConstParameter(char (&)[2]);
|
||||
void VolatileParameter(Struct &&);
|
||||
void Restrict(char *__restrict__);
|
||||
const char *const *MultipleConst(char **);
|
||||
}
|
||||
|
||||
const char &ConstReturn();
|
||||
volatile Struct &&VolatileReturn();
|
||||
@@ -0,0 +1,11 @@
|
||||
struct Struct;
|
||||
|
||||
extern "C" {
|
||||
void ConstParameter(const char (&)[2]);
|
||||
void VolatileParameter(volatile Struct &&);
|
||||
void Restrict(char *);
|
||||
char **MultipleConst(char const *const *const);
|
||||
}
|
||||
|
||||
char &ConstReturn();
|
||||
Struct &&VolatileReturn();
|
||||
@@ -0,0 +1,9 @@
|
||||
libfunction_extensions {
|
||||
global:
|
||||
ConstParameter;
|
||||
VolatileParameter;
|
||||
Restrict;
|
||||
MultipleConst;
|
||||
_Z11ConstReturnv;
|
||||
_Z14VolatileReturnv;
|
||||
};
|
||||
@@ -736,6 +736,24 @@ TEST_MODULES = [
|
||||
linker_flags=['-output-format', 'Json'],
|
||||
has_reference_dump=True,
|
||||
),
|
||||
LsdumpModule(
|
||||
name='libfunction_extensions',
|
||||
arch='arm64',
|
||||
srcs=['integration/function_extensions/include/base.h'],
|
||||
version_script='integration/function_extensions/map.txt',
|
||||
export_include_dirs=['integration/function_extensions/include'],
|
||||
linker_flags=['-output-format', 'Json'],
|
||||
has_reference_dump=True,
|
||||
),
|
||||
LsdumpModule(
|
||||
name='liballowed_function_extensions',
|
||||
arch='arm64',
|
||||
srcs=['integration/function_extensions/include/extensions.h'],
|
||||
version_script='integration/function_extensions/map.txt',
|
||||
export_include_dirs=['integration/function_extensions/include'],
|
||||
linker_flags=['-output-format', 'Json'],
|
||||
has_reference_dump=True,
|
||||
),
|
||||
]
|
||||
|
||||
TEST_MODULES = {m.name: m for m in TEST_MODULES}
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
{
|
||||
"array_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 1,
|
||||
"linker_set_key" : "_ZTIA2_c",
|
||||
"name" : "char[2]",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIA2_c",
|
||||
"size" : 2,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
],
|
||||
"builtin_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 1,
|
||||
"is_integral" : true,
|
||||
"is_unsigned" : true,
|
||||
"linker_set_key" : "_ZTIc",
|
||||
"name" : "char",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIc",
|
||||
"size" : 1
|
||||
},
|
||||
{
|
||||
"linker_set_key" : "_ZTIv",
|
||||
"name" : "void",
|
||||
"referenced_type" : "_ZTIv",
|
||||
"self_type" : "_ZTIv"
|
||||
}
|
||||
],
|
||||
"elf_functions" :
|
||||
[
|
||||
{
|
||||
"name" : "ConstParameter"
|
||||
},
|
||||
{
|
||||
"name" : "MultipleConst"
|
||||
},
|
||||
{
|
||||
"name" : "Restrict"
|
||||
},
|
||||
{
|
||||
"name" : "VolatileParameter"
|
||||
},
|
||||
{
|
||||
"name" : "_Z11ConstReturnv"
|
||||
},
|
||||
{
|
||||
"name" : "_Z14VolatileReturnv"
|
||||
}
|
||||
],
|
||||
"elf_objects" : [],
|
||||
"enum_types" : [],
|
||||
"function_types" : [],
|
||||
"functions" :
|
||||
[
|
||||
{
|
||||
"function_name" : "ConstParameter",
|
||||
"linker_set_key" : "ConstParameter",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIRA2_Kc"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "MultipleConst",
|
||||
"linker_set_key" : "MultipleConst",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIKPKPKc"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIPPc",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "Restrict",
|
||||
"linker_set_key" : "Restrict",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIPc"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "VolatileParameter",
|
||||
"linker_set_key" : "VolatileParameter",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIOV6Struct"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "ConstReturn",
|
||||
"linker_set_key" : "_Z11ConstReturnv",
|
||||
"return_type" : "_ZTIRc",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "VolatileReturn",
|
||||
"linker_set_key" : "_Z14VolatileReturnv",
|
||||
"return_type" : "_ZTIO6Struct",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
],
|
||||
"global_vars" : [],
|
||||
"lvalue_reference_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIRA2_Kc",
|
||||
"name" : "const char (&)[2]",
|
||||
"referenced_type" : "_ZTIA2_Kc",
|
||||
"self_type" : "_ZTIRA2_Kc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIRc",
|
||||
"name" : "char &",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIRc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
],
|
||||
"pointer_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPKPKc",
|
||||
"name" : "const char *const *",
|
||||
"referenced_type" : "_ZTIKPKc",
|
||||
"self_type" : "_ZTIPKPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPKc",
|
||||
"name" : "const char *",
|
||||
"referenced_type" : "_ZTIKc",
|
||||
"self_type" : "_ZTIPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPPc",
|
||||
"name" : "char **",
|
||||
"referenced_type" : "_ZTIPc",
|
||||
"self_type" : "_ZTIPPc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPc",
|
||||
"name" : "char *",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIPc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
],
|
||||
"qualified_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 1,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIA2_Kc",
|
||||
"name" : "const char[2]",
|
||||
"referenced_type" : "_ZTIA2_c",
|
||||
"self_type" : "_ZTIA2_Kc",
|
||||
"size" : 2,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIKPKPKc",
|
||||
"name" : "const char *const *const",
|
||||
"referenced_type" : "_ZTIPKPKc",
|
||||
"self_type" : "_ZTIKPKPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIKPKc",
|
||||
"name" : "const char *const",
|
||||
"referenced_type" : "_ZTIPKc",
|
||||
"self_type" : "_ZTIKPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 1,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIKc",
|
||||
"name" : "const char",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIKc",
|
||||
"size" : 1,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"is_volatile" : true,
|
||||
"linker_set_key" : "_ZTIV6Struct",
|
||||
"name" : "volatile Struct",
|
||||
"referenced_type" : "_ZTI6Struct",
|
||||
"self_type" : "_ZTIV6Struct",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
],
|
||||
"record_types" : [],
|
||||
"rvalue_reference_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIO6Struct",
|
||||
"name" : "Struct &&",
|
||||
"referenced_type" : "_ZTI6Struct",
|
||||
"self_type" : "_ZTIO6Struct",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIOV6Struct",
|
||||
"name" : "volatile Struct &&",
|
||||
"referenced_type" : "_ZTIV6Struct",
|
||||
"self_type" : "_ZTIOV6Struct",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/extensions.h"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
{
|
||||
"array_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 1,
|
||||
"linker_set_key" : "_ZTIA2_c",
|
||||
"name" : "char[2]",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIA2_c",
|
||||
"size" : 2,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
],
|
||||
"builtin_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 1,
|
||||
"is_integral" : true,
|
||||
"is_unsigned" : true,
|
||||
"linker_set_key" : "_ZTIc",
|
||||
"name" : "char",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIc",
|
||||
"size" : 1
|
||||
},
|
||||
{
|
||||
"linker_set_key" : "_ZTIv",
|
||||
"name" : "void",
|
||||
"referenced_type" : "_ZTIv",
|
||||
"self_type" : "_ZTIv"
|
||||
}
|
||||
],
|
||||
"elf_functions" :
|
||||
[
|
||||
{
|
||||
"name" : "ConstParameter"
|
||||
},
|
||||
{
|
||||
"name" : "MultipleConst"
|
||||
},
|
||||
{
|
||||
"name" : "Restrict"
|
||||
},
|
||||
{
|
||||
"name" : "VolatileParameter"
|
||||
},
|
||||
{
|
||||
"name" : "_Z11ConstReturnv"
|
||||
},
|
||||
{
|
||||
"name" : "_Z14VolatileReturnv"
|
||||
}
|
||||
],
|
||||
"elf_objects" : [],
|
||||
"enum_types" : [],
|
||||
"function_types" : [],
|
||||
"functions" :
|
||||
[
|
||||
{
|
||||
"function_name" : "ConstParameter",
|
||||
"linker_set_key" : "ConstParameter",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIRA2_c"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "MultipleConst",
|
||||
"linker_set_key" : "MultipleConst",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIPPc"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIPKPKc",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "Restrict",
|
||||
"linker_set_key" : "Restrict",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIrPc"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "VolatileParameter",
|
||||
"linker_set_key" : "VolatileParameter",
|
||||
"parameters" :
|
||||
[
|
||||
{
|
||||
"referenced_type" : "_ZTIO6Struct"
|
||||
}
|
||||
],
|
||||
"return_type" : "_ZTIv",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "ConstReturn",
|
||||
"linker_set_key" : "_Z11ConstReturnv",
|
||||
"return_type" : "_ZTIRKc",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"function_name" : "VolatileReturn",
|
||||
"linker_set_key" : "_Z14VolatileReturnv",
|
||||
"return_type" : "_ZTIOV6Struct",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
],
|
||||
"global_vars" : [],
|
||||
"lvalue_reference_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIRA2_c",
|
||||
"name" : "char (&)[2]",
|
||||
"referenced_type" : "_ZTIA2_c",
|
||||
"self_type" : "_ZTIRA2_c",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIRKc",
|
||||
"name" : "const char &",
|
||||
"referenced_type" : "_ZTIKc",
|
||||
"self_type" : "_ZTIRKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
],
|
||||
"pointer_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPKPKc",
|
||||
"name" : "const char *const *",
|
||||
"referenced_type" : "_ZTIKPKc",
|
||||
"self_type" : "_ZTIPKPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPKc",
|
||||
"name" : "const char *",
|
||||
"referenced_type" : "_ZTIKc",
|
||||
"self_type" : "_ZTIPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPPc",
|
||||
"name" : "char **",
|
||||
"referenced_type" : "_ZTIPc",
|
||||
"self_type" : "_ZTIPPc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIPc",
|
||||
"name" : "char *",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIPc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
],
|
||||
"qualified_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIKPKc",
|
||||
"name" : "const char *const",
|
||||
"referenced_type" : "_ZTIPKc",
|
||||
"self_type" : "_ZTIKPKc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 1,
|
||||
"is_const" : true,
|
||||
"linker_set_key" : "_ZTIKc",
|
||||
"name" : "const char",
|
||||
"referenced_type" : "_ZTIc",
|
||||
"self_type" : "_ZTIKc",
|
||||
"size" : 1,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"is_volatile" : true,
|
||||
"linker_set_key" : "_ZTIV6Struct",
|
||||
"name" : "volatile Struct",
|
||||
"referenced_type" : "_ZTI6Struct",
|
||||
"self_type" : "_ZTIV6Struct",
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"is_restricted" : true,
|
||||
"linker_set_key" : "_ZTIrPc",
|
||||
"name" : "char *__restrict",
|
||||
"referenced_type" : "_ZTIPc",
|
||||
"self_type" : "_ZTIrPc",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
],
|
||||
"record_types" : [],
|
||||
"rvalue_reference_types" :
|
||||
[
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIO6Struct",
|
||||
"name" : "Struct &&",
|
||||
"referenced_type" : "_ZTI6Struct",
|
||||
"self_type" : "_ZTIO6Struct",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
},
|
||||
{
|
||||
"alignment" : 8,
|
||||
"linker_set_key" : "_ZTIOV6Struct",
|
||||
"name" : "volatile Struct &&",
|
||||
"referenced_type" : "_ZTIV6Struct",
|
||||
"self_type" : "_ZTIOV6Struct",
|
||||
"size" : 8,
|
||||
"source_file" : "development/vndk/tools/header-checker/tests/integration/function_extensions/include/base.h"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -441,6 +441,21 @@ class HeaderCheckerTest(unittest.TestCase):
|
||||
flags=["-input-format-new", "Json", "-input-format-old", "Json"],
|
||||
create_old=False, create_new=False)
|
||||
|
||||
def test_function_extensions(self):
|
||||
diff = self.prepare_and_run_abi_diff_all_archs(
|
||||
"libfunction_extensions", "liballowed_function_extensions", 4,
|
||||
flags=["-input-format-new", "Json", "-input-format-old", "Json"],
|
||||
create_old=False, create_new=False)
|
||||
self.assertEqual(6, diff.count('function_extension_diffs'))
|
||||
|
||||
diff = self.prepare_and_run_abi_diff_all_archs(
|
||||
"liballowed_function_extensions", "libfunction_extensions", 8,
|
||||
flags=["-input-format-new", "Json", "-input-format-old", "Json"],
|
||||
create_old=False, create_new=False)
|
||||
# Adding and removing __restrict__ at the first level are extensions.
|
||||
self.assertEqual(1, diff.count('function_extension_diffs'))
|
||||
self.assertEqual(5, diff.count('function_diffs'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user