Merge "Added more information in abi dump."
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -27,22 +28,38 @@ HeaderASTVisitor::HeaderASTVisitor(
|
||||
abi_dump::TranslationUnit *tu_ptr,
|
||||
clang::MangleContext *mangle_contextp,
|
||||
const clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p)
|
||||
const clang::CompilerInstance *compiler_instance_p,
|
||||
const std::string ¤t_file_name)
|
||||
: tu_ptr_(tu_ptr),
|
||||
mangle_contextp_(mangle_contextp),
|
||||
ast_contextp_(ast_contextp),
|
||||
cip_(compiler_instance_p) { }
|
||||
cip_(compiler_instance_p),
|
||||
current_file_name_(current_file_name) { }
|
||||
|
||||
bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
|
||||
// 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);
|
||||
if (source_file != current_file_name_)
|
||||
return true;
|
||||
abi_dump::RecordDecl *record_decl = tu_ptr_->add_classes();
|
||||
SetupClassFields(record_decl, decl);
|
||||
if (!SetupClassFields(record_decl, decl, source_file) ||
|
||||
!SetupClassBases(record_decl, decl)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
|
||||
std::string source_file = GetDeclSourceFile(decl);
|
||||
if (source_file != current_file_name_) {
|
||||
return true;
|
||||
}
|
||||
abi_dump::FunctionDecl *function_decl = tu_ptr_->add_functions();
|
||||
// FIXME: Use return value.
|
||||
SetupFunction(function_decl, decl);
|
||||
|
||||
if (!SetupFunction(function_decl, decl, source_file)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -59,7 +76,7 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||
std::unique_ptr<clang::MangleContext> mangle_contextp(
|
||||
ctx.createMangleContext());
|
||||
abi_dump::TranslationUnit tu;
|
||||
HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_);
|
||||
HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_, file_name_);
|
||||
v.TraverseDecl(translation_unit);
|
||||
std::ofstream text_output(out_dump_name_ + ".txt");
|
||||
std::fstream binary_output(
|
||||
@@ -84,6 +101,24 @@ std::string HeaderASTVisitor::GetDeclSourceFile(const clang::NamedDecl *decl) {
|
||||
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)) {
|
||||
@@ -95,12 +130,13 @@ std::string HeaderASTVisitor::GetMangledNameDecl(const clang::NamedDecl *decl) {
|
||||
}
|
||||
|
||||
bool HeaderASTVisitor::SetupFunction(abi_dump::FunctionDecl *functionp,
|
||||
const clang::FunctionDecl *decl) {
|
||||
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(GetDeclSourceFile(decl));
|
||||
functionp->set_source_file(source_file);
|
||||
clang::QualType return_type =
|
||||
decl->getReturnType().getDesugaredType(*ast_contextp_);
|
||||
functionp->set_return_type(
|
||||
@@ -109,7 +145,7 @@ bool HeaderASTVisitor::SetupFunction(abi_dump::FunctionDecl *functionp,
|
||||
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";
|
||||
llvm::errs() << "Couldn't add parameter to method. Aborting\n";
|
||||
return false;
|
||||
}
|
||||
function_fieldp->set_field_name((*param_it)->getName());
|
||||
@@ -118,16 +154,17 @@ bool HeaderASTVisitor::SetupFunction(abi_dump::FunctionDecl *functionp,
|
||||
|
||||
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::RecordDecl *decl) {
|
||||
const clang::CXXRecordDecl *decl,
|
||||
const std::string &source_file) {
|
||||
classp->set_fully_qualified_name(decl->getQualifiedNameAsString());
|
||||
classp->set_source_file(GetDeclSourceFile(decl));
|
||||
classp->set_source_file(source_file);
|
||||
classp->set_entity_type("class");
|
||||
clang::RecordDecl::field_iterator field = decl->field_begin();
|
||||
while (field != decl->field_end()) {
|
||||
@@ -138,16 +175,39 @@ bool HeaderASTVisitor::SetupClassFields(abi_dump::RecordDecl *classp,
|
||||
return false;
|
||||
}
|
||||
class_fieldp->set_field_name(field->getName());
|
||||
//FIXME: This needs to change. Resolve typedef, class name, built-in etc.
|
||||
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());
|
||||
|
||||
@@ -34,21 +34,29 @@ class HeaderASTVisitor
|
||||
HeaderASTVisitor(abi_dump::TranslationUnit *tu_ptr,
|
||||
clang::MangleContext *mangle_contextp,
|
||||
const clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p);
|
||||
const clang::CompilerInstance *compiler_instance_p,
|
||||
const std::string ¤t_file_name);
|
||||
|
||||
bool VisitRecordDecl(const clang::RecordDecl *decl);
|
||||
bool VisitCXXRecordDecl(const clang::CXXRecordDecl *decl);
|
||||
|
||||
bool VisitFunctionDecl(const clang::FunctionDecl *decl);
|
||||
|
||||
private:
|
||||
bool SetupFunction(abi_dump::FunctionDecl *methodp,
|
||||
const clang::FunctionDecl *decl);
|
||||
const clang::FunctionDecl *decl,
|
||||
const std::string &source_file);
|
||||
|
||||
bool SetupClassFields(abi_dump::RecordDecl *classp,
|
||||
const clang::RecordDecl *decl);
|
||||
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);
|
||||
|
||||
private:
|
||||
@@ -56,6 +64,7 @@ class HeaderASTVisitor
|
||||
clang::MangleContext *mangle_contextp_;
|
||||
const clang::ASTContext *ast_contextp_;
|
||||
const clang::CompilerInstance *cip_;
|
||||
const std::string current_file_name_;
|
||||
};
|
||||
|
||||
class HeaderASTConsumer : public clang::ASTConsumer {
|
||||
|
||||
@@ -14,21 +14,30 @@ message FunctionDecl {
|
||||
repeated string template_arguments = 5 ;
|
||||
repeated FieldDecl parameters = 6;
|
||||
required string return_type = 7 [default = "VOID"];
|
||||
required string access = 8 [default = "public"];
|
||||
}
|
||||
|
||||
message FieldDecl {
|
||||
required string field_name = 1 [default = "NONE"];
|
||||
required string field_type = 2 [default = "VOID"];
|
||||
required string access = 3 [default = "public"];
|
||||
}
|
||||
|
||||
message CXXBaseSpecifier {
|
||||
required string fully_qualified_name = 1 [default = "NONE"];
|
||||
required string access = 2 [default = "public"];
|
||||
required bool is_virtual = 3 [default = false];
|
||||
}
|
||||
|
||||
message RecordDecl {
|
||||
repeated FieldDecl fields = 2;
|
||||
repeated string inner_classes = 3;
|
||||
repeated string base_classes = 4;
|
||||
repeated CXXBaseSpecifier base_specifiers = 4;
|
||||
required string fully_qualified_name = 5 [default = "NONE"];
|
||||
required int64 id = 6 [default = 0];
|
||||
required string entity_type = 7 [default = "NONE"];
|
||||
required string source_file = 9;
|
||||
required string source_file = 9 [default = "NONE"];
|
||||
required bool is_c_struct = 10 [default = false];
|
||||
}
|
||||
|
||||
message TranslationUnit {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef EXAMPLE1_H_
|
||||
#define EXAMPLE1_H_
|
||||
|
||||
#include "example2.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -13,6 +15,14 @@ struct Hello {
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
using namespace test2;
|
||||
using namespace test3;
|
||||
typedef float float_type;
|
||||
typedef const float_type cfloat_type;
|
||||
struct CPPHello : private HelloAgain, public ByeAgain<float_type> {
|
||||
const int cpp_foo;
|
||||
cfloat_type cpp_bar;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct StackNode {
|
||||
@@ -47,4 +57,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
const volatile int Global_Foo(int global_bar);
|
||||
|
||||
#endif // EXAMPLE1_H_
|
||||
|
||||
18
vndk/tools/header-checker/tests/example2.h
Normal file
18
vndk/tools/header-checker/tests/example2.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef EXAMPLE2_H_
|
||||
#define EXAMPLE2_H_
|
||||
namespace test2 {
|
||||
struct HelloAgain {
|
||||
int foo_again;
|
||||
int bar_again;
|
||||
};
|
||||
} // namespace test2
|
||||
|
||||
namespace test3 {
|
||||
template <typename T>
|
||||
struct ByeAgain {
|
||||
T foo_again;
|
||||
int bar_again;
|
||||
};
|
||||
} // namespace test3
|
||||
|
||||
#endif // EXAMPLE2_H_
|
||||
Reference in New Issue
Block a user