Seperated out protobuf impl into wrapper classes. am: 2920754397
am: 85204bdd59
Change-Id: I0fd503ad5176efa6d16678e957a9c6a1d3a8510c
This commit is contained in:
326
vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp
Normal file
326
vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.cpp
Normal file
@@ -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 <clang/Tooling/Core/QualTypeNames.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
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<abi_dump::FunctionDecl> FunctionDeclWrapper::GetFunctionDecl() const {
|
||||
std::unique_ptr<abi_dump::FunctionDecl> 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<clang::CXXRecordDecl>(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<clang::CXXRecordDecl>(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<clang::ClassTemplateSpecializationDecl>(
|
||||
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<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_);
|
||||
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<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_);
|
||||
|
||||
if (!SetupEnum(abi_decl.get(), source_file)) {
|
||||
llvm::errs() << "Setting up Enum fields failed\n";
|
||||
return nullptr;
|
||||
}
|
||||
return abi_decl;
|
||||
}
|
||||
119
vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h
Normal file
119
vndk/tools/header-checker/header-abi-dumper/src/abi_wrappers.h
Normal file
@@ -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 <clang/AST/AST.h>
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/Mangle.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
|
||||
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<abi_dump::RecordDecl> 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<abi_dump::FunctionDecl> 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<abi_dump::EnumDecl> 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_
|
||||
@@ -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 <clang/Lex/Token.h>
|
||||
#include <clang/Tooling/Core/QualTypeNames.h>
|
||||
@@ -24,6 +24,10 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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<abi_dump::RecordDecl> 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<abi_dump::EnumDecl> 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<abi_dump::FunctionDecl> 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());
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,62 @@
|
||||
#ifndef EXAMPLE2_H_
|
||||
#define EXAMPLE2_H_
|
||||
#include <memory>
|
||||
|
||||
namespace test2 {
|
||||
struct HelloAgain {
|
||||
int foo_again;
|
||||
std::unique_ptr<HelloAgain> foo_again;
|
||||
int bar_again;
|
||||
};
|
||||
struct NowWeCrash;
|
||||
} // namespace test2
|
||||
|
||||
enum Foo_s {
|
||||
foosball = 10,
|
||||
foosbat
|
||||
};
|
||||
|
||||
namespace test3 {
|
||||
template <typename T>
|
||||
struct ByeAgain {
|
||||
T foo_again;
|
||||
int bar_again;
|
||||
T method_foo(T);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ByeAgain<float> {
|
||||
float foo_again;
|
||||
float bar_Again;
|
||||
float method_foo(int);
|
||||
};
|
||||
|
||||
ByeAgain<double> double_bye;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool Begin(T1 arg1, T2 arg2);
|
||||
template <>
|
||||
bool Begin<int, float>(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_
|
||||
|
||||
Reference in New Issue
Block a user