Merge "Added header-abi-diff." am: 4f4b426e06 am: 8800a6b8d9 am: 649fbd4ce4
am: eb9d98f889
Change-Id: I1a8054aeb53414f729711de05fea85d113131235
This commit is contained in:
@@ -98,6 +98,7 @@ cc_library_static {
|
|||||||
|
|
||||||
srcs: [
|
srcs: [
|
||||||
"proto/abi_dump.proto",
|
"proto/abi_dump.proto",
|
||||||
|
"proto/abi_diff.proto",
|
||||||
],
|
],
|
||||||
|
|
||||||
proto: {
|
proto: {
|
||||||
@@ -174,3 +175,35 @@ cc_binary_host {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_binary_host {
|
||||||
|
name: "header-abi-diff",
|
||||||
|
|
||||||
|
defaults: [
|
||||||
|
"header-checker-defaults",
|
||||||
|
"header-abi-linker-lib-defaults",
|
||||||
|
],
|
||||||
|
|
||||||
|
srcs: [
|
||||||
|
"header-abi-diff/src/*.cpp",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"libheader-checker-proto",
|
||||||
|
],
|
||||||
|
|
||||||
|
target: {
|
||||||
|
linux: {
|
||||||
|
host_ldlibs: [
|
||||||
|
"-ldl",
|
||||||
|
"-lpthread",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
darwin: {
|
||||||
|
host_ldlibs: [
|
||||||
|
"-ldl",
|
||||||
|
"-lpthread",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,33 @@
|
|||||||
# VNDK Header Checker
|
# VNDK Header Abi Dumper
|
||||||
|
|
||||||
`header-checker` is a tool to check for ABI compliance. First, we can create a
|
`header-abi-dumper` is a tool to dump the abi of a source. The Abi dumped
|
||||||
reference dump for each header file when we are preparing a formal release.
|
belonging to a source file is filtered by dumping only the Abi contained in a
|
||||||
After the release, we can check the ABI compliance by comparing the information
|
set of header files exposed through the "export_include_dirs" directory(ies).
|
||||||
in the reference dump and the latest header.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
header-abi-dumper -o <dump-file> <source_file> -I <export-include-dir-1> -I
|
||||||
|
<export-include-dir-2>.. -- <cflags>
|
||||||
|
|
||||||
Example 1:
|
# VNDK Header Abi Linker
|
||||||
|
|
||||||
|
`header-abi-linker` is a tool to link abi dumps produced by header-abi-dumper.
|
||||||
|
This tool combines all the abi information present in the dump files passed to
|
||||||
|
it.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
header-abi-linker -o <linked-abi-dump> <abi-dump1> <abi-dump2> <abi-dump3> ...
|
||||||
|
|
||||||
|
# VNDK Header Abi Diff
|
||||||
|
|
||||||
|
`header-abi-diff` is a tool which compares two header abi dumps produced by
|
||||||
|
header-abi-dumper. It produces a report outlining all the differences in the
|
||||||
|
abi's exposed by the two dumps.
|
||||||
|
|
||||||
|
# Return Value
|
||||||
|
1: InCompatible
|
||||||
|
0: Compatible or Compatible Extension.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
header-abi-diff -old <old-abi-dump> -new <new-abi-dump> -o <report>
|
||||||
|
|
||||||
$ header-checker -g -r example1.ast tests/example1.h -- clang -x c++
|
|
||||||
|
|||||||
232
vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp
Normal file
232
vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
// Copyright (C) 2016 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "abi_diff.h"
|
||||||
|
|
||||||
|
#include <llvm/Support/raw_ostream.h>
|
||||||
|
|
||||||
|
#include <google/protobuf/text_format.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
Status HeaderAbiDiff::GenerateCompatibilityReport() {
|
||||||
|
abi_dump::TranslationUnit old_tu;
|
||||||
|
abi_dump::TranslationUnit new_tu;
|
||||||
|
std::ifstream old_input(old_dump_);
|
||||||
|
std::ifstream new_input(new_dump_);
|
||||||
|
google::protobuf::io::IstreamInputStream text_iso(&old_input);
|
||||||
|
google::protobuf::io::IstreamInputStream text_isn(&new_input);
|
||||||
|
|
||||||
|
if (!google::protobuf::TextFormat::Parse(&text_iso, &old_tu) ||
|
||||||
|
!google::protobuf::TextFormat::Parse(&text_isn, &new_tu)) {
|
||||||
|
llvm::errs() << "Failed to Parse Input\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
return CompareTUs(old_tu, new_tu);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HeaderAbiDiff::CompareTUs(const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu) {
|
||||||
|
abi_diff::TranslationUnitDiff diff_tu;
|
||||||
|
Status record_Status = CollectRecords(&diff_tu, old_tu, new_tu);
|
||||||
|
Status function_Status = CollectFunctions(&diff_tu, old_tu, new_tu);
|
||||||
|
Status enum_Status = CollectEnums(&diff_tu, old_tu, new_tu);
|
||||||
|
|
||||||
|
Status combined_Status = record_Status | function_Status | enum_Status;
|
||||||
|
|
||||||
|
std::ofstream text_output(cr_);
|
||||||
|
google::protobuf::io::OstreamOutputStream text_os(&text_output);
|
||||||
|
|
||||||
|
if(!google::protobuf::TextFormat::Print(diff_tu, &text_os)) {
|
||||||
|
llvm::errs() << "Unable to dump report\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
if (combined_Status & INCOMPATIBLE) {
|
||||||
|
return INCOMPATIBLE;
|
||||||
|
}
|
||||||
|
if (combined_Status & EXTENSION) {
|
||||||
|
return EXTENSION;
|
||||||
|
}
|
||||||
|
return COMPATIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HeaderAbiDiff::CollectRecords(abi_diff::TranslationUnitDiff *diff_tu,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu) {
|
||||||
|
AddToMap(&old_dump_records_, old_tu.records());
|
||||||
|
AddToMap(&new_dump_records_, new_tu.records());
|
||||||
|
|
||||||
|
if (!PopulateRemovedElements(diff_tu->mutable_records_removed(),
|
||||||
|
old_dump_records_, new_dump_records_) ||
|
||||||
|
!PopulateRemovedElements(diff_tu->mutable_records_removed(),
|
||||||
|
new_dump_records_, old_dump_records_) ||
|
||||||
|
!PopulateCommonElements(diff_tu->mutable_records_diff(),old_dump_records_,
|
||||||
|
new_dump_records_)) {
|
||||||
|
llvm::errs() << "Populating records in report failed\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
if (diff_tu->records_diff().size() || diff_tu->records_removed().size()) {
|
||||||
|
return INCOMPATIBLE;
|
||||||
|
}
|
||||||
|
if (diff_tu->records_added().size()) {
|
||||||
|
return EXTENSION;
|
||||||
|
}
|
||||||
|
return COMPATIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HeaderAbiDiff::CollectFunctions(
|
||||||
|
abi_diff::TranslationUnitDiff *diff_tu,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu) {
|
||||||
|
AddToMap(&old_dump_functions_, old_tu.functions());
|
||||||
|
AddToMap(&new_dump_functions_, new_tu.functions());
|
||||||
|
|
||||||
|
if (!PopulateRemovedElements(diff_tu->mutable_functions_removed(),
|
||||||
|
old_dump_functions_, new_dump_functions_) ||
|
||||||
|
!PopulateRemovedElements(diff_tu->mutable_functions_added(),
|
||||||
|
new_dump_functions_, old_dump_functions_)) {
|
||||||
|
llvm::errs() << "Populating functions in report failed\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
if (diff_tu->functions_removed().size()) {
|
||||||
|
return INCOMPATIBLE;
|
||||||
|
}
|
||||||
|
if (diff_tu->functions_added().size()) {
|
||||||
|
return EXTENSION;
|
||||||
|
}
|
||||||
|
return COMPATIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status HeaderAbiDiff::CollectEnums(abi_diff::TranslationUnitDiff *diff_tu,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu) {
|
||||||
|
AddToMap(&old_dump_enums_, old_tu.enums());
|
||||||
|
AddToMap(&new_dump_enums_, new_tu.enums());
|
||||||
|
|
||||||
|
if (!PopulateRemovedElements(diff_tu->mutable_enums_removed(),
|
||||||
|
old_dump_enums_, new_dump_enums_) ||
|
||||||
|
!PopulateRemovedElements(diff_tu->mutable_enums_added(), new_dump_enums_,
|
||||||
|
old_dump_enums_) ||
|
||||||
|
!PopulateCommonElements(diff_tu->mutable_enums_diff(),old_dump_enums_,
|
||||||
|
new_dump_enums_)) {
|
||||||
|
llvm::errs() << "Populating enums in report failed\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
if (diff_tu->enums_removed().size() || diff_tu->enums_diff().size()) {
|
||||||
|
return INCOMPATIBLE;
|
||||||
|
}
|
||||||
|
if (diff_tu->enums_added().size()) {
|
||||||
|
return EXTENSION;
|
||||||
|
}
|
||||||
|
return COMPATIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool HeaderAbiDiff::PopulateRemovedElements(
|
||||||
|
google::protobuf::RepeatedPtrField<T> *dst,
|
||||||
|
const std::map<std::string, const T*> &old_elements_map,
|
||||||
|
const std::map<std::string, const T*> &new_elements_map) const {
|
||||||
|
|
||||||
|
std::vector<const T *> removed_elements;
|
||||||
|
for (auto &&map_element : old_elements_map) {
|
||||||
|
const T *element = map_element.second;
|
||||||
|
auto new_element = new_elements_map.find(element->linker_set_key());
|
||||||
|
if (new_element == new_elements_map.end()) {
|
||||||
|
removed_elements.emplace_back(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!DumpLoneElements(dst, removed_elements)) {
|
||||||
|
llvm::errs() << "Dumping added / removed element to report failed\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
bool HeaderAbiDiff::PopulateCommonElements(
|
||||||
|
google::protobuf::RepeatedPtrField<TDiff> *dst,
|
||||||
|
const std::map<std::string, const T *> &old_elements_map,
|
||||||
|
const std::map<std::string, const T *> &new_elements_map) const {
|
||||||
|
std::vector<std::pair<const T *, const T *>> common_elements;
|
||||||
|
typename std::map<std::string, const T *>::const_iterator old_element =
|
||||||
|
old_elements_map.begin();
|
||||||
|
typename std::map<std::string, const T *>::const_iterator new_element =
|
||||||
|
new_elements_map.begin();
|
||||||
|
while (old_element != old_elements_map.end() &&
|
||||||
|
new_element != new_elements_map.end()) {
|
||||||
|
if (old_element->first == new_element->first) {
|
||||||
|
common_elements.emplace_back(std::make_pair(
|
||||||
|
old_element->second, new_element->second));
|
||||||
|
old_element++;
|
||||||
|
new_element++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (old_element->first < new_element->first) {
|
||||||
|
old_element++;
|
||||||
|
} else {
|
||||||
|
new_element++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!DumpDiffElements(dst, common_elements)) {
|
||||||
|
llvm::errs() << "Dumping difference in common element to report failed\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool HeaderAbiDiff::DumpLoneElements(google::protobuf::RepeatedPtrField<T> *dst,
|
||||||
|
std::vector<const T *> &elements) const {
|
||||||
|
for (auto &&element : elements) {
|
||||||
|
T *added_element = dst->Add();
|
||||||
|
if (!added_element) {
|
||||||
|
llvm::errs() << "Adding element diff failed\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*added_element = *element;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
bool HeaderAbiDiff::DumpDiffElements(
|
||||||
|
google::protobuf::RepeatedPtrField<TDiff> *dst,
|
||||||
|
std::vector<std::pair<const T *,const T *>> &pairs) const {
|
||||||
|
for (auto &&pair : pairs) {
|
||||||
|
const T *old_element = pair.first;
|
||||||
|
const T *new_element = pair.second;
|
||||||
|
// Not having inheritance from protobuf messages makes this
|
||||||
|
// restrictive code.
|
||||||
|
abi_diff_wrappers::DiffWrapper<T, TDiff> diff_wrapper(old_element,
|
||||||
|
new_element);
|
||||||
|
std::unique_ptr<TDiff> decl_diff_ptr = diff_wrapper.Get();
|
||||||
|
if (!decl_diff_ptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TDiff *added_element_diff = dst->Add();
|
||||||
|
if (!added_element_diff) {
|
||||||
|
llvm::errs() << "Adding element diff failed\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*added_element_diff = *decl_diff_ptr;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
125
vndk/tools/header-checker/header-abi-diff/src/abi_diff.h
Normal file
125
vndk/tools/header-checker/header-abi-diff/src/abi_diff.h
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
// Copyright (C) 2016 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "abi_diff_wrappers.h"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||||
|
#include "proto/abi_dump.pb.h"
|
||||||
|
#include "proto/abi_diff.pb.h"
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderAbiDiff {
|
||||||
|
public:
|
||||||
|
enum Status {
|
||||||
|
COMPATIBLE = 1 << 0,
|
||||||
|
EXTENSION = 1 << 1,
|
||||||
|
INCOMPATIBLE = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HeaderAbiDiff(const std::string &old_dump, const std::string &new_dump,
|
||||||
|
const std::string &compatibility_report)
|
||||||
|
: old_dump_(old_dump), new_dump_(new_dump), cr_(compatibility_report) { }
|
||||||
|
|
||||||
|
Status GenerateCompatibilityReport();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Status CompareTUs(const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu);
|
||||||
|
// Collect* methods fill in the diff_tu.
|
||||||
|
Status CollectRecords(abi_diff::TranslationUnitDiff *abi_diff,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu);
|
||||||
|
|
||||||
|
Status CollectFunctions(abi_diff::TranslationUnitDiff *abi_diff,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu);
|
||||||
|
|
||||||
|
Status CollectEnums(abi_diff::TranslationUnitDiff *abi_diff,
|
||||||
|
const abi_dump::TranslationUnit &old_tu,
|
||||||
|
const abi_dump::TranslationUnit &new_tu);
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void AddToMap(std::map<std::string, const T *> *dst,
|
||||||
|
const google::protobuf::RepeatedPtrField<T> &src);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool PopulateRemovedElements(
|
||||||
|
google::protobuf::RepeatedPtrField<T> *dst,
|
||||||
|
const std::map<std::string, const T *> &old_elements_map,
|
||||||
|
const std::map<std::string, const T *> &new_elements_map) const;
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
bool PopulateCommonElements(
|
||||||
|
google::protobuf::RepeatedPtrField<TDiff> *dst,
|
||||||
|
const std::map<std::string, const T *> &old_elements_map,
|
||||||
|
const std::map<std::string, const T *> &new_elements_map) const;
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
bool DumpDiffElements(
|
||||||
|
google::protobuf::RepeatedPtrField<TDiff> *dst,
|
||||||
|
std::vector<std::pair<const T *, const T *>> &pairs) const;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool DumpLoneElements(google::protobuf::RepeatedPtrField<T> *dst,
|
||||||
|
std::vector<const T *> &elements) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string &old_dump_;
|
||||||
|
const std::string &new_dump_;
|
||||||
|
const std::string &cr_;
|
||||||
|
|
||||||
|
// HashMaps for the old tu abis
|
||||||
|
std::map<std::string, const abi_dump::RecordDecl *> old_dump_records_;
|
||||||
|
std::map<std::string, const abi_dump::FunctionDecl *> old_dump_functions_;
|
||||||
|
std::map<std::string, const abi_dump::EnumDecl *> old_dump_enums_;
|
||||||
|
|
||||||
|
// HashMaps for the new tu abis
|
||||||
|
std::map<std::string, const abi_dump::RecordDecl *> new_dump_records_;
|
||||||
|
std::map<std::string, const abi_dump::FunctionDecl *> new_dump_functions_;
|
||||||
|
std::map<std::string, const abi_dump::EnumDecl *> new_dump_enums_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef HeaderAbiDiff::Status Status;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void HeaderAbiDiff::AddToMap(
|
||||||
|
std::map<std::string, const T *> *dst,
|
||||||
|
const google::protobuf::RepeatedPtrField<T> &src) {
|
||||||
|
for (auto &&element : src) {
|
||||||
|
dst->insert(std::make_pair(element.linker_set_key(), &element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Status operator|(Status f, Status s) {
|
||||||
|
return static_cast<Status>(
|
||||||
|
static_cast<std::underlying_type<Status>::type>(f) |
|
||||||
|
static_cast<std::underlying_type<Status>::type>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Status operator&(Status f, Status s) {
|
||||||
|
return static_cast<Status>(
|
||||||
|
static_cast<std::underlying_type<Status>::type>(f) &
|
||||||
|
static_cast<std::underlying_type<Status>::type>(s));
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
// Copyright (C) 2016 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "abi_diff_wrappers.h"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||||
|
#include "proto/abi_dump.pb.h"
|
||||||
|
#include "proto/abi_diff.pb.h"
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
#include <llvm/Support/raw_ostream.h>
|
||||||
|
|
||||||
|
using abi_diff::RecordDeclDiff;
|
||||||
|
using abi_diff::FieldDeclDiff;
|
||||||
|
using abi_diff::CXXBaseSpecifierDiff;
|
||||||
|
using abi_diff::EnumDeclDiff;
|
||||||
|
using abi_diff::EnumFieldDeclDiff;
|
||||||
|
using abi_dump::RecordDecl;
|
||||||
|
using abi_dump::EnumDecl;
|
||||||
|
|
||||||
|
namespace abi_diff_wrappers {
|
||||||
|
|
||||||
|
// This function fills in a *Diff Message's repeated field. For eg:
|
||||||
|
// RecordDeclDiff's CXXBaseSpecifierDiff fields and well as FieldDeclDiff
|
||||||
|
// fields.
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
template <typename Element, typename ElementDiff>
|
||||||
|
bool DiffWrapperBase<T, TDiff>::GetElementDiffs(
|
||||||
|
google::protobuf::RepeatedPtrField<ElementDiff> *dst,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &old_elements,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &new_elements) {
|
||||||
|
bool differs = false;
|
||||||
|
assert (dst != nullptr);
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
while (i < old_elements.size() && j < new_elements.size()) {
|
||||||
|
const Element &old_element = old_elements.Get(i);
|
||||||
|
const Element &new_element = new_elements.Get(i);
|
||||||
|
if (old_element.linker_set_key() != new_element.linker_set_key()) {
|
||||||
|
ElementDiff *diff = dst->Add();
|
||||||
|
Element *old_elementp = nullptr;
|
||||||
|
Element *new_elementp = nullptr;
|
||||||
|
if (!diff || !(old_elementp = diff->mutable_old()) ||
|
||||||
|
!(new_elementp = diff->mutable_new_())) {
|
||||||
|
llvm::errs() << "Failed to add diff element\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
*old_elementp = old_element;
|
||||||
|
*new_elementp = new_element;
|
||||||
|
diff->set_index(i);
|
||||||
|
differs = true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (old_elements.size() != new_elements.size()) {
|
||||||
|
GetExtraElementDiffs(dst, i, j, old_elements, new_elements);
|
||||||
|
differs = true;
|
||||||
|
}
|
||||||
|
return differs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
template <typename Element, typename ElementDiff>
|
||||||
|
void DiffWrapperBase<T, TDiff>::GetExtraElementDiffs(
|
||||||
|
google::protobuf::RepeatedPtrField<ElementDiff> *dst, int i, int j,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &old_elements,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &new_elements) {
|
||||||
|
assert(dst != nullptr);
|
||||||
|
while (i < old_elements.size()) {
|
||||||
|
const Element &old_element = old_elements.Get(i);
|
||||||
|
ElementDiff *diff = dst->Add();
|
||||||
|
Element *old_elementp = nullptr;
|
||||||
|
if (!diff || !(old_elementp = diff->mutable_old())) {
|
||||||
|
llvm::errs() << "Failed to add diff element\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
*old_elementp = old_element;
|
||||||
|
diff->set_index(i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (j < new_elements.size()) {
|
||||||
|
const Element &new_element = new_elements.Get(j);
|
||||||
|
ElementDiff *diff = dst->Add();
|
||||||
|
Element *new_elementp = nullptr;
|
||||||
|
if (!diff || !(new_elementp = diff->mutable_new_())) {
|
||||||
|
llvm::errs() << "Failed to add diff element\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
*new_elementp = new_element;
|
||||||
|
diff->set_index(j);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::unique_ptr<RecordDeclDiff> DiffWrapper<RecordDecl, RecordDeclDiff>::Get() {
|
||||||
|
std::unique_ptr<RecordDeclDiff> record_diff(new RecordDeclDiff());
|
||||||
|
assert(oldp_->fully_qualified_name() == newp_->fully_qualified_name());
|
||||||
|
record_diff->set_name(oldp_->fully_qualified_name());
|
||||||
|
google::protobuf::RepeatedPtrField<FieldDeclDiff> *fdiffs =
|
||||||
|
record_diff->mutable_field_diffs();
|
||||||
|
google::protobuf::RepeatedPtrField<CXXBaseSpecifierDiff> *bdiffs =
|
||||||
|
record_diff->mutable_base_diffs();
|
||||||
|
assert(fdiffs != nullptr && bdiffs != nullptr);
|
||||||
|
// Template Information isn't diffed since the linker_set_key includes the
|
||||||
|
// mangled name which includes template information.
|
||||||
|
if (GetElementDiffs(fdiffs, oldp_->fields(), newp_->fields()) ||
|
||||||
|
GetElementDiffs(bdiffs, oldp_->base_specifiers(),
|
||||||
|
newp_->base_specifiers())) {
|
||||||
|
return record_diff;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::unique_ptr<EnumDeclDiff> DiffWrapper<EnumDecl, EnumDeclDiff>::Get() {
|
||||||
|
std::unique_ptr<EnumDeclDiff> enum_diff(new EnumDeclDiff());
|
||||||
|
assert(oldp_->enum_name() == newp_->enum_name());
|
||||||
|
google::protobuf::RepeatedPtrField<EnumFieldDeclDiff> *fdiffs =
|
||||||
|
enum_diff->mutable_field_diffs();
|
||||||
|
assert(fdiffs != nullptr);
|
||||||
|
if (GetElementDiffs(fdiffs, oldp_->enum_fields(), newp_->enum_fields()) ||
|
||||||
|
(oldp_->enum_type() != newp_->enum_type())) {
|
||||||
|
return enum_diff;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // abi_diff_wrappers
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (C) 2016 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
|
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||||
|
#include "proto/abi_dump.pb.h"
|
||||||
|
#include "proto/abi_diff.pb.h"
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
namespace abi_diff_wrappers {
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
class DiffWrapperBase {
|
||||||
|
public:
|
||||||
|
virtual std::unique_ptr<TDiff> Get() = 0 ;
|
||||||
|
protected:
|
||||||
|
DiffWrapperBase(const T *oldp, const T *newp)
|
||||||
|
: oldp_(oldp), newp_(newp) { }
|
||||||
|
template <typename Element, typename ElementDiff>
|
||||||
|
bool GetElementDiffs(
|
||||||
|
google::protobuf::RepeatedPtrField<ElementDiff> *dst,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &old_elements,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &new_elements);
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Element, typename ElementDiff>
|
||||||
|
void GetExtraElementDiffs(
|
||||||
|
google::protobuf::RepeatedPtrField<ElementDiff> *dst, int i, int j,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &old_elements,
|
||||||
|
const google::protobuf::RepeatedPtrField<Element> &new_elements);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const T *oldp_;
|
||||||
|
const T *newp_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename TDiff>
|
||||||
|
class DiffWrapper : public DiffWrapperBase<T, TDiff> {
|
||||||
|
public:
|
||||||
|
DiffWrapper(const T *oldp, const T *newp)
|
||||||
|
: DiffWrapperBase<T, TDiff>(oldp, newp) { }
|
||||||
|
|
||||||
|
std::unique_ptr<TDiff> Get() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // abi_diff_wrappers
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright (C) 2016 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "abi_diff.h"
|
||||||
|
|
||||||
|
#include <llvm/Support/CommandLine.h>
|
||||||
|
#include <llvm/Support/raw_ostream.h>
|
||||||
|
|
||||||
|
static llvm::cl::OptionCategory header_checker_category(
|
||||||
|
"header-abi-diff options");
|
||||||
|
|
||||||
|
static llvm::cl::opt<std::string> compatibility_report(
|
||||||
|
"o", llvm::cl::desc("<compatibility report>"), llvm::cl::Required,
|
||||||
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
|
static llvm::cl::opt<std::string> new_dump(
|
||||||
|
"new", llvm::cl::desc("<new dump>"), llvm::cl::Required,
|
||||||
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
|
static llvm::cl::opt<std::string> old_dump(
|
||||||
|
"old", llvm::cl::desc("<old dump>"), llvm::cl::Required,
|
||||||
|
llvm::cl::cat(header_checker_category));
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
|
llvm::cl::ParseCommandLineOptions(argc, argv, "header-checker");
|
||||||
|
HeaderAbiDiff judge(old_dump, new_dump, compatibility_report);
|
||||||
|
switch (judge.GenerateCompatibilityReport()) {
|
||||||
|
case HeaderAbiDiff::COMPATIBLE:
|
||||||
|
case HeaderAbiDiff::EXTENSION:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
llvm::errs() << "******************************************************\n"
|
||||||
|
<< "VNDK Abi Compliance breakage:"
|
||||||
|
<< " Please check compatiblity report at : "
|
||||||
|
<< compatibility_report << "\n"
|
||||||
|
<< "*****************************************************\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -225,9 +225,13 @@ bool RecordDeclWrapper::SetupRecordFields(
|
|||||||
<< " to reference dump\n";
|
<< " to reference dump\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
record_fieldp->set_field_name(field->getName());
|
std::string name = field->getName();
|
||||||
record_fieldp->set_field_type(QualTypeToString(field->getType()));
|
std::string type = QualTypeToString(field->getType());
|
||||||
record_fieldp->set_access(AccessToString(field->getAccess()));
|
std::string access = AccessToString(field->getAccess());
|
||||||
|
record_fieldp->set_field_name(name);
|
||||||
|
record_fieldp->set_field_type(type);
|
||||||
|
record_fieldp->set_access(access);
|
||||||
|
record_fieldp->set_linker_set_key(name + type + access);
|
||||||
field++;
|
field++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -248,11 +252,14 @@ bool RecordDeclWrapper::SetupCXXBases(abi_dump::RecordDecl *cxxp) const {
|
|||||||
llvm::errs() << " Couldn't add base specifier to reference dump\n";
|
llvm::errs() << " Couldn't add base specifier to reference dump\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
base_specifierp->set_fully_qualified_name(
|
std::string name = QualTypeToString(base_class->getType());
|
||||||
QualTypeToString(base_class->getType()));
|
bool is_virtual = base_class->isVirtual();
|
||||||
base_specifierp->set_is_virtual(base_class->isVirtual());
|
char is_virtual_c = is_virtual ? 't' : 'f';
|
||||||
base_specifierp->set_access(
|
std::string access = AccessToString(base_class->getAccessSpecifier());
|
||||||
AccessToString(base_class->getAccessSpecifier()));
|
base_specifierp->set_fully_qualified_name(name);
|
||||||
|
base_specifierp->set_is_virtual(is_virtual);
|
||||||
|
base_specifierp->set_access(access);
|
||||||
|
base_specifierp->set_linker_set_key(name + is_virtual_c + access);
|
||||||
base_class++;
|
base_class++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -298,9 +305,11 @@ bool RecordDeclWrapper::SetupTemplateInfo(
|
|||||||
void RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp,
|
void RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp,
|
||||||
const std::string &source_file) const {
|
const std::string &source_file) const {
|
||||||
std::string qualified_name = GetTagDeclQualifiedName(record_decl_);
|
std::string qualified_name = GetTagDeclQualifiedName(record_decl_);
|
||||||
|
std::string mangled_name = GetMangledNameDecl(record_decl_);
|
||||||
|
std::string linker_key = (mangled_name == "") ? qualified_name : mangled_name;
|
||||||
record_declp->set_fully_qualified_name(qualified_name);
|
record_declp->set_fully_qualified_name(qualified_name);
|
||||||
//TODO: Add Template Information
|
record_declp->set_mangled_record_name(mangled_name);
|
||||||
record_declp->set_linker_set_key(qualified_name);
|
record_declp->set_linker_set_key(linker_key);
|
||||||
record_declp->set_source_file(source_file);
|
record_declp->set_source_file(source_file);
|
||||||
record_declp->set_access(AccessToString(record_decl_->getAccess()));
|
record_declp->set_access(AccessToString(record_decl_->getAccess()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class RecordDeclWrapper : public ABIWrapper {
|
|||||||
void SetupRecordInfo(abi_dump::RecordDecl *record_declp,
|
void SetupRecordInfo(abi_dump::RecordDecl *record_declp,
|
||||||
const std::string &source_file) const;
|
const std::string &source_file) const;
|
||||||
|
|
||||||
bool SetupRecordFields(abi_dump::RecordDecl *recordp,
|
bool SetupRecordFields(abi_dump::RecordDecl *record_declp,
|
||||||
const std::string &source_file) const;
|
const std::string &source_file) const;
|
||||||
|
|
||||||
bool SetupCXXBases(abi_dump::RecordDecl *cxxp) const;
|
bool SetupCXXBases(abi_dump::RecordDecl *cxxp) const;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <clang/Tooling/Core/QualTypeNames.h>
|
#include <clang/Tooling/Core/QualTypeNames.h>
|
||||||
|
|
||||||
#include <google/protobuf/text_format.h>
|
#include <google/protobuf/text_format.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -128,11 +129,8 @@ HeaderASTConsumer::HeaderASTConsumer(
|
|||||||
|
|
||||||
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
std::ofstream text_output(out_dump_name_ + ".txt");
|
std::ofstream text_output(out_dump_name_);
|
||||||
std::fstream binary_output(
|
google::protobuf::io::OstreamOutputStream text_os(&text_output);
|
||||||
out_dump_name_,
|
|
||||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
|
||||||
|
|
||||||
clang::TranslationUnitDecl* translation_unit = ctx.getTranslationUnitDecl();
|
clang::TranslationUnitDecl* translation_unit = ctx.getTranslationUnitDecl();
|
||||||
std::unique_ptr<clang::MangleContext> mangle_contextp(
|
std::unique_ptr<clang::MangleContext> mangle_contextp(
|
||||||
ctx.createMangleContext());
|
ctx.createMangleContext());
|
||||||
@@ -141,12 +139,10 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
|||||||
HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_, file_name_,
|
HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_, file_name_,
|
||||||
exported_headers_);
|
exported_headers_);
|
||||||
if (!v.TraverseDecl(translation_unit) ||
|
if (!v.TraverseDecl(translation_unit) ||
|
||||||
!google::protobuf::TextFormat::PrintToString(tu, &str_out) ||
|
!google::protobuf::TextFormat::Print(tu, &text_os)) {
|
||||||
!tu.SerializeToOstream(&binary_output)) {
|
|
||||||
llvm::errs() << "Serialization to ostream failed\n";
|
llvm::errs() << "Serialization to ostream failed\n";
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
text_output << str_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeaderASTConsumer::HandleVTable(clang::CXXRecordDecl *crd) {
|
void HeaderASTConsumer::HandleVTable(clang::CXXRecordDecl *crd) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <google/protobuf/text_format.h>
|
#include <google/protobuf/text_format.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -78,15 +79,13 @@ class HeaderAbiLinker {
|
|||||||
|
|
||||||
bool HeaderAbiLinker::LinkAndDump() {
|
bool HeaderAbiLinker::LinkAndDump() {
|
||||||
abi_dump::TranslationUnit linked_tu;
|
abi_dump::TranslationUnit linked_tu;
|
||||||
std::string str_out;
|
std::ofstream text_output(out_dump_name_);
|
||||||
std::ofstream text_output(out_dump_name_ + ".txt");
|
google::protobuf::io::OstreamOutputStream text_os(&text_output);
|
||||||
std::fstream binary_output(
|
|
||||||
out_dump_name_,
|
|
||||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
|
||||||
for (auto &&i : dump_files_) {
|
for (auto &&i : dump_files_) {
|
||||||
abi_dump::TranslationUnit dump_tu;
|
abi_dump::TranslationUnit dump_tu;
|
||||||
std::fstream input(i, std::ios::binary | std::ios::in);
|
std::ifstream input(i);
|
||||||
if (!dump_tu.ParseFromIstream(&input) ||
|
google::protobuf::io::IstreamInputStream text_is(&input);
|
||||||
|
if (!google::protobuf::TextFormat::Parse(&text_is, &dump_tu) ||
|
||||||
!LinkRecords(dump_tu, &linked_tu) ||
|
!LinkRecords(dump_tu, &linked_tu) ||
|
||||||
!LinkFunctions(dump_tu, &linked_tu) ||
|
!LinkFunctions(dump_tu, &linked_tu) ||
|
||||||
!LinkEnums(dump_tu, &linked_tu)) {
|
!LinkEnums(dump_tu, &linked_tu)) {
|
||||||
@@ -95,13 +94,10 @@ bool HeaderAbiLinker::LinkAndDump() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!google::protobuf::TextFormat::PrintToString(linked_tu, &str_out) ||
|
if (!google::protobuf::TextFormat::Print(linked_tu, &text_os)) {
|
||||||
!linked_tu.SerializeToOstream(&binary_output)) {
|
|
||||||
llvm::errs() << "Serialization to ostream failed\n";
|
llvm::errs() << "Serialization to ostream failed\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
text_output << str_out;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
55
vndk/tools/header-checker/proto/abi_diff.proto
Normal file
55
vndk/tools/header-checker/proto/abi_diff.proto
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
import "development/vndk/tools/header-checker/proto/abi_dump.proto";
|
||||||
|
|
||||||
|
package abi_diff;
|
||||||
|
|
||||||
|
message FieldDeclDiff {
|
||||||
|
optional abi_dump.FieldDecl old = 1;
|
||||||
|
optional abi_dump.FieldDecl new = 2;
|
||||||
|
required uint32 index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumFieldDeclDiff {
|
||||||
|
optional abi_dump.EnumFieldDecl old = 1;
|
||||||
|
optional abi_dump.EnumFieldDecl new = 2;
|
||||||
|
required uint32 index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CXXBaseSpecifierDiff {
|
||||||
|
optional abi_dump.CXXBaseSpecifier old = 1;
|
||||||
|
optional abi_dump.CXXBaseSpecifier new = 2;
|
||||||
|
required uint32 index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AccessDiff {
|
||||||
|
required string old = 1;
|
||||||
|
required string new = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RecordDeclDiff {
|
||||||
|
repeated FieldDeclDiff field_diffs = 1;
|
||||||
|
repeated CXXBaseSpecifierDiff base_diffs = 2;
|
||||||
|
required AccessDiff access_diff = 3;
|
||||||
|
required string name = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumDeclDiff {
|
||||||
|
repeated EnumFieldDeclDiff field_diffs = 1;
|
||||||
|
optional AccessDiff access_diff = 2;
|
||||||
|
required string name = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TranslationUnitDiff {
|
||||||
|
// Differing Elements.
|
||||||
|
repeated RecordDeclDiff records_diff = 1;
|
||||||
|
repeated EnumDeclDiff enums_diff = 3;
|
||||||
|
// Removed Elements.
|
||||||
|
repeated abi_dump.RecordDecl records_removed = 4;
|
||||||
|
repeated abi_dump.FunctionDecl functions_removed = 5;
|
||||||
|
repeated abi_dump.EnumDecl enums_removed = 6;
|
||||||
|
// Added Elements.
|
||||||
|
repeated abi_dump.RecordDecl records_added = 7;
|
||||||
|
repeated abi_dump.FunctionDecl functions_added = 8;
|
||||||
|
repeated abi_dump.EnumDecl enums_added = 9;
|
||||||
|
}
|
||||||
@@ -25,11 +25,13 @@ message FieldDecl {
|
|||||||
optional string field_type = 2 [default = "VOID"];
|
optional string field_type = 2 [default = "VOID"];
|
||||||
optional string access = 3 [default = "public"];
|
optional string access = 3 [default = "public"];
|
||||||
optional bool default_arg = 4 [default = false];
|
optional bool default_arg = 4 [default = false];
|
||||||
|
optional string linker_set_key = 5 [default = "NONE"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumFieldDecl {
|
message EnumFieldDecl {
|
||||||
optional string enum_field_name = 1 [default = "NONE"];
|
optional string enum_field_name = 1 [default = "NONE"];
|
||||||
optional int64 enum_field_value = 2 [default = 0]; // assumption: fits int64
|
optional int64 enum_field_value = 2 [default = 0]; // assumption: fits int64
|
||||||
|
optional string linker_set_key = 3 [default = "NONE"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message TemplateInfo {
|
message TemplateInfo {
|
||||||
@@ -40,19 +42,19 @@ message CXXBaseSpecifier {
|
|||||||
optional string fully_qualified_name = 1 [default = "NONE"];
|
optional string fully_qualified_name = 1 [default = "NONE"];
|
||||||
optional string access = 2 [default = "public"];
|
optional string access = 2 [default = "public"];
|
||||||
optional bool is_virtual = 3 [default = false];
|
optional bool is_virtual = 3 [default = false];
|
||||||
|
optional string linker_set_key = 4 [default = "NONE"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message RecordDecl {
|
message RecordDecl {
|
||||||
repeated FieldDecl fields = 2;
|
repeated FieldDecl fields = 1;
|
||||||
repeated string inner_classes = 3;
|
repeated CXXBaseSpecifier base_specifiers = 2;
|
||||||
repeated CXXBaseSpecifier base_specifiers = 4;
|
optional string fully_qualified_name = 3 [default = "NONE"];
|
||||||
optional string fully_qualified_name = 5 [default = "NONE"];
|
optional string source_file = 4 [default = "NONE"];
|
||||||
optional int64 id = 6 [default = 0];
|
optional uint32 template_kind = 5 [default = 0];
|
||||||
optional string source_file = 9 [default = "NONE"];
|
optional TemplateInfo template_info = 6;
|
||||||
optional string template_kind = 11 [default = "NONE"];
|
optional string access = 7 [default = "public"];
|
||||||
optional TemplateInfo template_info = 12;
|
optional string linker_set_key = 8 [default = "NONE"];
|
||||||
optional string access = 13 [default = "public"];
|
optional string mangled_record_name = 9 [default = "NONE"];
|
||||||
optional string linker_set_key = 14 [default = "NONE"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message EnumDecl {
|
message EnumDecl {
|
||||||
|
|||||||
Reference in New Issue
Block a user