Merge "Added more information in abi dump."

This commit is contained in:
Treehugger Robot
2017-01-18 19:31:44 +00:00
committed by Gerrit Code Review
5 changed files with 128 additions and 20 deletions

View File

@@ -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 &current_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 &macro_name_tok,
const clang::MacroDirective *) {
assert(macro_name_tok.isAnyIdentifier());

View File

@@ -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 &current_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 {

View File

@@ -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 {

View File

@@ -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_

View 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_