From 3d1ad14df9f5732210b8da64b234f5434d761607 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Chen Date: Tue, 30 Oct 2018 18:48:49 +0800 Subject: [PATCH] Add a command line option to dump function declarations If -dump-function-declarations is specified, header-abi-dumper outputs the functions declared but not defined in the input file. The command line option can be used to dump header files. Test: header-abi-dumper -suppress-errors -dump-function-declarations system/libfmq/include/fmq/MessageQueue.h -o test.txt -- Bug: 117582158 Bug: 71485848 Change-Id: I85a3944047e085a032779a69b04ac5211f3b9467 --- .../header-abi-dumper/src/ast_processing.cpp | 35 ++++++++++--------- .../header-abi-dumper/src/ast_processing.h | 12 +++---- .../header-abi-dumper/src/header_checker.cpp | 11 ++++-- .../header-abi-dumper/src/header_checker.h | 13 ++++--- 4 files changed, 42 insertions(+), 29 deletions(-) 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 c7c8ff992..e4056a001 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 @@ -31,20 +31,14 @@ using abi_wrapper::EnumDeclWrapper; using abi_wrapper::GlobalVarDeclWrapper; HeaderASTVisitor::HeaderASTVisitor( - clang::MangleContext *mangle_contextp, + const HeaderCheckerOptions &options, clang::MangleContext *mangle_contextp, clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, - const std::set &exported_headers, - const clang::Decl *tu_decl, - abi_util::IRDumper *ir_dumper, + const clang::Decl *tu_decl, abi_util::IRDumper *ir_dumper, ast_util::ASTCaches *ast_caches) - : mangle_contextp_(mangle_contextp), - ast_contextp_(ast_contextp), - cip_(compiler_instance_p), - exported_headers_(exported_headers), - tu_decl_(tu_decl), - ir_dumper_(ir_dumper), - ast_caches_(ast_caches) {} + : options_(options), mangle_contextp_(mangle_contextp), + ast_contextp_(ast_contextp), cip_(compiler_instance_p), tu_decl_(tu_decl), + ir_dumper_(ir_dumper), ast_caches_(ast_caches) {} bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { // Avoid segmentation fault in getASTRecordLayout. @@ -96,8 +90,15 @@ static bool AddMangledFunctions(const abi_util::FunctionIR *function, return true; } -static bool ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) { +bool HeaderASTVisitor::ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) { if (!decl->getDefinition()) { + if (!options_.dump_function_declarations_ || + options_.source_file_ != ABIWrapper::GetDeclSourceFile(decl, cip_)) { + return true; + } + } + // Skip explicitly deleted functions such as `Foo operator=(Foo) = delete;`. + if (decl->isDeleted()) { return true; } if (decl->getLinkageAndVisibility().getLinkage() != @@ -165,8 +166,9 @@ bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) { ast_caches_->decl_to_source_file_cache_.insert( std::make_pair(decl, source_file)); // If no exported headers are specified we assume the whole AST is exported. - if ((decl != tu_decl_) && AreHeadersExported(exported_headers_) && - (exported_headers_.find(source_file) == exported_headers_.end())) { + const auto &exported_headers = options_.exported_headers_; + if ((decl != tu_decl_) && AreHeadersExported(exported_headers) && + (exported_headers.find(source_file) == exported_headers.end())) { return true; } // If at all we're looking at the source file's AST decl node, it should be a @@ -202,9 +204,8 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) { std::unique_ptr ir_dumper = abi_util::IRDumper::CreateIRDumper(options_.text_format_, options_.dump_name_); - HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, - options_.exported_headers_, translation_unit, - ir_dumper.get(), &ast_caches); + HeaderASTVisitor v(options_, mangle_contextp.get(), &ctx, cip_, + translation_unit, ir_dumper.get(), &ast_caches); if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) { llvm::errs() << "Serialization to ostream failed\n"; 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 c234db05a..4e8cd5969 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 @@ -30,10 +30,10 @@ class HeaderASTVisitor : public clang::RecursiveASTVisitor { public: - HeaderASTVisitor(clang::MangleContext *mangle_contextp, + HeaderASTVisitor(const HeaderCheckerOptions &options, + clang::MangleContext *mangle_contextp, clang::ASTContext *ast_contextp, const clang::CompilerInstance *compiler_instance_p, - const std::set &exported_headers, const clang::Decl *tu_decl, abi_util::IRDumper *ir_dumper, ast_util::ASTCaches *ast_caches); @@ -49,15 +49,15 @@ class HeaderASTVisitor bool TraverseDecl(clang::Decl *decl); // Enable recursive traversal of template instantiations. - bool shouldVisitTemplateInstantiations() const { - return true; - } + bool shouldVisitTemplateInstantiations() const { return true; } private: + bool ShouldSkipFunctionDecl(const clang::FunctionDecl *decl); + + const HeaderCheckerOptions &options_; clang::MangleContext *mangle_contextp_; clang::ASTContext *ast_contextp_; const clang::CompilerInstance *cip_; - const std::set &exported_headers_; // To optimize recursion into only exported abi. const clang::Decl *tu_decl_; abi_util::IRDumper *ir_dumper_; diff --git a/vndk/tools/header-checker/header-abi-dumper/src/header_checker.cpp b/vndk/tools/header-checker/header-abi-dumper/src/header_checker.cpp index 1661634b0..25f352b95 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/header_checker.cpp +++ b/vndk/tools/header-checker/header-abi-dumper/src/header_checker.cpp @@ -57,6 +57,12 @@ static llvm::cl::opt suppress_errors( llvm::cl::desc("Suppress preprocess and semantic errors"), llvm::cl::Optional, llvm::cl::cat(header_checker_category)); +static llvm::cl::opt dump_function_declarations( + "dump-function-declarations", + llvm::cl::desc("Output the functions declared but not defined in the input " + "file"), + llvm::cl::Optional, llvm::cl::cat(header_checker_category)); + static llvm::cl::opt output_format( "output-format", llvm::cl::desc("Specify format of output dump file"), llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat, @@ -130,8 +136,9 @@ int main(int argc, const char **argv) { // Initialize clang tools and run front-end action. std::vector header_files{ header_file }; - HeaderCheckerOptions options(out_dump, std::move(exported_headers), - output_format, suppress_errors); + HeaderCheckerOptions options(abi_util::RealPath(header_file), out_dump, + std::move(exported_headers), output_format, + dump_function_declarations, suppress_errors); clang::tooling::ClangTool tool(*compilations, header_files); std::unique_ptr factory( diff --git a/vndk/tools/header-checker/header-abi-dumper/src/header_checker.h b/vndk/tools/header-checker/header-abi-dumper/src/header_checker.h index cb695e6d1..8fe4ebbc7 100644 --- a/vndk/tools/header-checker/header-abi-dumper/src/header_checker.h +++ b/vndk/tools/header-checker/header-abi-dumper/src/header_checker.h @@ -22,18 +22,23 @@ class HeaderCheckerOptions { public: + std::string source_file_; std::string dump_name_; std::set exported_headers_; abi_util::TextFormatIR text_format_; + bool dump_function_declarations_; bool suppress_errors_; public: - HeaderCheckerOptions(std::string dump_name, + HeaderCheckerOptions(std::string source_file, std::string dump_name, std::set exported_headers, - abi_util::TextFormatIR text_format, bool suppress_errors) - : dump_name_(std::move(dump_name)), + abi_util::TextFormatIR text_format, + bool dump_function_declarations, bool suppress_errors) + : source_file_(std::move(source_file)), dump_name_(std::move(dump_name)), exported_headers_(std::move(exported_headers)), - text_format_(text_format), suppress_errors_(suppress_errors) {} + text_format_(text_format), + dump_function_declarations_(dump_function_declarations), + suppress_errors_(suppress_errors) {} }; #endif // HEADER_CHECKER_H_