Merge "Optimization : Do not recurse into unexported Abi."
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 637542c..d2cd9f5 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
@@ -23,13 +23,14 @@
 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) { }
+    const clang::CompilerInstance *cip)
+  : cip_(cip),
+    mangle_contextp_(mangle_contextp),
+    ast_contextp_(ast_contextp) { }
 
-std::string ABIWrapper::GetDeclSourceFile(const clang::NamedDecl *decl) const {
-  clang::SourceManager &sm = cip_->getSourceManager();
+std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
+                                          const clang::CompilerInstance *cip) {
+  clang::SourceManager &sm = cip->getSourceManager();
   clang::SourceLocation location = decl->getLocation();
   llvm::StringRef file_name = sm.getFilename(location);
   llvm::SmallString<128> abs_path(file_name.str());
@@ -199,7 +200,7 @@
 FunctionDeclWrapper::GetFunctionDecl() const {
   std::unique_ptr<abi_dump::FunctionDecl> abi_decl(
       new abi_dump::FunctionDecl());
-  std::string source_file = GetDeclSourceFile(function_decl_);
+  std::string source_file = GetDeclSourceFile(function_decl_, cip_);
   if (!SetupFunction(abi_decl.get(), source_file)) {
     return nullptr;
   }
@@ -316,7 +317,7 @@
 
 std::unique_ptr<abi_dump::RecordDecl> RecordDeclWrapper::GetRecordDecl() const {
   std::unique_ptr<abi_dump::RecordDecl> abi_decl(new abi_dump::RecordDecl());
-  std::string source_file = GetDeclSourceFile(record_decl_);
+  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";
@@ -362,7 +363,7 @@
 
 std::unique_ptr<abi_dump::EnumDecl> EnumDeclWrapper::GetEnumDecl() const {
   std::unique_ptr<abi_dump::EnumDecl> abi_decl(new abi_dump::EnumDecl());
-  std::string source_file = GetDeclSourceFile(enum_decl_);
+  std::string source_file = GetDeclSourceFile(enum_decl_, cip_);
 
   if (!SetupEnum(abi_decl.get(), source_file)) {
     llvm::errs() << "Setting up Enum fields failed\n";
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 4beb216..bdb0274 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
@@ -31,9 +31,10 @@
  public:
   ABIWrapper(clang::MangleContext *mangle_contextp,
              const clang::ASTContext *ast_contextp,
-             const clang::CompilerInstance *compiler_instance_p);
+             const clang::CompilerInstance *cip);
 
-  std::string GetDeclSourceFile(const clang::NamedDecl *decl) const;
+  static std::string GetDeclSourceFile(const clang::Decl *decl,
+                                       const clang::CompilerInstance *cip);
 
  protected:
   std::string AccessToString(const clang::AccessSpecifier sp) const;
@@ -49,10 +50,13 @@
   std::string QualTypeToString(const clang::QualType &sweet_qt) const;
 
   std::string GetTagDeclQualifiedName(const clang::TagDecl *decl) const;
+
+ protected:
+  const clang::CompilerInstance *cip_;
+
  private:
   clang::MangleContext *mangle_contextp_;
   const clang::ASTContext *ast_contextp_;
-  const clang::CompilerInstance *cip_;
 };
 
 class RecordDeclWrapper : public ABIWrapper {
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 d5fe042..ec1aa71 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
@@ -25,6 +25,7 @@
 #include <iostream>
 #include <string>
 
+using abi_wrapper::ABIWrapper;
 using abi_wrapper::FunctionDeclWrapper;
 using abi_wrapper::RecordDeclWrapper;
 using abi_wrapper::EnumDeclWrapper;
@@ -35,13 +36,15 @@
     const clang::ASTContext *ast_contextp,
     const clang::CompilerInstance *compiler_instance_p,
     const std::string &current_file_name,
-    const std::set<std::string> &exported_headers)
+    const std::set<std::string> &exported_headers,
+    const clang::Decl *tu_decl)
   : tu_ptr_(tu_ptr),
     mangle_contextp_(mangle_contextp),
     ast_contextp_(ast_contextp),
     cip_(compiler_instance_p),
     current_file_name_(current_file_name),
-    exported_headers_(exported_headers) { }
+    exported_headers_(exported_headers),
+    tu_decl_(tu_decl) { }
 
 bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
   // Forward declaration
@@ -50,12 +53,6 @@
   }
   RecordDeclWrapper record_decl_wrapper(
       mangle_contextp_, ast_contextp_, cip_, decl);
-  // TODO: Optimize source file initial check by preferably moving this into
-  // TraverseTranslationUnitDecl.
-  std::string source_file = record_decl_wrapper.GetDeclSourceFile(decl);
-  if (exported_headers_.find(source_file) == exported_headers_.end()) {
-    return true;
-  }
   std::unique_ptr<abi_dump::RecordDecl> wrapped_record_decl =
       record_decl_wrapper.GetRecordDecl();
   if (!wrapped_record_decl) {
@@ -76,10 +73,6 @@
   }
   EnumDeclWrapper enum_decl_wrapper(
       mangle_contextp_, ast_contextp_, cip_, decl);
-  std::string source_file = enum_decl_wrapper.GetDeclSourceFile(decl);
-  if (exported_headers_.find(source_file) == exported_headers_.end()) {
-    return true;
-  }
   std::unique_ptr<abi_dump::EnumDecl> wrapped_enum_decl =
       enum_decl_wrapper.GetEnumDecl();
   if (!wrapped_enum_decl) {
@@ -97,12 +90,6 @@
 bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
   FunctionDeclWrapper function_decl_wrapper(
       mangle_contextp_, ast_contextp_, cip_, decl);
-  // TODO: Optimize source file initial check by preferably moving this into
-  // TraverseTranslationUnitDecl.
-  std::string source_file = function_decl_wrapper.GetDeclSourceFile(decl);
-  if (exported_headers_.find(source_file) == exported_headers_.end()) {
-    return true;
-  }
   std::unique_ptr<abi_dump::FunctionDecl> wrapped_function_decl =
       function_decl_wrapper.GetFunctionDecl();
   if (!wrapped_function_decl) {
@@ -117,6 +104,18 @@
   return true;
 }
 
+// We don't need to recurse into Declarations which are not exported.
+bool HeaderASTVisitor::TraverseDecl(clang::Decl *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())) {
+    return true;
+  }
+  return RecursiveASTVisitor<HeaderASTVisitor>::TraverseDecl(decl);
+}
+
 HeaderASTConsumer::HeaderASTConsumer(
     const std::string &file_name,
     clang::CompilerInstance *compiler_instancep,
@@ -131,13 +130,13 @@
   GOOGLE_PROTOBUF_VERIFY_VERSION;
   std::ofstream text_output(out_dump_name_);
   google::protobuf::io::OstreamOutputStream text_os(&text_output);
-  clang::TranslationUnitDecl* translation_unit = ctx.getTranslationUnitDecl();
+  clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl();
   std::unique_ptr<clang::MangleContext> mangle_contextp(
       ctx.createMangleContext());
   abi_dump::TranslationUnit tu;
   std::string str_out;
   HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_, file_name_,
-                     exported_headers_);
+                     exported_headers_, translation_unit);
   if (!v.TraverseDecl(translation_unit) ||
       !google::protobuf::TextFormat::Print(tu, &text_os)) {
     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 00dcfce..b66dea4 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
@@ -38,7 +38,8 @@
                    const clang::ASTContext *ast_contextp,
                    const clang::CompilerInstance *compiler_instance_p,
                    const std::string &current_file_name,
-                   const std::set<std::string> &exported_headers);
+                   const std::set<std::string> &exported_headers,
+                   const clang::Decl *tu_decl);
 
   bool VisitRecordDecl(const clang::RecordDecl *decl);
 
@@ -46,6 +47,8 @@
 
   bool VisitEnumDecl(const clang::EnumDecl *decl);
 
+  bool TraverseDecl(clang::Decl *decl);
+
   // Enable recursive traversal of template instantiations.
   bool shouldVisitTemplateInstantiations() const {
     return true;
@@ -58,6 +61,8 @@
   const clang::CompilerInstance *cip_;
   const std::string current_file_name_;
   const std::set<std::string> &exported_headers_;
+  // To optimize recursion into only exported abi.
+  const clang::Decl *tu_decl_;
 };
 
 class HeaderASTConsumer : public clang::ASTConsumer {