From 292075439711f06797a52df0ca4b7ab23b63e485 Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Wed, 18 Jan 2017 17:25:12 -0800 Subject: [PATCH] Seperated out protobuf impl into wrapper classes. Added Template information to RecordDecls and FunctionDecls. Added Enum Information. Removed decl parameters from wrapper class methods. Omit processing RecordDecl forward declarations. Test: header-abi-dumper -o example2.dump tests/example2.h -- clang -x c++ -I . -std=c++11 -I ~/android/aosp/external/clang/lib/Headers/ Change-Id: I4bd1eea25d00f2efc24ca38051a8d19a72c0fbb9 --- .../header-abi-dumper/src/abi_wrappers.cpp | 326 ++++++++++++++++++ .../header-abi-dumper/src/abi_wrappers.h | 119 +++++++ .../header-abi-dumper/src/ast_processing.cpp | 189 ++++------ .../header-abi-dumper/src/ast_processing.h | 23 +- .../tools/header-checker/proto/abi_dump.proto | 24 ++ vndk/tools/header-checker/tests/example2.h | 46 ++- 6 files changed, 583 insertions(+), 144 deletions(-) create mode 100644 vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp create mode 100644 vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h 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 new file mode 100644 index 000000000..204d5c7a6 --- /dev/null +++ b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp @@ -0,0 +1,326 @@ +// 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_wrappers.h" + +#include + +#include + +using namespace abi_wrapper; + +ABIWrapper::ABIWrapper( + clang::MangleContext *mangle_contextp, + const clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p) + : mangle_contextp_(mangle_contextp), + ast_contextp_(ast_contextp), + cip_(compiler_instance_p) {} + +std::string ABIWrapper::GetDeclSourceFile(const clang::NamedDecl *decl) const { + clang::SourceManager &SM = cip_->getSourceManager(); + clang::SourceLocation location = decl->getLocation(); + llvm::StringRef file_name= SM.getFilename(location); + return file_name.str(); +} + +std::string ABIWrapper::AccessToString(const clang::AccessSpecifier sp) const { + std::string str = "public"; + switch (sp) { + case clang::AS_private: + str = "private"; + break; + case clang::AS_protected: + str = "protected"; + break; + default: + break; + } + return str; +} + +std::string ABIWrapper::GetMangledNameDecl(const clang::NamedDecl *decl) const { + std::string mangled_or_demangled_name = decl->getName(); + if (mangle_contextp_->shouldMangleDeclName(decl)) { + llvm::raw_string_ostream ostream(mangled_or_demangled_name); + mangle_contextp_->mangleName(decl, ostream); + ostream.flush(); + } + return mangled_or_demangled_name; +} + +bool ABIWrapper::SetupTemplateParamNames(abi_dump::TemplateInfo *tinfo, + clang::TemplateParameterList *pl) const { + if (tinfo->template_parameters_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(); + if (!template_parameterp) + return false; + template_parameterp->set_field_name((*template_it)->getName()); + template_it++; + } + return true; +} + +bool ABIWrapper::SetupTemplateArguments(abi_dump::TemplateInfo *tinfo, + const clang::TemplateArgumentList *tl) const { + for (int i = 0; i < tl->size(); i++) { + const clang::TemplateArgument &arg = (*tl)[i]; + std::string type = QualTypeToString(arg.getAsType()); + abi_dump::FieldDecl *template_parameterp = + tinfo->add_template_parameters(); + if (!template_parameterp) + return false; + template_parameterp->set_field_type((type)); + } + return true; +} + +std::string ABIWrapper::QualTypeToString(const clang::QualType &sweet_qt) const { + const clang::QualType salty_qt = sweet_qt.getDesugaredType(*ast_contextp_); + return clang::TypeName::getFullyQualifiedName(salty_qt, *ast_contextp_); +} + +FunctionDeclWrapper::FunctionDeclWrapper( + clang::MangleContext *mangle_contextp, + const 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::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. + functionp->set_function_name(function_decl_->getQualifiedNameAsString()); + functionp->set_mangled_function_name(GetMangledNameDecl(function_decl_)); + 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; +} + +bool FunctionDeclWrapper::SetupTemplateInfo(abi_dump::FunctionDecl *functionp) const { + switch (function_decl_->getTemplatedKind()) { + case clang::FunctionDecl::TK_FunctionTemplate: + { + clang::FunctionTemplateDecl *template_decl = + function_decl_->getDescribedFunctionTemplate(); + if (template_decl) { + clang::TemplateParameterList *template_parameter_list = + template_decl->getTemplateParameters(); + if (template_parameter_list && + !SetupTemplateParamNames(functionp->mutable_template_info(), + template_parameter_list)) { + return false; + } + } + break; + } + case clang::FunctionDecl::TK_FunctionTemplateSpecialization: + { + const clang::TemplateArgumentList *arg_list = + function_decl_->getTemplateSpecializationArgs(); + if (arg_list && + !SetupTemplateArguments( + functionp->mutable_template_info(), arg_list)) { + return false; + } + break; + } + default: + break; + } + return true; +} + +std::unique_ptr FunctionDeclWrapper::GetFunctionDecl() const { + std::unique_ptr abi_decl( + new abi_dump::FunctionDecl()); + std::string source_file = GetDeclSourceFile(function_decl_); + if (!SetupFunction(abi_decl.get(), source_file)) { + return nullptr; + } + return abi_decl; +} + +RecordDeclWrapper::RecordDeclWrapper( + clang::MangleContext *mangle_contextp, + const 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 { + clang::RecordDecl::field_iterator field = record_decl_->field_begin(); + while (field != record_decl_->field_end()) { + abi_dump::FieldDecl *record_fieldp = recordp->add_fields(); + if (!record_fieldp) { + llvm::errs() << " Couldn't add record field: " << field->getName() + << " to reference dump\n"; + return false; + } + record_fieldp->set_field_name(field->getName()); + record_fieldp->set_field_type(QualTypeToString(field->getType())); + record_fieldp->set_access(AccessToString(field->getAccess())); + 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; + + clang::CXXRecordDecl::base_class_const_iterator base_class = + cxx_record_decl->bases_begin(); + while (base_class != cxx_record_decl->bases_end()) { + abi_dump::CXXBaseSpecifier *base_specifierp = cxxp->add_base_specifiers(); + if (!base_specifierp) { + llvm::errs() << " Couldn't add base specifier to reference dump\n"; + return false; + } + base_specifierp->set_fully_qualified_name( + QualTypeToString(base_class->getType())); + base_specifierp->set_is_virtual(base_class->isVirtual()); + base_specifierp->set_access( + AccessToString(base_class->getAccessSpecifier())); + 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) + return true; + + if (cxx_record_decl->isTemplateDecl()) { + clang::ClassTemplateDecl *template_decl = + cxx_record_decl->getDescribedClassTemplate(); + if (template_decl) { + clang::TemplateParameterList *template_parameter_list = + template_decl->getTemplateParameters(); + if (template_parameter_list + && !SetupTemplateParamNames(record_declp->mutable_template_info(), + template_parameter_list)) { + return false; + } + } + } else { + const clang::ClassTemplateSpecializationDecl *specialization_decl = + clang::dyn_cast( + cxx_record_decl); + if(specialization_decl) { + const clang::TemplateArgumentList *arg_list = + &(specialization_decl->getTemplateArgs()); + if (arg_list + && !SetupTemplateArguments(record_declp->mutable_template_info(), + arg_list)) { + return false; + } + } + } + return true; +} + +void RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp, + const std::string &source_file) const { + record_declp->set_fully_qualified_name( + record_decl_->getQualifiedNameAsString()); + record_declp->set_source_file(source_file); + record_declp->set_access(AccessToString(record_decl_->getAccess())); +} + +std::unique_ptr RecordDeclWrapper::GetRecordDecl() const { + std::unique_ptr abi_decl(new abi_dump::RecordDecl()); + std::string source_file = GetDeclSourceFile(record_decl_); + 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())) { + llvm::errs() << "Setting up CXX Bases / Template Info failed\n"; + return nullptr; + } + return abi_decl; +} + +EnumDeclWrapper::EnumDeclWrapper( + clang::MangleContext *mangle_contextp, + const 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. + enump->set_enum_name(enum_decl_->getQualifiedNameAsString()); + //Enum's base integer type. + enump->set_enum_type(QualTypeToString(enum_decl_->getIntegerType())); + + clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin(); + while (enum_it != enum_decl_->enumerator_end()) { + abi_dump::EnumField *enum_fieldp = enump->add_enum_fields(); + if (!enum_fieldp) + return false; + enum_fieldp->set_enum_field_name(enum_it->getQualifiedNameAsString()); + enum_fieldp->set_enum_field_value(enum_it->getInitVal().getExtValue()); + enum_it++; + } + return true; +} + +std::unique_ptr EnumDeclWrapper::GetEnumDecl() const { + std::unique_ptr abi_decl(new abi_dump::EnumDecl()); + std::string source_file = GetDeclSourceFile(enum_decl_); + + if (!SetupEnum(abi_decl.get(), source_file)) { + llvm::errs() << "Setting up Enum fields failed\n"; + 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 new file mode 100644 index 000000000..bc796f0e2 --- /dev/null +++ b/vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h @@ -0,0 +1,119 @@ +// 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. + +#ifndef ABI_WRAPPERS_H_ +#define ABI_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" +#pragma clang diagnostic pop + +#include +#include +#include +#include + +namespace abi_wrapper { +class ABIWrapper { + public: + ABIWrapper(clang::MangleContext *mangle_contextp, + const clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p); + + std::string GetDeclSourceFile(const clang::NamedDecl *decl) const; + + protected: + std::string AccessToString(const clang::AccessSpecifier sp) const; + + std::string GetMangledNameDecl(const clang::NamedDecl *decl) const; + + bool SetupTemplateParamNames(abi_dump::TemplateInfo *tinfo, + clang::TemplateParameterList *pl) const; + + bool SetupTemplateArguments(abi_dump::TemplateInfo *tinfo, + const clang::TemplateArgumentList *tl) const; + + std::string QualTypeToString(const clang::QualType &sweet_qt) const; + + private: + clang::MangleContext *mangle_contextp_; + const clang::ASTContext *ast_contextp_; + const clang::CompilerInstance *cip_; +}; + +class RecordDeclWrapper : public ABIWrapper { + public: + RecordDeclWrapper(clang::MangleContext *mangle_contextp, + const clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p, + const clang::RecordDecl *decl); + + std::unique_ptr GetRecordDecl() const; + + private: + const clang::RecordDecl *record_decl_; + + private: + void SetupRecordInfo(abi_dump::RecordDecl *record_declp, + const std::string &source_file) const; + + bool SetupRecordFields(abi_dump::RecordDecl *recordp, + const std::string &source_file) const; + + bool SetupCXXBases(abi_dump::RecordDecl *cxxp) const; + + bool SetupTemplateInfo(abi_dump::RecordDecl *record_declp) const; +}; + +class FunctionDeclWrapper : public ABIWrapper { + public: + FunctionDeclWrapper(clang::MangleContext *mangle_contextp, + const clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p, + const clang::FunctionDecl *decl); + + std::unique_ptr GetFunctionDecl() const; + + private: + const clang::FunctionDecl *function_decl_; + + private: + bool SetupFunction(abi_dump::FunctionDecl *methodp, + const std::string &source_file) const; + + bool SetupTemplateInfo(abi_dump::FunctionDecl *functionp) const; +}; + +class EnumDeclWrapper : public ABIWrapper { + public: + EnumDeclWrapper(clang::MangleContext *mangle_contextp, + const clang::ASTContext *ast_contextp, + const clang::CompilerInstance *compiler_instance_p, + const clang::EnumDecl *decl); + + std::unique_ptr GetEnumDecl() const; + + private: + const clang::EnumDecl *enum_decl_; + + private: + bool SetupEnum(abi_dump::EnumDecl *enump, + const std::string &source_file) const; +}; + +} //end namespace abi_wrapper + +#endif // ABI_WRAPPERS_H_ 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 d3dd2825e..3e1101335 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 @@ -1,4 +1,3 @@ - // Copyright (C) 2016 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,6 +13,7 @@ // limitations under the License. #include "ast_processing.h" +#include "abi_wrappers.h" #include #include @@ -24,6 +24,10 @@ #include #include +using abi_wrapper::FunctionDeclWrapper; +using abi_wrapper::RecordDeclWrapper; +using abi_wrapper::EnumDeclWrapper; + HeaderASTVisitor::HeaderASTVisitor( abi_dump::TranslationUnit *tu_ptr, clang::MangleContext *mangle_contextp, @@ -38,28 +42,75 @@ HeaderASTVisitor::HeaderASTVisitor( // TODO: optimize source file initial check by preferably moving this into // TraverseTranslationUnitDecl. -bool HeaderASTVisitor::VisitCXXRecordDecl(const clang::CXXRecordDecl *decl) { - std::string source_file = GetDeclSourceFile(decl); +bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { + //forward declaration + if (!decl->isThisDeclarationADefinition()) { + return true; + } + RecordDeclWrapper record_decl_wrapper(mangle_contextp_, + ast_contextp_, + cip_, + decl); + std::string source_file = record_decl_wrapper.GetDeclSourceFile(decl); if (source_file != current_file_name_) return true; - abi_dump::RecordDecl *record_decl = tu_ptr_->add_classes(); - if (!SetupClassFields(record_decl, decl, source_file) || - !SetupClassBases(record_decl, decl)) { + std::unique_ptr wrapped_record_decl = + record_decl_wrapper.GetRecordDecl(); + if (!wrapped_record_decl) { + llvm::errs() << "Getting Record Decl failed\n"; return false; } + abi_dump::RecordDecl *record_declp = tu_ptr_->add_classes(); + if (!record_declp) { + return false; + } + *record_declp = *wrapped_record_decl; + return true; +} + +bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) { + if (!decl->isThisDeclarationADefinition()) { + return true; + } + EnumDeclWrapper enum_decl_wrapper(mangle_contextp_, + ast_contextp_, + cip_, + decl); + std::string source_file = enum_decl_wrapper.GetDeclSourceFile(decl); + if (source_file != current_file_name_) + return true; + std::unique_ptr wrapped_enum_decl = + enum_decl_wrapper.GetEnumDecl(); + if (!wrapped_enum_decl) { + llvm::errs() << "Getting Enum Decl failed\n"; + return false; + } + abi_dump::EnumDecl *enum_declp = tu_ptr_->add_enums(); + if (!enum_declp) { + return false; + } + *enum_declp = *wrapped_enum_decl; return true; } bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) { - std::string source_file = GetDeclSourceFile(decl); - if (source_file != current_file_name_) { + FunctionDeclWrapper function_decl_wrapper(mangle_contextp_, + ast_contextp_, + cip_, + decl); + std::string source_file = function_decl_wrapper.GetDeclSourceFile(decl); + if (source_file != current_file_name_) return true; - } - abi_dump::FunctionDecl *function_decl = tu_ptr_->add_functions(); - - if (!SetupFunction(function_decl, decl, source_file)) { + 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) + return false; + *function_declp = *wrapped_function_decl; return true; } @@ -94,120 +145,6 @@ void HeaderASTConsumer::HandleVTable(clang::CXXRecordDecl *crd) { llvm::errs() << "HandleVTable: " << crd->getName() << "\n"; } -std::string HeaderASTVisitor::GetDeclSourceFile(const clang::NamedDecl *decl) { - clang::SourceManager &SM = cip_->getSourceManager(); - clang::SourceLocation location = decl->getLocation(); - llvm::StringRef file_name= SM.getFilename(location); - return file_name.str(); -} - -std::string HeaderASTVisitor::AccessToString(const clang::AccessSpecifier sp) { - std::string str = "none"; - switch (sp) { - case clang::AS_public: - str = "public"; - break; - case clang::AS_private: - str = "private"; - break; - case clang::AS_protected: - str = "protected"; - break; - default: - break; - } - return str; -} - -std::string HeaderASTVisitor::GetMangledNameDecl(const clang::NamedDecl *decl) { - std::string mangled_or_demangled_name = decl->getName(); - if (mangle_contextp_->shouldMangleDeclName(decl)) { - llvm::raw_string_ostream ostream(mangled_or_demangled_name); - mangle_contextp_->mangleName(decl, ostream); - ostream.flush(); - } - return mangled_or_demangled_name; -} - -bool HeaderASTVisitor::SetupFunction(abi_dump::FunctionDecl *functionp, - const clang::FunctionDecl *decl, - const std::string &source_file) { - // 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. - functionp->set_function_name(decl->getQualifiedNameAsString()); - functionp->set_mangled_function_name(GetMangledNameDecl(decl)); - functionp->set_source_file(source_file); - clang::QualType return_type = - decl->getReturnType().getDesugaredType(*ast_contextp_); - functionp->set_return_type( - clang::TypeName::getFullyQualifiedName(return_type, *ast_contextp_)); - clang::FunctionDecl::param_const_iterator param_it = decl->param_begin(); - while (param_it != 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()); - clang::QualType field_type = - (*param_it)->getType().getDesugaredType(*ast_contextp_); - - function_fieldp->set_field_type( - clang::TypeName::getFullyQualifiedName(field_type, *ast_contextp_)); - param_it++; - } - functionp->set_access(AccessToString(decl->getAccess())); - return true; -} - -bool HeaderASTVisitor::SetupClassFields(abi_dump::RecordDecl *classp, - const clang::CXXRecordDecl *decl, - const std::string &source_file) { - classp->set_fully_qualified_name(decl->getQualifiedNameAsString()); - classp->set_source_file(source_file); - classp->set_entity_type("class"); - clang::RecordDecl::field_iterator field = decl->field_begin(); - while (field != decl->field_end()) { - abi_dump::FieldDecl *class_fieldp = classp->add_fields(); - if (!class_fieldp) { - llvm::errs() << " Couldn't add class field: " << field->getName() - << " to reference dump\n"; - return false; - } - class_fieldp->set_field_name(field->getName()); - clang::QualType field_type = - field->getType().getDesugaredType(*ast_contextp_); - class_fieldp->set_field_type( - clang::TypeName::getFullyQualifiedName(field_type, *ast_contextp_)); - class_fieldp->set_access(AccessToString(field->getAccess())); - field++; - } - return true; -} - -bool HeaderASTVisitor::SetupClassBases(abi_dump::RecordDecl *classp, - const clang::CXXRecordDecl *decl) { - clang::CXXRecordDecl::base_class_const_iterator base_class = - decl->bases_begin(); - while (base_class != decl->bases_end()) { - abi_dump::CXXBaseSpecifier *base_specifierp = classp->add_base_specifiers(); - if (!base_specifierp) { - llvm::errs() << " Couldn't add base specifier to reference dump\n"; - return false; - } - //TODO: Make this pair into a function, used accross. - clang::QualType base_type = - base_class->getType().getDesugaredType(*ast_contextp_); - base_specifierp->set_fully_qualified_name( - clang::TypeName::getFullyQualifiedName(base_type, *ast_contextp_)); - base_specifierp->set_is_virtual(base_class->isVirtual()); - base_specifierp->set_access( - AccessToString(base_class->getAccessSpecifier())); - base_class++; - } - return true; -} - void HeaderASTPPCallbacks::MacroDefined(const clang::Token ¯o_name_tok, const clang::MacroDirective *) { assert(macro_name_tok.isAnyIdentifier()); 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 6d986e532..f007c3e5a 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 @@ -37,27 +37,16 @@ class HeaderASTVisitor const clang::CompilerInstance *compiler_instance_p, const std::string ¤t_file_name); - bool VisitCXXRecordDecl(const clang::CXXRecordDecl *decl); + bool VisitRecordDecl(const clang::RecordDecl *decl); bool VisitFunctionDecl(const clang::FunctionDecl *decl); - private: - bool SetupFunction(abi_dump::FunctionDecl *methodp, - const clang::FunctionDecl *decl, - const std::string &source_file); + bool VisitEnumDecl(const clang::EnumDecl *decl); - bool SetupClassFields(abi_dump::RecordDecl *classp, - const clang::CXXRecordDecl *decl, - const std::string &source_file); - - bool SetupClassBases(abi_dump::RecordDecl *classp, - const clang::CXXRecordDecl *decl); - - std::string GetDeclSourceFile(const clang::NamedDecl *decl); - - std::string AccessToString(const clang::AccessSpecifier sp); - - std::string GetMangledNameDecl(const clang::NamedDecl *decl); + //Enable recursive traversal of template instantiations. + bool shouldVisitTemplateInstantiations() const { + return true; + } private: abi_dump::TranslationUnit *tu_ptr_; diff --git a/vndk/tools/header-checker/proto/abi_dump.proto b/vndk/tools/header-checker/proto/abi_dump.proto index 5e5992202..ff2ee7762 100644 --- a/vndk/tools/header-checker/proto/abi_dump.proto +++ b/vndk/tools/header-checker/proto/abi_dump.proto @@ -15,12 +15,24 @@ message FunctionDecl { repeated FieldDecl parameters = 6; required string return_type = 7 [default = "VOID"]; required string access = 8 [default = "public"]; + required uint32 template_kind = 9 [default = 0]; + required TemplateInfo template_info = 10; } message FieldDecl { required string field_name = 1 [default = "NONE"]; required string field_type = 2 [default = "VOID"]; required string access = 3 [default = "public"]; + required bool default_arg = 4 [default = false]; +} + +message EnumField { + required string enum_field_name = 1 [default = "NONE"]; + required int64 enum_field_value = 2 [default = 0]; // assumption: fits int64 +} + +message TemplateInfo { + repeated FieldDecl template_parameters = 1; } message CXXBaseSpecifier { @@ -38,9 +50,21 @@ message RecordDecl { required string entity_type = 7 [default = "NONE"]; required string source_file = 9 [default = "NONE"]; required bool is_c_struct = 10 [default = false]; + required string template_kind = 11 [default = "NONE"]; + required TemplateInfo template_info = 12; + required string access = 13 [default = "public"]; +} + +message EnumDecl { + required string enum_name = 1 [default = "NONE"]; + required string access = 2 [default = "public"]; + required string enum_type = 3 [default = "int"]; + repeated EnumField enum_fields = 4; + required string source_file = 5 [default = "NONE"]; } message TranslationUnit { repeated RecordDecl classes = 1; repeated FunctionDecl functions = 2; + repeated EnumDecl enums = 3; } diff --git a/vndk/tools/header-checker/tests/example2.h b/vndk/tools/header-checker/tests/example2.h index b1ead4fbb..140eb874c 100644 --- a/vndk/tools/header-checker/tests/example2.h +++ b/vndk/tools/header-checker/tests/example2.h @@ -1,18 +1,62 @@ #ifndef EXAMPLE2_H_ #define EXAMPLE2_H_ +#include + namespace test2 { struct HelloAgain { - int foo_again; + std::unique_ptr foo_again; int bar_again; }; +struct NowWeCrash; } // namespace test2 +enum Foo_s { + foosball = 10, + foosbat +}; + namespace test3 { template struct ByeAgain { T foo_again; int bar_again; + T method_foo(T); }; + +template<> +struct ByeAgain { + float foo_again; + float bar_Again; + float method_foo(int); +}; + +ByeAgain double_bye; + +template +bool Begin(T1 arg1, T2 arg2); +template <> +bool Begin(int a, float b); +bool End ( float arg = 2.0) { + bool ret = Begin(arg, 2); + return ret; +} + + +enum Kind { + kind1 = 24, + kind2 = 2312 +}; + +class Outer { + public: + int a; + private: + class Inner { + int b; + }; +}; + + } // namespace test3 #endif // EXAMPLE2_H_