diff --git a/vndk/tools/header-checker/Android.bp b/vndk/tools/header-checker/Android.bp index 3cdec178d..8c97386b8 100644 --- a/vndk/tools/header-checker/Android.bp +++ b/vndk/tools/header-checker/Android.bp @@ -26,6 +26,7 @@ cc_defaults { "-Werror", "-std=c++11", "-DGOOGLE_PROTOBUF_NO_RTTI", + "-UNDEBUG" ], target: { diff --git a/vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp b/vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp index ffa118ecd..2a61357e9 100644 --- a/vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp +++ b/vndk/tools/header-checker/header-abi-diff/src/abi_diff.cpp @@ -45,95 +45,76 @@ Status HeaderAbiDiff::GenerateCompatibilityReport() { 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); + std::unique_ptr diff_tu( + new abi_diff::TranslationUnitDiff); - Status combined_Status = record_Status | function_Status | enum_Status; + Status record_status = Collect( + diff_tu->mutable_records_added(), diff_tu->mutable_records_removed(), + diff_tu->mutable_records_diff(), old_tu.records(), new_tu.records()); + + Status function_status = Collect( + diff_tu->mutable_functions_added(), diff_tu->mutable_functions_removed(), + diff_tu->mutable_functions_diff(), old_tu.functions(), + new_tu.functions()); + + Status enum_status = Collect( + diff_tu->mutable_enums_added(), diff_tu->mutable_enums_removed(), + diff_tu->mutable_enums_diff(), old_tu.enums(), new_tu.enums()); + + Status global_var_status = Collect( + diff_tu->mutable_global_vars_added(), + diff_tu->mutable_global_vars_removed(), + diff_tu->mutable_global_vars_diff(), old_tu.global_vars(), + new_tu.global_vars()); + + Status combined_status = + record_status | function_status | enum_status | global_var_status; std::ofstream text_output(cr_); google::protobuf::io::OstreamOutputStream text_os(&text_output); - if(!google::protobuf::TextFormat::Print(diff_tu, &text_os)) { + if(!google::protobuf::TextFormat::Print(*diff_tu, &text_os)) { llvm::errs() << "Unable to dump report\n"; ::exit(1); } - if (combined_Status & INCOMPATIBLE) { + if (combined_status & INCOMPATIBLE) { return INCOMPATIBLE; } - if (combined_Status & EXTENSION) { + 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()); +template +Status HeaderAbiDiff::Collect( + google::protobuf::RepeatedPtrField *elements_added, + google::protobuf::RepeatedPtrField *elements_removed, + google::protobuf::RepeatedPtrField *elements_diff, + const google::protobuf::RepeatedPtrField &old_srcs, + const google::protobuf::RepeatedPtrField &new_srcs) { + assert(elements_added != nullptr); + assert(elements_removed != nullptr); + assert(elements_diff != nullptr); - 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; -} + std::map old_elements_map; + std::map new_elements_map; + AddToMap(&old_elements_map, old_srcs); + AddToMap(&new_elements_map, new_srcs); -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_)) { + if (!PopulateRemovedElements(elements_removed, old_elements_map, + new_elements_map) || + !PopulateRemovedElements(elements_added, new_elements_map, + old_elements_map) || + !PopulateCommonElements(elements_diff, old_elements_map, + new_elements_map)) { llvm::errs() << "Populating functions in report failed\n"; ::exit(1); } - if (diff_tu->functions_removed().size()) { + if (elements_diff->size() || elements_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()) { + if (elements_added->size()) { return EXTENSION; } return COMPATIBLE; @@ -143,12 +124,13 @@ template bool HeaderAbiDiff::PopulateRemovedElements( google::protobuf::RepeatedPtrField *dst, const std::map &old_elements_map, - const std::map &new_elements_map) const { + const std::map &new_elements_map) { std::vector 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()); + auto new_element = + new_elements_map.find(element->basic_abi().linker_set_key()); if (new_element == new_elements_map.end()) { removed_elements.emplace_back(element); } @@ -164,7 +146,7 @@ template bool HeaderAbiDiff::PopulateCommonElements( google::protobuf::RepeatedPtrField *dst, const std::map &old_elements_map, - const std::map &new_elements_map) const { + const std::map &new_elements_map) { std::vector> common_elements; typename std::map::const_iterator old_element = old_elements_map.begin(); @@ -194,7 +176,7 @@ bool HeaderAbiDiff::PopulateCommonElements( template bool HeaderAbiDiff::DumpLoneElements(google::protobuf::RepeatedPtrField *dst, - std::vector &elements) const { + std::vector &elements) { for (auto &&element : elements) { T *added_element = dst->Add(); if (!added_element) { @@ -209,7 +191,7 @@ bool HeaderAbiDiff::DumpLoneElements(google::protobuf::RepeatedPtrField *dst, template bool HeaderAbiDiff::DumpDiffElements( google::protobuf::RepeatedPtrField *dst, - std::vector> &pairs) const { + std::vector> &pairs) { for (auto &&pair : pairs) { const T *old_element = pair.first; const T *new_element = pair.second; diff --git a/vndk/tools/header-checker/header-abi-diff/src/abi_diff.h b/vndk/tools/header-checker/header-abi-diff/src/abi_diff.h index 7ee0245ae..c52476ba7 100644 --- a/vndk/tools/header-checker/header-abi-diff/src/abi_diff.h +++ b/vndk/tools/header-checker/header-abi-diff/src/abi_diff.h @@ -47,58 +47,43 @@ class HeaderAbiDiff { 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 + static Status Collect( + google::protobuf::RepeatedPtrField *elements_added, + google::protobuf::RepeatedPtrField *elements_removed, + google::protobuf::RepeatedPtrField *elements_diff, + const google::protobuf::RepeatedPtrField &old_srcs, + const google::protobuf::RepeatedPtrField &new_srcs); template - inline void AddToMap(std::map *dst, - const google::protobuf::RepeatedPtrField &src); + static inline void AddToMap(std::map *dst, + const google::protobuf::RepeatedPtrField &src); template - bool PopulateRemovedElements( + static bool PopulateRemovedElements( google::protobuf::RepeatedPtrField *dst, const std::map &old_elements_map, - const std::map &new_elements_map) const; + const std::map &new_elements_map); template - bool PopulateCommonElements( + static bool PopulateCommonElements( google::protobuf::RepeatedPtrField *dst, const std::map &old_elements_map, - const std::map &new_elements_map) const; + const std::map &new_elements_map); template - bool DumpDiffElements( + static bool DumpDiffElements( google::protobuf::RepeatedPtrField *dst, - std::vector> &pairs) const; + std::vector> &pairs); template - bool DumpLoneElements(google::protobuf::RepeatedPtrField *dst, - std::vector &elements) const; + static bool DumpLoneElements(google::protobuf::RepeatedPtrField *dst, + std::vector &elements); private: const std::string &old_dump_; const std::string &new_dump_; const std::string &cr_; - - // HashMaps for the old tu abis - std::map old_dump_records_; - std::map old_dump_functions_; - std::map old_dump_enums_; - - // HashMaps for the new tu abis - std::map new_dump_records_; - std::map new_dump_functions_; - std::map new_dump_enums_; }; typedef HeaderAbiDiff::Status Status; @@ -108,7 +93,7 @@ inline void HeaderAbiDiff::AddToMap( std::map *dst, const google::protobuf::RepeatedPtrField &src) { for (auto &&element : src) { - dst->insert(std::make_pair(element.linker_set_key(), &element)); + dst->insert(std::make_pair(element.basic_abi().linker_set_key(), &element)); } } diff --git a/vndk/tools/header-checker/header-abi-diff/src/abi_diff_wrappers.cpp b/vndk/tools/header-checker/header-abi-diff/src/abi_diff_wrappers.cpp index b2809ba5a..c886315f5 100644 --- a/vndk/tools/header-checker/header-abi-diff/src/abi_diff_wrappers.cpp +++ b/vndk/tools/header-checker/header-abi-diff/src/abi_diff_wrappers.cpp @@ -24,15 +24,93 @@ #include using abi_diff::RecordDeclDiff; -using abi_diff::FieldDeclDiff; +using abi_diff::RecordFieldDeclDiff; using abi_diff::CXXBaseSpecifierDiff; +using abi_diff::CXXVTableDiff; +using abi_diff::EnumDeclDiff; +using abi_diff::ReturnTypeDiff; +using abi_diff::FunctionDeclDiff; using abi_diff::EnumDeclDiff; using abi_diff::EnumFieldDeclDiff; +using abi_diff::GlobalVarDeclDiff; using abi_dump::RecordDecl; +using abi_dump::RecordFieldDecl; using abi_dump::EnumDecl; +using abi_dump::EnumFieldDecl; +using abi_dump::FunctionDecl; +using abi_dump::ParamDecl; +using abi_dump::VTableComponent; +using abi_dump::CXXBaseSpecifier; +using abi_dump::GlobalVarDecl; namespace abi_diff_wrappers { +static bool IsAccessDownGraded(abi_dump::AccessSpecifier old_access, + abi_dump::AccessSpecifier new_access) { + bool access_downgraded = false; + switch (old_access) { + case abi_dump::AccessSpecifier::protected_access: + if (new_access == abi_dump::AccessSpecifier::private_access) { + access_downgraded = true; + } + break; + case abi_dump::AccessSpecifier::public_access: + if (new_access != abi_dump::AccessSpecifier::public_access) { + access_downgraded = true; + } + break; + default: + break; + } + return access_downgraded; +} + +static bool DiffBasicTypeAbi(const abi_dump::BasicTypeAbi &old_abi, + const abi_dump::BasicTypeAbi &new_abi) { + bool name_comparison = (old_abi.name() != new_abi.name()); + bool size_comparison = (old_abi.size() != new_abi.size()); + bool alignment_comparison = (old_abi.alignment() != new_abi.alignment()); + return name_comparison || size_comparison || alignment_comparison; +} + +template +static bool Diff(const T &old_element, const T &new_element) { + // Can be specialized for future changes in the format. + return DiffBasicTypeAbi(old_element.basic_abi().type_abi(), + new_element.basic_abi().type_abi()) || + IsAccessDownGraded(old_element.basic_abi().access(), + new_element.basic_abi().access()); +} + +template <> +bool Diff(const EnumFieldDecl &old_element, + const EnumFieldDecl &new_element) { + // Can be specialized for future changes in the format. + return DiffBasicTypeAbi(old_element.basic_abi().type_abi(), + new_element.basic_abi().type_abi()) || + (old_element.enum_field_value() != new_element.enum_field_value()); +} + +template <> +bool Diff(const CXXBaseSpecifier &old_element, + const CXXBaseSpecifier &new_element) { + // Can be specialized for future changes in the format. + return (DiffBasicTypeAbi(old_element.basic_abi().type_abi(), + new_element.basic_abi().type_abi()) || + old_element.basic_abi().access() != new_element.basic_abi().access() || + old_element.is_virtual() != new_element.is_virtual()); +} + +template <> +bool Diff(const VTableComponent &old_element, + const VTableComponent &new_element) { + bool kind_comparison = old_element.kind() != new_element.kind(); + bool mangled_name_comparison = old_element.mangled_component_name() != + new_element.mangled_component_name(); + bool value_comparison = old_element.value() != new_element.value(); + return kind_comparison || mangled_name_comparison || value_comparison; +} + // This function fills in a *Diff Message's repeated field. For eg: // RecordDeclDiff's CXXBaseSpecifierDiff fields and well as FieldDeclDiff // fields. @@ -43,13 +121,14 @@ bool DiffWrapperBase::GetElementDiffs( const google::protobuf::RepeatedPtrField &old_elements, const google::protobuf::RepeatedPtrField &new_elements) { bool differs = false; - assert (dst != nullptr); + 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()) { + + if (Diff(old_element, new_element)) { ElementDiff *diff = dst->Add(); Element *old_elementp = nullptr; Element *new_elementp = nullptr; @@ -109,18 +188,22 @@ void DiffWrapperBase::GetExtraElementDiffs( template <> std::unique_ptr DiffWrapper::Get() { std::unique_ptr record_diff(new RecordDeclDiff()); - assert(oldp_->fully_qualified_name() == newp_->fully_qualified_name()); - record_diff->set_name(oldp_->fully_qualified_name()); - google::protobuf::RepeatedPtrField *fdiffs = + assert(oldp_->basic_abi().name() == newp_->basic_abi().name()); + record_diff->set_name(oldp_->basic_abi().name()); + google::protobuf::RepeatedPtrField *fdiffs = record_diff->mutable_field_diffs(); google::protobuf::RepeatedPtrField *bdiffs = record_diff->mutable_base_diffs(); + google::protobuf::RepeatedPtrField *vtdiffs = + record_diff->mutable_vtable_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())) { + newp_->base_specifiers()) || + GetElementDiffs(vtdiffs, oldp_->vtable_layout().vtable_components(), + newp_->vtable_layout().vtable_components())) { return record_diff; } return nullptr; @@ -129,15 +212,51 @@ std::unique_ptr DiffWrapper::Get() { template <> std::unique_ptr DiffWrapper::Get() { std::unique_ptr enum_diff(new EnumDeclDiff()); - assert(oldp_->enum_name() == newp_->enum_name()); + assert(oldp_->basic_abi().name() == newp_->basic_abi().name()); google::protobuf::RepeatedPtrField *fdiffs = enum_diff->mutable_field_diffs(); assert(fdiffs != nullptr); - if (GetElementDiffs(fdiffs, oldp_->enum_fields(), newp_->enum_fields()) || - (oldp_->enum_type() != newp_->enum_type())) { + if (GetElementDiffs(fdiffs, oldp_->enum_fields(), newp_->enum_fields())) { return enum_diff; } return nullptr; } +template <> +std::unique_ptr +DiffWrapper::Get() { + std::unique_ptr func_diff(new FunctionDeclDiff()); + if (DiffBasicTypeAbi(oldp_->basic_abi().type_abi(), + newp_->basic_abi().type_abi()) || + IsAccessDownGraded(oldp_->basic_abi().access(), + newp_->basic_abi().access())) { + assert(func_diff->mutable_return_type_diffs() != nullptr && + func_diff->mutable_return_type_diffs()->mutable_old() != nullptr && + func_diff->mutable_return_type_diffs()->mutable_new_() != nullptr); + *(func_diff->mutable_return_type_diffs()->mutable_old()) = + oldp_->basic_abi(); + *(func_diff->mutable_return_type_diffs()->mutable_new_()) = + newp_->basic_abi(); + return func_diff; + } + return nullptr; +} + +template <> +std::unique_ptr +DiffWrapper::Get() { + std::unique_ptr global_var_diff(new GlobalVarDeclDiff()); + if (DiffBasicTypeAbi(oldp_->basic_abi().type_abi(), + newp_->basic_abi().type_abi()) || + IsAccessDownGraded(oldp_->basic_abi().access(), + newp_->basic_abi().access())) { + assert(global_var_diff->mutable_old() != nullptr); + assert(global_var_diff->mutable_new_() != nullptr); + *(global_var_diff->mutable_old()) = oldp_->basic_abi(); + *(global_var_diff->mutable_new_()) = newp_->basic_abi(); + return global_var_diff; + } + return nullptr; +} + } // abi_diff_wrappers diff --git a/vndk/tools/header-checker/header-abi-diff/src/header_abi_diff.cpp b/vndk/tools/header-checker/header-abi-diff/src/header_abi_diff.cpp index 13fc0df81..226e0f487 100644 --- a/vndk/tools/header-checker/header-abi-diff/src/header_abi_diff.cpp +++ b/vndk/tools/header-checker/header-abi-diff/src/header_abi_diff.cpp @@ -35,17 +35,24 @@ static llvm::cl::opt old_dump( int main(int argc, const char **argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; llvm::cl::ParseCommandLineOptions(argc, argv, "header-checker"); + uint8_t extension_or_incompatible = 0; HeaderAbiDiff judge(old_dump, new_dump, compatibility_report); switch (judge.GenerateCompatibilityReport()) { case HeaderAbiDiff::COMPATIBLE: + break; case HeaderAbiDiff::EXTENSION: - return 0; + extension_or_incompatible = 1; + break; default: - llvm::errs() << "******************************************************\n" - << "VNDK Abi Compliance breakage:" - << " Please check compatiblity report at : " - << compatibility_report << "\n" - << "*****************************************************\n"; - return 1; + extension_or_incompatible = 2; + break; } + if (extension_or_incompatible) { + llvm::errs() << "******************************************************\n" + << "VNDK Abi Compliance breakage:" + << " Please check compatiblity report at : " + << compatibility_report << "\n" + << "*****************************************************\n"; + } + return extension_or_incompatible; } diff --git a/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp index d2cd9f5a8..d070a2a12 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp +++ b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp @@ -22,7 +22,7 @@ using namespace abi_wrapper; ABIWrapper::ABIWrapper( clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *cip) : cip_(cip), mangle_contextp_(mangle_contextp), @@ -40,26 +40,66 @@ std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl, return abs_path.str(); } -std::string ABIWrapper::AccessToString(const clang::AccessSpecifier sp) const { - std::string str = "public"; +abi_dump::AccessSpecifier ABIWrapper::AccessClangToDump( + const clang::AccessSpecifier sp) const { switch (sp) { case clang::AS_private: { - str = "private"; + return abi_dump::AccessSpecifier::private_access; break; } case clang::AS_protected: { - str = "protected"; + return abi_dump::AccessSpecifier::protected_access; break; } default: { + return abi_dump::AccessSpecifier::public_access; break; } } - return str; +} + +bool ABIWrapper::SetupBasicTypeAbi(abi_dump::BasicTypeAbi *type_abi, + const clang::QualType type) const { + if (!type_abi) { + return false; + } + type_abi->set_name(QualTypeToString(type)); + // Cannot determine the size and alignment for template parameter dependent + // types as well as incomplete types. + const clang::Type *base_type = type.getTypePtr(); + if (base_type && !(base_type->isDependentType()) && + !(base_type->isIncompleteType())) { + std::pair size_and_alignment = + ast_contextp_->getTypeInfoInChars(type); + int64_t size = size_and_alignment.first.getQuantity(); + int64_t alignment = size_and_alignment.second.getQuantity(); + type_abi->set_size(size); + type_abi->set_alignment(alignment); + } + return true; +} + +bool ABIWrapper::SetupBasicNamedAndTypedDecl( + abi_dump::BasicNamedAndTypedDecl *basic_named_and_typed_decl, + const clang::QualType type, const std::string &name, + const clang::AccessSpecifier &access, std::string key) const { + if (!basic_named_and_typed_decl) { + return false; + } + abi_dump::AccessSpecifier access_dump = AccessClangToDump(access); + basic_named_and_typed_decl->set_name(name); + basic_named_and_typed_decl->set_access(access_dump); + if (key != "") { + basic_named_and_typed_decl->set_linker_set_key(key); + } + return SetupBasicTypeAbi(basic_named_and_typed_decl->mutable_type_abi(), + type); } std::string ABIWrapper::GetMangledNameDecl(const clang::NamedDecl *decl) const { - std::string mangled_or_demangled_name = decl->getName(); + clang::IdentifierInfo *identifier = decl->getIdentifier(); + std::string mangled_or_demangled_name = + identifier ? identifier->getName() : ""; if (mangle_contextp_->shouldMangleDeclName(decl)) { llvm::raw_string_ostream ostream(mangled_or_demangled_name); mangle_contextp_->mangleName(decl, ostream); @@ -71,17 +111,26 @@ std::string ABIWrapper::GetMangledNameDecl(const clang::NamedDecl *decl) const { bool ABIWrapper::SetupTemplateParamNames( abi_dump::TemplateInfo *tinfo, clang::TemplateParameterList *pl) const { - if (tinfo->template_parameters_size() > 0) { + if (tinfo->elements_size() > 0) { return true; } clang::TemplateParameterList::iterator template_it = pl->begin(); while (template_it != pl->end()) { - abi_dump::FieldDecl *template_parameterp = tinfo->add_template_parameters(); + abi_dump::TemplateElement *template_parameterp = + tinfo->add_elements(); if (!template_parameterp) { return false; } - template_parameterp->set_field_name((*template_it)->getName()); + abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi = + template_parameterp->mutable_basic_abi(); + if (!basic_abi) { + return false; + } + std::string name = (*template_it)->getName(); + basic_abi->set_name(name); + // TODO : Default arg ? + basic_abi->set_linker_set_key(name); template_it++; } return true; @@ -92,7 +141,6 @@ std::string ABIWrapper::GetTagDeclQualifiedName( if (decl->getTypedefNameForAnonDecl()) { return decl->getTypedefNameForAnonDecl()->getQualifiedNameAsString(); } - return decl->getQualifiedNameAsString(); } @@ -102,16 +150,22 @@ bool ABIWrapper::SetupTemplateArguments( for (int i = 0; i < tl->size(); i++) { const clang::TemplateArgument &arg = (*tl)[i]; //TODO: More comprehensive checking needed. - std::string type = " "; - if(arg.getKind() == clang::TemplateArgument::Type) { - type = QualTypeToString(arg.getAsType()); + if (arg.getKind() != clang::TemplateArgument::Type) { + continue; } - abi_dump::FieldDecl *template_parameterp = - tinfo->add_template_parameters(); + clang::QualType type = arg.getAsType(); + abi_dump::TemplateElement *template_parameterp = + tinfo->add_elements(); if (!template_parameterp) { return false; } - template_parameterp->set_field_type((type)); + abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi = + template_parameterp->mutable_basic_abi(); + if (!basic_abi || !SetupBasicTypeAbi(basic_abi->mutable_type_abi(), type)) { + return false; + } + // TODO : default arg + basic_abi->set_linker_set_key(QualTypeToString(type)); } return true; } @@ -124,42 +178,51 @@ std::string ABIWrapper::QualTypeToString( FunctionDeclWrapper::FunctionDeclWrapper( clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::FunctionDecl *decl) : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p), function_decl_(decl) { } +bool FunctionDeclWrapper::SetupFunctionParameters( + abi_dump::FunctionDecl *functionp) const { + clang::FunctionDecl::param_const_iterator param_it = + function_decl_->param_begin(); + while (param_it != function_decl_->param_end()) { + abi_dump::ParamDecl *function_fieldp = functionp->add_parameters(); + if (!function_fieldp) { + llvm::errs() << "Couldn't add parameter to method. Aborting\n"; + return false; + } + // The linker set key is blank since that shows up in the mangled name. + bool has_default_arg = (*param_it)->hasDefaultArg(); + if (!SetupBasicNamedAndTypedDecl( + function_fieldp->mutable_basic_abi(), + (*param_it)->getType(), (*param_it)->getName(), + (*param_it)->getAccess(), has_default_arg ? "true" : "false")) { + return false; + } + function_fieldp->set_default_arg(has_default_arg); + param_it++; + } + return true; +} + bool FunctionDeclWrapper::SetupFunction(abi_dump::FunctionDecl *functionp, const std::string &source_file) const { // Go through all the parameters in the method and add them to the fields. // Also get the fully qualfied name and mangled name and store them. std::string mangled_name = GetMangledNameDecl(function_decl_); - functionp->set_function_name(function_decl_->getQualifiedNameAsString()); functionp->set_mangled_function_name(mangled_name); - functionp->set_linker_set_key(mangled_name); functionp->set_source_file(source_file); - functionp->set_return_type(QualTypeToString(function_decl_->getReturnType())); - clang::FunctionDecl::param_const_iterator param_it = - function_decl_->param_begin(); - while (param_it != function_decl_->param_end()) { - abi_dump::FieldDecl *function_fieldp = functionp->add_parameters(); - if (!function_fieldp) { - llvm::errs() << "Couldn't add parameter to method. Aborting\n"; - return false; - } - function_fieldp->set_field_name((*param_it)->getName()); - function_fieldp->set_default_arg((*param_it)->hasDefaultArg()); - function_fieldp->set_field_type(QualTypeToString((*param_it)->getType())); - param_it++; - } - functionp->set_access(AccessToString(function_decl_->getAccess())); - functionp->set_template_kind(function_decl_->getTemplatedKind()); - if(!SetupTemplateInfo(functionp)) { - return false; - } - return true; + // Combine the function name and return type to form a NamedAndTypedDecl + return SetupBasicNamedAndTypedDecl( + functionp->mutable_basic_abi(), + function_decl_->getReturnType(), + function_decl_->getQualifiedNameAsString(), + function_decl_->getAccess(), mangled_name) && + SetupTemplateInfo(functionp) && SetupFunctionParameters(functionp); } bool FunctionDeclWrapper::SetupTemplateInfo( @@ -209,42 +272,35 @@ FunctionDeclWrapper::GetFunctionDecl() const { RecordDeclWrapper::RecordDeclWrapper( clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::RecordDecl *decl) : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p), record_decl_(decl) { } -bool RecordDeclWrapper::SetupRecordFields( - abi_dump::RecordDecl *recordp, - const std::string &source_file) const { +bool RecordDeclWrapper::SetupRecordFields(abi_dump::RecordDecl *recordp) const { clang::RecordDecl::field_iterator field = record_decl_->field_begin(); while (field != record_decl_->field_end()) { - abi_dump::FieldDecl *record_fieldp = recordp->add_fields(); + abi_dump::RecordFieldDecl *record_fieldp = recordp->add_fields(); if (!record_fieldp) { llvm::errs() << " Couldn't add record field: " << field->getName() << " to reference dump\n"; return false; } - std::string name = field->getName(); - std::string type = QualTypeToString(field->getType()); - 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); + if (!SetupBasicNamedAndTypedDecl(record_fieldp->mutable_basic_abi(), + field->getType(), field->getName(), + field->getAccess(), "")) { + return false; + } field++; } return true; } -bool RecordDeclWrapper::SetupCXXBases(abi_dump::RecordDecl *cxxp) const { - const clang::CXXRecordDecl *cxx_record_decl = - clang::dyn_cast(record_decl_); - if (!cxx_record_decl) { - return true; - } - +bool RecordDeclWrapper::SetupCXXBases( + abi_dump::RecordDecl *cxxp, + const clang::CXXRecordDecl *cxx_record_decl) const { + assert(cxx_record_decl != nullptr); clang::CXXRecordDecl::base_class_const_iterator base_class = cxx_record_decl->bases_begin(); while (base_class != cxx_record_decl->bases_end()) { @@ -255,25 +311,121 @@ bool RecordDeclWrapper::SetupCXXBases(abi_dump::RecordDecl *cxxp) const { } std::string name = QualTypeToString(base_class->getType()); bool is_virtual = base_class->isVirtual(); - char is_virtual_c = is_virtual ? 't' : 'f'; - std::string access = AccessToString(base_class->getAccessSpecifier()); - base_specifierp->set_fully_qualified_name(name); + if (!SetupBasicNamedAndTypedDecl(base_specifierp->mutable_basic_abi(), + base_class->getType(), + "", base_class->getAccessSpecifier(), + "")) { + return false; + } 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++; } return true; } -bool RecordDeclWrapper::SetupTemplateInfo( - abi_dump::RecordDecl *record_declp) const { - const clang::CXXRecordDecl *cxx_record_decl = - clang::dyn_cast(record_decl_); - if (!cxx_record_decl) { +bool RecordDeclWrapper::SetupRecordVTable( + abi_dump::RecordDecl *record_declp, + const clang::CXXRecordDecl *cxx_record_decl) const { + assert(cxx_record_decl != nullptr); + clang::VTableContextBase *base_vtable_contextp = + ast_contextp_->getVTableContext(); + const clang::Type *typep = cxx_record_decl->getTypeForDecl(); + if (!base_vtable_contextp || !typep) { + return false; + } + // Skip Microsoft ABI. + clang::ItaniumVTableContext *itanium_vtable_contextp = + llvm::dyn_cast(base_vtable_contextp); + if (!itanium_vtable_contextp || !cxx_record_decl->isPolymorphic() || + typep->isDependentType() || typep->isIncompleteType()) { return true; } + const clang::VTableLayout &vtable_layout = + itanium_vtable_contextp->getVTableLayout(cxx_record_decl); + abi_dump::VTableLayout *vtablep = record_declp->mutable_vtable_layout(); + if (!vtablep) { + return false; + } + for (const auto &vtable_component : vtable_layout.vtable_components()) { + abi_dump::VTableComponent *added_vtable_component = + vtablep->add_vtable_components(); + if (!added_vtable_component || + !SetupRecordVTableComponent(added_vtable_component, vtable_component)) { + return false; + } + } + return true; +} +bool RecordDeclWrapper::SetupRecordVTableComponent( + abi_dump::VTableComponent *added_vtable_component, + const clang::VTableComponent &vtable_component) const { + assert(added_vtable_component != nullptr); + abi_dump::VTableComponent_Kind kind = abi_dump::VTableComponent_Kind_RTTI; + std::string mangled_component_name = ""; + uint64_t value = 0; + clang::VTableComponent::Kind clang_component_kind = + vtable_component.getKind(); + switch (clang_component_kind) { + case clang::VTableComponent::CK_VCallOffset: + kind = abi_dump::VTableComponent_Kind_VCallOffset; + value = vtable_component.getVCallOffset().getQuantity(); + break; + case clang::VTableComponent::CK_VBaseOffset: + kind = abi_dump::VTableComponent_Kind_VBaseOffset; + value = vtable_component.getVBaseOffset().getQuantity(); + break; + case clang::VTableComponent::CK_OffsetToTop: + kind = abi_dump::VTableComponent_Kind_OffsetToTop; + value = vtable_component.getOffsetToTop().getQuantity(); + break; + case clang::VTableComponent::CK_RTTI: + { + kind = abi_dump::VTableComponent_Kind_RTTI; + const clang::CXXRecordDecl *rtti_decl = + vtable_component.getRTTIDecl(); + assert(rtti_decl != nullptr); + mangled_component_name = GetMangledNameDecl(rtti_decl); + } + break; + case clang::VTableComponent::CK_FunctionPointer: + case clang::VTableComponent::CK_CompleteDtorPointer: + case clang::VTableComponent::CK_DeletingDtorPointer: + case clang::VTableComponent::CK_UnusedFunctionPointer: + { + const clang::CXXMethodDecl *method_decl = + vtable_component.getFunctionDecl(); + assert(method_decl != nullptr); + mangled_component_name = GetMangledNameDecl(method_decl); + switch (clang_component_kind) { + case clang::VTableComponent::CK_FunctionPointer: + kind = abi_dump::VTableComponent_Kind_FunctionPointer; + break; + case clang::VTableComponent::CK_CompleteDtorPointer: + kind = abi_dump::VTableComponent_Kind_CompleteDtorPointer; + break; + case clang::VTableComponent::CK_DeletingDtorPointer: + kind = abi_dump::VTableComponent_Kind_DeletingDtorPointer; + case clang::VTableComponent::CK_UnusedFunctionPointer: + kind = abi_dump::VTableComponent_Kind_UnusedFunctionPointer; + default: + break; + } + } + break; + default: + return false; + } + added_vtable_component->set_kind(kind); + added_vtable_component->set_value(value); + added_vtable_component->set_mangled_component_name(mangled_component_name); + return true; +} + +bool RecordDeclWrapper::SetupTemplateInfo( + abi_dump::RecordDecl *record_declp, + const clang::CXXRecordDecl *cxx_record_decl) const { + assert(cxx_record_decl != nullptr); if (cxx_record_decl->isTemplateDecl()) { clang::ClassTemplateDecl *template_decl = cxx_record_decl->getDescribedClassTemplate(); @@ -303,28 +455,45 @@ bool RecordDeclWrapper::SetupTemplateInfo( return true; } -void RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp, +bool RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp, const std::string &source_file) const { std::string qualified_name = GetTagDeclQualifiedName(record_decl_); std::string mangled_name = GetMangledNameDecl(record_decl_); + const clang::Type *basic_type = nullptr; + if (!(basic_type = record_decl_->getTypeForDecl())) { + return false; + } + clang::QualType type = basic_type->getCanonicalTypeInternal(); std::string linker_key = (mangled_name == "") ? qualified_name : mangled_name; - record_declp->set_fully_qualified_name(qualified_name); + if (!SetupBasicNamedAndTypedDecl(record_declp->mutable_basic_abi(), + type, qualified_name, + record_decl_->getAccess(), linker_key)) { + return false; + } record_declp->set_mangled_record_name(mangled_name); - record_declp->set_linker_set_key(linker_key); record_declp->set_source_file(source_file); - record_declp->set_access(AccessToString(record_decl_->getAccess())); + return true; +} + +bool RecordDeclWrapper::SetupCXXRecordInfo( + abi_dump::RecordDecl *record_declp) const { + const clang::CXXRecordDecl *cxx_record_decl = + clang::dyn_cast(record_decl_); + if (!cxx_record_decl) { + return true; + } + return SetupTemplateInfo(record_declp, cxx_record_decl) && + SetupCXXBases(record_declp, cxx_record_decl) && + SetupRecordVTable(record_declp, cxx_record_decl); } std::unique_ptr RecordDeclWrapper::GetRecordDecl() const { std::unique_ptr abi_decl(new abi_dump::RecordDecl()); std::string source_file = GetDeclSourceFile(record_decl_, cip_); - SetupRecordInfo(abi_decl.get(), source_file); - if (!SetupRecordFields(abi_decl.get(), source_file)) { - llvm::errs() << "Setting up Record Fields failed\n"; - return nullptr; - } - - if (!SetupCXXBases(abi_decl.get()) || !SetupTemplateInfo(abi_decl.get())) { + abi_dump::RecordDecl *record_declp = abi_decl.get(); + if (!SetupRecordInfo(record_declp, source_file) || + !SetupRecordFields(record_declp) || + !SetupCXXRecordInfo(abi_decl.get())) { llvm::errs() << "Setting up CXX Bases / Template Info failed\n"; return nullptr; } @@ -333,34 +502,46 @@ std::unique_ptr RecordDeclWrapper::GetRecordDecl() const { EnumDeclWrapper::EnumDeclWrapper( clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::EnumDecl *decl) : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p), enum_decl_(decl) { } -bool EnumDeclWrapper::SetupEnum(abi_dump::EnumDecl *enump, - const std::string &source_file) const { - // Enum's name. - std::string enum_name = GetTagDeclQualifiedName(enum_decl_); - std::string enum_type = QualTypeToString(enum_decl_->getIntegerType()); - enump->set_enum_name(enum_name); - // Enum's base integer type. - enump->set_enum_type(enum_type); - enump->set_linker_set_key(enum_name + enum_type); +bool EnumDeclWrapper::SetupEnumFields(abi_dump::EnumDecl *enump) const { clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin(); while (enum_it != enum_decl_->enumerator_end()) { abi_dump::EnumFieldDecl *enum_fieldp = enump->add_enum_fields(); - if (!enum_fieldp) { + std::string name = enum_it->getQualifiedNameAsString(); + uint64_t field_value = enum_it->getInitVal().getExtValue(); + if (!enum_fieldp || + !SetupBasicNamedAndTypedDecl(enum_fieldp->mutable_basic_abi(), + enum_it->getType(), name, + enum_it->getAccess(), + std::to_string(field_value))) { return false; } - enum_fieldp->set_enum_field_name(enum_it->getQualifiedNameAsString()); - enum_fieldp->set_enum_field_value(enum_it->getInitVal().getExtValue()); + enum_fieldp->set_enum_field_value(field_value); enum_it++; } return true; } +bool EnumDeclWrapper::SetupEnum(abi_dump::EnumDecl *enump, + const std::string &source_file) const { + std::string enum_name = GetTagDeclQualifiedName(enum_decl_); + std::string enum_mangled_name = GetMangledNameDecl(enum_decl_); + clang::QualType enum_type = enum_decl_->getIntegerType(); + if (!SetupBasicNamedAndTypedDecl(enump->mutable_basic_abi(), enum_type, + enum_name, enum_decl_->getAccess(), + enum_mangled_name) || + !SetupEnumFields(enump)) { + return false; + } + enump->set_source_file(source_file); + return true; +} + std::unique_ptr EnumDeclWrapper::GetEnumDecl() const { std::unique_ptr abi_decl(new abi_dump::EnumDecl()); std::string source_file = GetDeclSourceFile(enum_decl_, cip_); @@ -371,3 +552,35 @@ std::unique_ptr EnumDeclWrapper::GetEnumDecl() const { } return abi_decl; } + +GlobalVarDeclWrapper::GlobalVarDeclWrapper( + clang::MangleContext *mangle_contextp, + clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p, + const clang::VarDecl *decl) + : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p), + global_var_decl_(decl) { } + +bool GlobalVarDeclWrapper::SetupGlobalVar( + abi_dump::GlobalVarDecl *global_varp, + const std::string &source_file) const { + if (!SetupBasicNamedAndTypedDecl( + global_varp->mutable_basic_abi(),global_var_decl_->getType(), + global_var_decl_->getQualifiedNameAsString(), + global_var_decl_->getAccess(), GetMangledNameDecl(global_var_decl_))) { + return false; + } + global_varp->set_source_file(source_file); + return true; +} + +std::unique_ptr +GlobalVarDeclWrapper::GetGlobalVarDecl() const { + std::unique_ptr + abi_decl(new abi_dump::GlobalVarDecl); + std::string source_file = GetDeclSourceFile(global_var_decl_, cip_); + if (!SetupGlobalVar(abi_decl.get(), source_file)) { + return nullptr; + } + return abi_decl; +} diff --git a/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h index bdb027463..88ea4335d 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h +++ b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h @@ -24,20 +24,22 @@ #include #include #include +#include #include namespace abi_wrapper { class ABIWrapper { public: ABIWrapper(clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *cip); static std::string GetDeclSourceFile(const clang::Decl *decl, const clang::CompilerInstance *cip); protected: - std::string AccessToString(const clang::AccessSpecifier sp) const; + abi_dump::AccessSpecifier AccessClangToDump( + const clang::AccessSpecifier sp) const; std::string GetMangledNameDecl(const clang::NamedDecl *decl) const; @@ -51,18 +53,24 @@ class ABIWrapper { std::string GetTagDeclQualifiedName(const clang::TagDecl *decl) const; - protected: - const clang::CompilerInstance *cip_; + bool SetupBasicTypeAbi(abi_dump::BasicTypeAbi *type_abi, + const clang::QualType type) const; - private: + bool SetupBasicNamedAndTypedDecl( + abi_dump::BasicNamedAndTypedDecl *basic_named_and_typed_decl, + const clang::QualType type, const std::string &name, + const clang::AccessSpecifier &access, std::string key) const; + +protected: + const clang::CompilerInstance *cip_; clang::MangleContext *mangle_contextp_; - const clang::ASTContext *ast_contextp_; + clang::ASTContext *ast_contextp_; }; class RecordDeclWrapper : public ABIWrapper { public: RecordDeclWrapper(clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::RecordDecl *decl); @@ -72,21 +80,30 @@ class RecordDeclWrapper : public ABIWrapper { const clang::RecordDecl *record_decl_; private: - void SetupRecordInfo(abi_dump::RecordDecl *record_declp, + bool SetupRecordInfo(abi_dump::RecordDecl *record_declp, const std::string &source_file) const; - bool SetupRecordFields(abi_dump::RecordDecl *record_declp, - const std::string &source_file) const; + bool SetupRecordFields(abi_dump::RecordDecl *record_declp) const; - bool SetupCXXBases(abi_dump::RecordDecl *cxxp) const; + bool SetupCXXBases(abi_dump::RecordDecl *cxxp, + const clang::CXXRecordDecl *cxx_record_decl) const; - bool SetupTemplateInfo(abi_dump::RecordDecl *record_declp) const; + bool SetupTemplateInfo(abi_dump::RecordDecl *record_declp, + const clang::CXXRecordDecl *cxx_record_decl) const; + + bool SetupRecordVTable(abi_dump::RecordDecl *record_declp, + const clang::CXXRecordDecl *cxx_record_decl) const; + bool SetupRecordVTableComponent( + abi_dump::VTableComponent *added_vtable_component, + const clang::VTableComponent &vtable_component) const; + + bool SetupCXXRecordInfo(abi_dump::RecordDecl *record_declp) const; }; class FunctionDeclWrapper : public ABIWrapper { public: FunctionDeclWrapper(clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::FunctionDecl *decl); @@ -100,12 +117,14 @@ class FunctionDeclWrapper : public ABIWrapper { const std::string &source_file) const; bool SetupTemplateInfo(abi_dump::FunctionDecl *functionp) const; + + bool SetupFunctionParameters(abi_dump::FunctionDecl *functionp) const; }; class EnumDeclWrapper : public ABIWrapper { public: EnumDeclWrapper(clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const clang::EnumDecl *decl); @@ -117,6 +136,23 @@ class EnumDeclWrapper : public ABIWrapper { private: bool SetupEnum(abi_dump::EnumDecl *enump, const std::string &source_file) const; + bool SetupEnumFields(abi_dump::EnumDecl *enump) const; +}; + +class GlobalVarDeclWrapper : public ABIWrapper { + public: + GlobalVarDeclWrapper(clang::MangleContext *mangle_contextp, + clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p, + const clang::VarDecl *decl); + + std::unique_ptr GetGlobalVarDecl() const; + + private: + const clang::VarDecl *global_var_decl_; + private: + bool SetupGlobalVar(abi_dump::GlobalVarDecl *global_varp, + const std::string &source_file) const; }; } //end namespace abi_wrapper diff --git a/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.cpp b/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.cpp index ec1aa71f3..a8d5ae108 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.cpp +++ b/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.cpp @@ -29,11 +29,12 @@ using abi_wrapper::ABIWrapper; using abi_wrapper::FunctionDeclWrapper; using abi_wrapper::RecordDeclWrapper; using abi_wrapper::EnumDeclWrapper; +using abi_wrapper::GlobalVarDeclWrapper; HeaderASTVisitor::HeaderASTVisitor( abi_dump::TranslationUnit *tu_ptr, clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const std::string ¤t_file_name, const std::set &exported_headers, @@ -47,7 +48,7 @@ HeaderASTVisitor::HeaderASTVisitor( tu_decl_(tu_decl) { } bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { - // Forward declaration + // Skip forward declaration. if (!decl->isThisDeclarationADefinition()) { return true; } @@ -59,11 +60,11 @@ bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { llvm::errs() << "Getting Record Decl failed\n"; return false; } - abi_dump::RecordDecl *record_declp = tu_ptr_->add_records(); - if (!record_declp) { + abi_dump::RecordDecl *added_record_declp = tu_ptr_->add_records(); + if (!added_record_declp) { return false; } - *record_declp = *wrapped_record_decl; + *added_record_declp = *wrapped_record_decl; return true; } @@ -79,35 +80,57 @@ bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) { llvm::errs() << "Getting Enum Decl failed\n"; return false; } - abi_dump::EnumDecl *enum_declp = tu_ptr_->add_enums(); - if (!enum_declp) { + abi_dump::EnumDecl *added_enum_declp = tu_ptr_->add_enums(); + if (!added_enum_declp) { return false; } - *enum_declp = *wrapped_enum_decl; + *added_enum_declp = *wrapped_enum_decl; return true; } bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) { - FunctionDeclWrapper function_decl_wrapper( - mangle_contextp_, ast_contextp_, cip_, decl); + FunctionDeclWrapper function_decl_wrapper(mangle_contextp_, ast_contextp_, + cip_, decl); std::unique_ptr wrapped_function_decl = function_decl_wrapper.GetFunctionDecl(); if (!wrapped_function_decl) { llvm::errs() << "Getting Function Decl failed\n"; return false; } - abi_dump::FunctionDecl *function_declp = tu_ptr_->add_functions(); - if (!function_declp) { + abi_dump::FunctionDecl *added_function_declp = tu_ptr_->add_functions(); + if (!added_function_declp) { return false; } - *function_declp = *wrapped_function_decl; + *added_function_declp = *wrapped_function_decl; + return true; +} + +bool HeaderASTVisitor::VisitVarDecl(const clang::VarDecl *decl) { + if(!decl->hasGlobalStorage()) { + // Non global / static variable declarations don't need to be dumped. + return true; + } + GlobalVarDeclWrapper global_var_decl_wrapper(mangle_contextp_, ast_contextp_, + cip_, decl); + std::unique_ptr wrapped_global_var_decl = + global_var_decl_wrapper.GetGlobalVarDecl(); + if (!wrapped_global_var_decl) { + llvm::errs() << "Getting Global Var Decl failed\n"; + return false; + } + abi_dump::GlobalVarDecl *added_global_var_declp = tu_ptr_->add_global_vars(); + if (!added_global_var_declp) { + return false; + } + *added_global_var_declp = *wrapped_global_var_decl; return true; } // We don't need to recurse into Declarations which are not exported. bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) { - if (!decl) + if (!decl) { return true; + } std::string source_file = ABIWrapper::GetDeclSourceFile(decl, cip_); if ((decl != tu_decl_) && (exported_headers_.find(source_file) == exported_headers_.end())) { @@ -150,5 +173,5 @@ void HeaderASTConsumer::HandleVTable(clang::CXXRecordDecl *crd) { void HeaderASTPPCallbacks::MacroDefined(const clang::Token ¯o_name_tok, const clang::MacroDirective *) { - assert(macro_name_tok.isAnyIdentifier()); + assert(macro_name_tok.getLength() != 0); } diff --git a/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.h b/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.h index b66dea417..f8de1dc4b 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.h +++ b/vndk/tools/header-checker/header-abi-dumper/src/ast_processing.h @@ -35,7 +35,7 @@ class HeaderASTVisitor public: HeaderASTVisitor(abi_dump::TranslationUnit *tu_ptr, clang::MangleContext *mangle_contextp, - const clang::ASTContext *ast_contextp, + clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, const std::string ¤t_file_name, const std::set &exported_headers, @@ -47,6 +47,8 @@ class HeaderASTVisitor bool VisitEnumDecl(const clang::EnumDecl *decl); + bool VisitVarDecl(const clang::VarDecl *decl); + bool TraverseDecl(clang::Decl *decl); // Enable recursive traversal of template instantiations. @@ -57,7 +59,7 @@ class HeaderASTVisitor private: abi_dump::TranslationUnit *tu_ptr_; clang::MangleContext *mangle_contextp_; - const clang::ASTContext *ast_contextp_; + clang::ASTContext *ast_contextp_; const clang::CompilerInstance *cip_; const std::string current_file_name_; const std::set &exported_headers_; diff --git a/vndk/tools/header-checker/header-abi-linker/src/header_abi_linker.cpp b/vndk/tools/header-checker/header-abi-linker/src/header_abi_linker.cpp index ca1f772a9..9644e0830 100644 --- a/vndk/tools/header-checker/header-abi-linker/src/header_abi_linker.cpp +++ b/vndk/tools/header-checker/header-abi-linker/src/header_abi_linker.cpp @@ -63,6 +63,9 @@ class HeaderAbiLinker { bool LinkEnums(const abi_dump::TranslationUnit &dump_tu, abi_dump::TranslationUnit *linked_tu); + bool LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu, + abi_dump::TranslationUnit *linked_tu); + template static inline bool LinkDecl( google::protobuf::RepeatedPtrField *dst, @@ -75,6 +78,7 @@ class HeaderAbiLinker { std::set record_decl_set_; std::set function_decl_set_; std::set enum_decl_set_; + std::set globvar_decl_set_; }; bool HeaderAbiLinker::LinkAndDump() { @@ -88,7 +92,8 @@ bool HeaderAbiLinker::LinkAndDump() { if (!google::protobuf::TextFormat::Parse(&text_is, &dump_tu) || !LinkRecords(dump_tu, &linked_tu) || !LinkFunctions(dump_tu, &linked_tu) || - !LinkEnums(dump_tu, &linked_tu)) { + !LinkEnums(dump_tu, &linked_tu) || + !LinkGlobalVars(dump_tu, &linked_tu)) { llvm::errs() << "Failed to link elements\n"; return false; } @@ -110,7 +115,7 @@ inline bool HeaderAbiLinker::LinkDecl( assert(link_set != nullptr); for (auto &&element : src) { // The element already exists in the linked dump. Skip. - if (!link_set->insert(element.linker_set_key()).second) { + if (!link_set->insert(element.basic_abi().linker_set_key()).second) { continue; } T *added_element = dst->Add(); @@ -144,6 +149,13 @@ bool HeaderAbiLinker::LinkEnums(const abi_dump::TranslationUnit &dump_tu, dump_tu.enums()); } +bool HeaderAbiLinker::LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu, + abi_dump::TranslationUnit *linked_tu) { + assert(linked_tu != nullptr); + return LinkDecl(linked_tu->mutable_global_vars(), &globvar_decl_set_, + dump_tu.global_vars()); +} + int main(int argc, const char **argv) { GOOGLE_PROTOBUF_VERIFY_VERSION; llvm::cl::ParseCommandLineOptions(argc, argv, "header-checker"); diff --git a/vndk/tools/header-checker/proto/abi_diff.proto b/vndk/tools/header-checker/proto/abi_diff.proto index e963de59c..e8b7570eb 100644 --- a/vndk/tools/header-checker/proto/abi_diff.proto +++ b/vndk/tools/header-checker/proto/abi_diff.proto @@ -4,9 +4,9 @@ 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; +message RecordFieldDeclDiff { + optional abi_dump.RecordFieldDecl old = 1; + optional abi_dump.RecordFieldDecl new = 2; required uint32 index = 3; } @@ -22,16 +22,23 @@ message CXXBaseSpecifierDiff { required uint32 index = 3; } +message CXXVTableDiff { + optional abi_dump.VTableComponent old = 1; + optional abi_dump.VTableComponent new = 2; + required uint32 index = 3; +} + message AccessDiff { - required string old = 1; - required string new = 2; + required abi_dump.AccessSpecifier old = 1; + required abi_dump.AccessSpecifier new = 2; } message RecordDeclDiff { - repeated FieldDeclDiff field_diffs = 1; + repeated RecordFieldDeclDiff field_diffs = 1; repeated CXXBaseSpecifierDiff base_diffs = 2; - required AccessDiff access_diff = 3; - required string name = 4; + repeated CXXVTableDiff vtable_diffs = 3; + required AccessDiff access_diff = 4; + required string name = 5; } message EnumDeclDiff { @@ -40,16 +47,34 @@ message EnumDeclDiff { required string name = 3; } +message ReturnTypeDiff { + required abi_dump.BasicNamedAndTypedDecl old = 1; + required abi_dump.BasicNamedAndTypedDecl new = 2; +} + +message FunctionDeclDiff { + required ReturnTypeDiff return_type_diffs = 1; +} + +message GlobalVarDeclDiff { + required abi_dump.BasicNamedAndTypedDecl old = 1; + required abi_dump.BasicNamedAndTypedDecl new = 2; +} + message TranslationUnitDiff { // Differing Elements. repeated RecordDeclDiff records_diff = 1; - repeated EnumDeclDiff enums_diff = 3; + repeated EnumDeclDiff enums_diff = 2; + repeated FunctionDeclDiff functions_diff = 3; + repeated GlobalVarDeclDiff global_vars_diff = 4; // Removed Elements. - repeated abi_dump.RecordDecl records_removed = 4; - repeated abi_dump.FunctionDecl functions_removed = 5; - repeated abi_dump.EnumDecl enums_removed = 6; + repeated abi_dump.RecordDecl records_removed = 5; + repeated abi_dump.FunctionDecl functions_removed = 6; + repeated abi_dump.EnumDecl enums_removed = 7; + repeated abi_dump.GlobalVarDecl global_vars_removed = 8; // Added Elements. - repeated abi_dump.RecordDecl records_added = 7; - repeated abi_dump.FunctionDecl functions_added = 8; - repeated abi_dump.EnumDecl enums_added = 9; + repeated abi_dump.RecordDecl records_added = 9; + repeated abi_dump.FunctionDecl functions_added = 10; + repeated abi_dump.EnumDecl enums_added = 11; + repeated abi_dump.GlobalVarDecl global_vars_added = 12; } diff --git a/vndk/tools/header-checker/proto/abi_dump.proto b/vndk/tools/header-checker/proto/abi_dump.proto index a7ab9cc6a..11eb3cc14 100644 --- a/vndk/tools/header-checker/proto/abi_dump.proto +++ b/vndk/tools/header-checker/proto/abi_dump.proto @@ -2,72 +2,114 @@ syntax = "proto2"; package abi_dump; -message FunctionDecl { - // Fully Qualified Name. - optional string function_name = 1 [default = "NONE"]; - - // Mangled name. - optional string mangled_function_name = 2 [default = "NONE"]; - - optional string source_file = 3; - optional string parent_name = 4 [default = "NONE"]; - repeated string template_arguments = 5 ; - repeated FieldDecl parameters = 6; - optional string return_type = 7 [default = "VOID"]; - optional string access = 8 [default = "public"]; - optional uint32 template_kind = 9 [default = 0]; - optional TemplateInfo template_info = 10; - optional string linker_set_key = 11 [default = "NONE"]; +message BasicTypeAbi { + // The type's name. for eg : a record field's type. + required string name = 1; + // Optional since templated types will not have this information. + optional uint64 size = 2 [default = 0]; + optional uint32 alignment = 3 [default = 0]; } -message FieldDecl { - optional string field_name = 1 [default = "NONE"]; - optional string field_type = 2 [default = "VOID"]; - optional string access = 3 [default = "public"]; - optional bool default_arg = 4 [default = false]; - optional string linker_set_key = 5 [default = "NONE"]; +enum AccessSpecifier { + public_access = 1; + private_access = 2; + protected_access = 3; +} + +message BasicNamedAndTypedDecl { + required BasicTypeAbi type_abi = 1; + // The TypedDecl's name. + required string name = 2; + required AccessSpecifier access = 3; + optional string linker_set_key = 4; +} + +message FunctionDecl { + required BasicNamedAndTypedDecl basic_abi = 1; + // Mangled name. + required string mangled_function_name = 2; + required string source_file = 3; + repeated ParamDecl parameters = 4; + optional TemplateInfo template_info = 5; +} + +message ParamDecl { + required BasicNamedAndTypedDecl basic_abi = 1; + required bool default_arg = 2; +} + +message RecordFieldDecl { + // For future additions. + required BasicNamedAndTypedDecl basic_abi = 1; } message EnumFieldDecl { - optional string enum_field_name = 1 [default = "NONE"]; - optional int64 enum_field_value = 2 [default = 0]; // assumption: fits int64 - optional string linker_set_key = 3 [default = "NONE"]; + required BasicNamedAndTypedDecl basic_abi = 1; + required int64 enum_field_value = 2; // assumption: fits int64 } message TemplateInfo { - repeated FieldDecl template_parameters = 1; + repeated TemplateElement elements = 1; +} + +message TemplateElement { + required BasicTemplateElementAbi basic_abi = 1; + message BasicTemplateElementAbi { + optional BasicTypeAbi type_abi = 1; + optional string name = 2; + required string linker_set_key = 3; + } } message CXXBaseSpecifier { - optional string fully_qualified_name = 1 [default = "NONE"]; - optional string access = 2 [default = "public"]; - optional bool is_virtual = 3 [default = false]; - optional string linker_set_key = 4 [default = "NONE"]; + required BasicNamedAndTypedDecl basic_abi = 1; + required bool is_virtual = 2; +} + +message VTableComponent { + enum Kind { + VCallOffset = 0; + VBaseOffset = 1; + OffsetToTop = 2; + RTTI = 3; + FunctionPointer = 4; + CompleteDtorPointer = 5; + DeletingDtorPointer = 6; + UnusedFunctionPointer = 7; + } + required Kind kind = 1; + optional string mangled_component_name = 2 [default = ""]; + optional uint64 value = 3 [default = 0]; +} + +message VTableLayout { + repeated VTableComponent vtable_components = 1; } message RecordDecl { - repeated FieldDecl fields = 1; - repeated CXXBaseSpecifier base_specifiers = 2; - optional string fully_qualified_name = 3 [default = "NONE"]; - optional string source_file = 4 [default = "NONE"]; - optional uint32 template_kind = 5 [default = 0]; - optional TemplateInfo template_info = 6; - optional string access = 7 [default = "public"]; - optional string linker_set_key = 8 [default = "NONE"]; - optional string mangled_record_name = 9 [default = "NONE"]; + required BasicNamedAndTypedDecl basic_abi = 1; + repeated RecordFieldDecl fields = 2; + repeated CXXBaseSpecifier base_specifiers = 3; + required string source_file = 4; + optional TemplateInfo template_info = 5; + required string mangled_record_name = 6; + optional VTableLayout vtable_layout = 7; } message EnumDecl { - optional string enum_name = 1 [default = "NONE"]; - optional string access = 2 [default = "public"]; - optional string enum_type = 3 [default = "int"]; - repeated EnumFieldDecl enum_fields = 4; - optional string source_file = 5 [default = "NONE"]; - optional string linker_set_key = 6 [default = "NONE"]; + required BasicNamedAndTypedDecl basic_abi = 1; + repeated EnumFieldDecl enum_fields = 2; + required string source_file = 3; +} + +message GlobalVarDecl { + required BasicNamedAndTypedDecl basic_abi = 1; + required string source_file = 2; } message TranslationUnit { repeated RecordDecl records = 1; repeated FunctionDecl functions = 2; repeated EnumDecl enums = 3; + repeated GlobalVarDecl global_vars = 4; } diff --git a/vndk/tools/header-checker/tests/input/example1.cpp b/vndk/tools/header-checker/tests/input/example1.cpp index 7b668534e..a22b4f545 100644 --- a/vndk/tools/header-checker/tests/input/example1.cpp +++ b/vndk/tools/header-checker/tests/input/example1.cpp @@ -1,4 +1,4 @@ -#include "example2.h" +#include "example1.h" class NotIncluded { int not_included; diff --git a/vndk/tools/header-checker/tests/input/example1.h b/vndk/tools/header-checker/tests/input/example1.h index d143afa2e..86530639d 100644 --- a/vndk/tools/header-checker/tests/input/example1.h +++ b/vndk/tools/header-checker/tests/input/example1.h @@ -22,7 +22,7 @@ typedef const float_type cfloat_type; struct CPPHello : private HelloAgain, public ByeAgain { const int cpp_foo; cfloat_type cpp_bar; - + virtual int again() { return 0; } CPPHello() : cpp_foo(20), cpp_bar(1.234) { } }; diff --git a/vndk/tools/header-checker/tests/input/example2.h b/vndk/tools/header-checker/tests/input/example2.h index e9b67f54e..9d2577847 100644 --- a/vndk/tools/header-checker/tests/input/example2.h +++ b/vndk/tools/header-checker/tests/input/example2.h @@ -1,12 +1,16 @@ #ifndef EXAMPLE2_H_ #define EXAMPLE2_H_ #include +#include +#include #include "example3.h" namespace test2 { struct HelloAgain { - std::unique_ptr foo_again; + std::vector foo_again; int bar_again; + static int hello_forever; + virtual int again(); }; struct NowWeCrash; } // namespace test2 @@ -16,6 +20,7 @@ enum Foo_s { foosbat }; + namespace test3 { template struct ByeAgain { @@ -27,6 +32,7 @@ struct ByeAgain { template<> struct ByeAgain { float foo_again; + static int foo_forever; float bar_Again; float method_foo(int); }; @@ -34,12 +40,11 @@ struct ByeAgain { ByeAgain double_bye; template -bool Begin(T1 arg1, T2 arg2); -template <> -bool Begin(int a, float b); +bool Begin( T1 arg1, T2 arg2, int c); + bool End ( float arg = 2.0) { - bool ret = Begin(arg, 2); - return ret; + bool ret = Begin(arg, 2, 2); + return true; } @@ -57,6 +62,7 @@ class Outer { }; }; +std::vector Dummy(int t); } // namespace test3