Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2016 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "abi_wrappers.h"
     16 
     17 #include <header_abi_util.h>
     18 
     19 #include <limits.h>
     20 #include <stdlib.h>
     21 #include <clang/Tooling/Core/QualTypeNames.h>
     22 #include <clang/Index/CodegenNameGenerator.h>
     23 
     24 #include <string>
     25 
     26 using namespace abi_wrapper;
     27 
     28 ABIWrapper::ABIWrapper(
     29     clang::MangleContext *mangle_contextp,
     30     clang::ASTContext *ast_contextp,
     31     const clang::CompilerInstance *cip)
     32   : cip_(cip),
     33     mangle_contextp_(mangle_contextp),
     34     ast_contextp_(ast_contextp) { }
     35 
     36 std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
     37                                           const clang::CompilerInstance *cip) {
     38   clang::SourceManager &sm = cip->getSourceManager();
     39   clang::SourceLocation location = decl->getLocation();
     40   // We need to use the expansion location to identify whether we should recurse
     41   // into the AST Node or not. For eg: macros specifying LinkageSpecDecl can
     42   // have their spelling location defined somewhere outside a source / header
     43   // file belonging to a library. This should not allow the AST node to be
     44   // skipped. Its expansion location will still be the source-file / header
     45   // belonging to the library.
     46   clang::SourceLocation expansion_location = sm.getExpansionLoc(location);
     47   llvm::StringRef file_name = sm.getFilename(expansion_location);
     48   std::string file_name_adjusted = "";
     49   char file_abs_path[PATH_MAX];
     50   if (realpath(file_name.str().c_str(), file_abs_path) == nullptr) {
     51     return "";
     52   }
     53   return file_abs_path;
     54 }
     55 
     56 abi_dump::AccessSpecifier ABIWrapper::AccessClangToDump(
     57     const clang::AccessSpecifier sp) const {
     58   switch (sp) {
     59     case clang::AS_private: {
     60       return abi_dump::AccessSpecifier::private_access;
     61       break;
     62     }
     63     case clang::AS_protected: {
     64       return abi_dump::AccessSpecifier::protected_access;
     65       break;
     66     }
     67     default: {
     68       return abi_dump::AccessSpecifier::public_access;
     69       break;
     70     }
     71   }
     72 }
     73 
     74 // Dumping the size and alignment is optional. This is since clang can lazily
     75 // instantiate records as incomplete and therefore their sizes 'may' not be
     76 // computable. b/62307940
     77 bool ABIWrapper::SetupBasicTypeAbi(abi_dump::BasicTypeAbi *type_abi,
     78                                    const clang::QualType type,
     79                                    bool dump_size) const {
     80   if (!type_abi) {
     81     return false;
     82   }
     83   const clang::QualType canonical_type = type.getCanonicalType();
     84   type_abi->set_name(QualTypeToString(canonical_type));
     85   // Cannot determine the size and alignment for template parameter dependent
     86   // types as well as incomplete types.
     87   const clang::Type *base_type = canonical_type.getTypePtr();
     88   clang::Type::TypeClass type_class = base_type->getTypeClass();
     89   // Temporary Hack for auto type sizes. Not determinable.
     90   if (dump_size && base_type && !(base_type->isDependentType()) &&
     91       !(base_type->isIncompleteType()) && (type_class != clang::Type::Auto)) {
     92     std::pair<clang::CharUnits, clang::CharUnits> size_and_alignment =
     93     ast_contextp_->getTypeInfoInChars(canonical_type);
     94     int64_t size = size_and_alignment.first.getQuantity();
     95     int64_t alignment = size_and_alignment.second.getQuantity();
     96     type_abi->set_size(size);
     97     type_abi->set_alignment(alignment);
     98   }
     99   return true;
    100 }
    101 
    102 bool ABIWrapper::SetupBasicNamedAndTypedDecl(
    103     abi_dump::BasicNamedAndTypedDecl *basic_named_and_typed_decl,
    104     const clang::QualType type, const std::string &name,
    105     const clang::AccessSpecifier &access, std::string key,
    106     bool dump_size) const {
    107   if (!basic_named_and_typed_decl) {
    108     return false;
    109   }
    110   abi_dump::AccessSpecifier access_dump = AccessClangToDump(access);
    111   basic_named_and_typed_decl->set_name(name);
    112   basic_named_and_typed_decl->set_access(access_dump);
    113   if (key != "") {
    114     basic_named_and_typed_decl->set_linker_set_key(key);
    115   }
    116   return SetupBasicTypeAbi(basic_named_and_typed_decl->mutable_type_abi(),
    117                            type, dump_size);
    118 }
    119 
    120 static bool ShouldDumpSize(clang::QualType qt) {
    121   const clang::Type *type_ptr = qt.getTypePtr();
    122   assert(type_ptr != nullptr);
    123   if (type_ptr->isBuiltinType() || type_ptr->isPointerType()) {
    124     return true;
    125   }
    126   return false;
    127 }
    128 
    129 std::string ABIWrapper::GetTypeLinkageName(const clang::Type *typep) const {
    130   assert(typep != nullptr);
    131   clang::QualType qt = typep->getCanonicalTypeInternal();
    132   return QualTypeToString(qt);
    133 }
    134 
    135 std::string ABIWrapper::GetMangledNameDecl(
    136     const clang::NamedDecl *decl, clang::MangleContext *mangle_contextp) {
    137   if (!mangle_contextp->shouldMangleDeclName(decl)) {
    138     clang::IdentifierInfo *identifier = decl->getIdentifier();
    139     return identifier ? identifier->getName() : "";
    140   }
    141   std::string mangled_name;
    142   llvm::raw_string_ostream ostream(mangled_name);
    143   mangle_contextp->mangleName(decl, ostream);
    144   ostream.flush();
    145   return mangled_name;
    146 }
    147 
    148 bool ABIWrapper::SetupTemplateParamNames(
    149     abi_dump::TemplateInfo *tinfo,
    150     clang::TemplateParameterList *pl) const {
    151   if (tinfo->elements_size() > 0) {
    152     return true;
    153   }
    154 
    155   clang::TemplateParameterList::iterator template_it = pl->begin();
    156   while (template_it != pl->end()) {
    157     abi_dump::TemplateElement *template_parameterp =
    158         tinfo->add_elements();
    159     if (!template_parameterp) {
    160       return false;
    161     }
    162     abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi =
    163         template_parameterp->mutable_basic_abi();
    164     if (!basic_abi) {
    165       return false;
    166     }
    167     std::string name = (*template_it)->getName();
    168     basic_abi->set_name(name);
    169     // TODO : Default arg ?
    170     basic_abi->set_linker_set_key(name);
    171     template_it++;
    172   }
    173   return true;
    174 }
    175 
    176 std::string ABIWrapper::GetTagDeclQualifiedName(
    177     const clang::TagDecl *decl) const {
    178   if (decl->getTypedefNameForAnonDecl()) {
    179     return decl->getTypedefNameForAnonDecl()->getQualifiedNameAsString();
    180   }
    181   return decl->getQualifiedNameAsString();
    182 }
    183 
    184 bool ABIWrapper::SetupTemplateArguments(
    185     abi_dump::TemplateInfo *tinfo,
    186     const clang::TemplateArgumentList *tl) const {
    187   for (int i = 0; i < tl->size(); i++) {
    188     const clang::TemplateArgument &arg = (*tl)[i];
    189     //TODO: More comprehensive checking needed.
    190     if (arg.getKind() != clang::TemplateArgument::Type) {
    191       continue;
    192     }
    193     clang::QualType type = arg.getAsType();
    194     abi_dump::TemplateElement *template_parameterp =
    195         tinfo->add_elements();
    196     if (!template_parameterp) {
    197       return false;
    198     }
    199     abi_dump::TemplateElement::BasicTemplateElementAbi *basic_abi =
    200         template_parameterp->mutable_basic_abi();
    201     if (!basic_abi || !SetupBasicTypeAbi(basic_abi->mutable_type_abi(), type,
    202                                          false)) {
    203       return false;
    204     }
    205     // TODO : default arg
    206     basic_abi->set_linker_set_key(QualTypeToString(type));
    207   }
    208   return true;
    209 }
    210 
    211 std::string ABIWrapper::QualTypeToString(
    212     const clang::QualType &sweet_qt) const {
    213   const clang::QualType salty_qt = sweet_qt.getCanonicalType();
    214   // clang::TypeName::getFullyQualifiedName removes the part of the type related
    215   // to it being a template parameter. Don't use it for dependent types.
    216   if (salty_qt.getTypePtr()->isDependentType()) {
    217     return salty_qt.getAsString();
    218   }
    219   return clang::TypeName::getFullyQualifiedName(salty_qt, *ast_contextp_);
    220 }
    221 
    222 FunctionDeclWrapper::FunctionDeclWrapper(
    223     clang::MangleContext *mangle_contextp,
    224     clang::ASTContext *ast_contextp,
    225     const clang::CompilerInstance *compiler_instance_p,
    226     const clang::FunctionDecl *decl)
    227   : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
    228     function_decl_(decl) { }
    229 
    230 bool FunctionDeclWrapper::SetupFunctionParameters(
    231     abi_dump::FunctionDecl *functionp) const {
    232   clang::FunctionDecl::param_const_iterator param_it =
    233       function_decl_->param_begin();
    234   while (param_it != function_decl_->param_end()) {
    235     abi_dump::ParamDecl *function_fieldp = functionp->add_parameters();
    236     if (!function_fieldp) {
    237       llvm::errs() << "Couldn't add parameter to method. Aborting\n";
    238       return false;
    239     }
    240     // The linker set key is blank since that shows up in the mangled name.
    241     bool has_default_arg = (*param_it)->hasDefaultArg();
    242     clang::QualType param_qt = (*param_it)->getType();
    243     bool should_dump_size = ShouldDumpSize(param_qt);
    244     if (!SetupBasicNamedAndTypedDecl(
    245         function_fieldp->mutable_basic_abi(),
    246         (*param_it)->getType(), (*param_it)->getName(),
    247         (*param_it)->getAccess(), has_default_arg ? "true" : "false",
    248         should_dump_size)) {
    249       return false;
    250     }
    251     function_fieldp->set_default_arg(has_default_arg);
    252     param_it++;
    253   }
    254   return true;
    255 }
    256 
    257 bool FunctionDeclWrapper::SetupFunction(abi_dump::FunctionDecl *functionp,
    258                                         const std::string &source_file) const {
    259   // Go through all the parameters in the method and add them to the fields.
    260   // Also get the fully qualfied name.
    261   functionp->set_source_file(source_file);
    262   // Combine the function name and return type to form a NamedAndTypedDecl
    263   clang::QualType return_type = function_decl_->getReturnType();
    264   bool should_dump_size = ShouldDumpSize(return_type);
    265   return SetupBasicNamedAndTypedDecl(
    266       functionp->mutable_basic_abi(),
    267       return_type, function_decl_->getQualifiedNameAsString(),
    268       function_decl_->getAccess(), "", should_dump_size) &&
    269       SetupTemplateInfo(functionp) && SetupFunctionParameters(functionp);
    270 }
    271 
    272 bool FunctionDeclWrapper::SetupTemplateInfo(
    273     abi_dump::FunctionDecl *functionp) const {
    274   switch (function_decl_->getTemplatedKind()) {
    275     case clang::FunctionDecl::TK_FunctionTemplate: {
    276       clang::FunctionTemplateDecl *template_decl =
    277           function_decl_->getDescribedFunctionTemplate();
    278       if (template_decl) {
    279         clang::TemplateParameterList *template_parameter_list =
    280             template_decl->getTemplateParameters();
    281         if (template_parameter_list &&
    282             !SetupTemplateParamNames(functionp->mutable_template_info(),
    283                                      template_parameter_list)) {
    284           return false;
    285         }
    286       }
    287       break;
    288     }
    289     case clang::FunctionDecl::TK_FunctionTemplateSpecialization: {
    290       const clang::TemplateArgumentList *arg_list =
    291           function_decl_->getTemplateSpecializationArgs();
    292       if (arg_list &&
    293           !SetupTemplateArguments(functionp->mutable_template_info(),
    294                                   arg_list)) {
    295         return false;
    296       }
    297       break;
    298     }
    299     default: {
    300       break;
    301     }
    302   }
    303   return true;
    304 }
    305 
    306 std::unique_ptr<abi_dump::FunctionDecl>
    307 FunctionDeclWrapper::GetFunctionDecl() const {
    308   std::unique_ptr<abi_dump::FunctionDecl> abi_decl(
    309       new abi_dump::FunctionDecl());
    310   std::string source_file = GetDeclSourceFile(function_decl_, cip_);
    311   if (!SetupFunction(abi_decl.get(), source_file)) {
    312     return nullptr;
    313   }
    314   return abi_decl;
    315 }
    316 
    317 RecordDeclWrapper::RecordDeclWrapper(
    318     clang::MangleContext *mangle_contextp,
    319     clang::ASTContext *ast_contextp,
    320     const clang::CompilerInstance *compiler_instance_p,
    321     const clang::RecordDecl *decl)
    322   : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
    323     record_decl_(decl) { }
    324 
    325 bool RecordDeclWrapper::SetupRecordFields(abi_dump::RecordDecl *recordp) const {
    326   clang::RecordDecl::field_iterator field = record_decl_->field_begin();
    327   while (field != record_decl_->field_end()) {
    328     abi_dump::RecordFieldDecl *record_fieldp = recordp->add_fields();
    329     if (!record_fieldp) {
    330       llvm::errs() << " Couldn't add record field: " << field->getName()
    331                    << " to reference dump\n";
    332       return false;
    333     }
    334     if (!SetupBasicNamedAndTypedDecl(record_fieldp->mutable_basic_abi(),
    335                                      field->getType(), field->getName(),
    336                                      field->getAccess(), "", true)) {
    337       return false;
    338     }
    339     field++;
    340   }
    341   return true;
    342 }
    343 
    344 bool RecordDeclWrapper::SetupCXXBases(
    345     abi_dump::RecordDecl *cxxp,
    346     const clang::CXXRecordDecl *cxx_record_decl) const {
    347   assert(cxx_record_decl != nullptr);
    348   clang::CXXRecordDecl::base_class_const_iterator base_class =
    349       cxx_record_decl->bases_begin();
    350   while (base_class != cxx_record_decl->bases_end()) {
    351     abi_dump::CXXBaseSpecifier *base_specifierp = cxxp->add_base_specifiers();
    352     if (!base_specifierp) {
    353       llvm::errs() << " Couldn't add base specifier to reference dump\n";
    354       return false;
    355     }
    356     std::string name = QualTypeToString(base_class->getType());
    357     bool is_virtual = base_class->isVirtual();
    358     if (!SetupBasicNamedAndTypedDecl(base_specifierp->mutable_basic_abi(),
    359                                      base_class->getType(),
    360                                      "", base_class->getAccessSpecifier(),
    361                                      "", false)) {
    362       return false;
    363     }
    364     base_specifierp->set_is_virtual(is_virtual);
    365     base_class++;
    366   }
    367   return true;
    368 }
    369 
    370 bool RecordDeclWrapper::SetupRecordVTable(
    371     abi_dump::RecordDecl *record_declp,
    372     const clang::CXXRecordDecl *cxx_record_decl) const {
    373   assert(cxx_record_decl != nullptr);
    374   clang::VTableContextBase *base_vtable_contextp =
    375       ast_contextp_->getVTableContext();
    376   const clang::Type *typep = cxx_record_decl->getTypeForDecl();
    377   if (!base_vtable_contextp || !typep) {
    378     return false;
    379   }
    380   // Skip Microsoft ABI.
    381   clang::ItaniumVTableContext *itanium_vtable_contextp =
    382         llvm::dyn_cast<clang::ItaniumVTableContext>(base_vtable_contextp);
    383   if (!itanium_vtable_contextp || !cxx_record_decl->isPolymorphic() ||
    384       typep->isDependentType() || typep->isIncompleteType()) {
    385     return true;
    386   }
    387   const clang::VTableLayout &vtable_layout =
    388       itanium_vtable_contextp->getVTableLayout(cxx_record_decl);
    389   abi_dump::VTableLayout *vtablep = record_declp->mutable_vtable_layout();
    390   if (!vtablep) {
    391     return false;
    392   }
    393   for (const auto &vtable_component : vtable_layout.vtable_components()) {
    394     abi_dump::VTableComponent *added_vtable_component =
    395         vtablep->add_vtable_components();
    396     if (!added_vtable_component ||
    397         !SetupRecordVTableComponent(added_vtable_component, vtable_component)) {
    398       return false;
    399     }
    400   }
    401   return true;
    402 }
    403 
    404 bool RecordDeclWrapper::SetupRecordVTableComponent(
    405     abi_dump::VTableComponent *added_vtable_component,
    406     const clang::VTableComponent &vtable_component) const {
    407   assert(added_vtable_component != nullptr);
    408   abi_dump::VTableComponent_Kind kind = abi_dump::VTableComponent_Kind_RTTI;
    409   std::string mangled_component_name = "";
    410   llvm::raw_string_ostream ostream(mangled_component_name);
    411   int64_t value = 0;
    412   clang::VTableComponent::Kind clang_component_kind =
    413       vtable_component.getKind();
    414     switch (clang_component_kind) {
    415       case clang::VTableComponent::CK_VCallOffset:
    416         kind =  abi_dump::VTableComponent_Kind_VCallOffset;
    417         value = vtable_component.getVCallOffset().getQuantity();
    418         break;
    419       case clang::VTableComponent::CK_VBaseOffset:
    420         kind =  abi_dump::VTableComponent_Kind_VBaseOffset;
    421         value = vtable_component.getVBaseOffset().getQuantity();
    422         break;
    423       case clang::VTableComponent::CK_OffsetToTop:
    424         kind =  abi_dump::VTableComponent_Kind_OffsetToTop;
    425         value = vtable_component.getOffsetToTop().getQuantity();
    426         break;
    427       case clang::VTableComponent::CK_RTTI:
    428         {
    429           kind =  abi_dump::VTableComponent_Kind_RTTI;
    430           const clang::CXXRecordDecl *rtti_decl =
    431               vtable_component.getRTTIDecl();
    432           assert(rtti_decl != nullptr);
    433           mangled_component_name =
    434               ABIWrapper::GetTypeLinkageName(rtti_decl->getTypeForDecl());
    435         }
    436         break;
    437       case clang::VTableComponent::CK_FunctionPointer:
    438       case clang::VTableComponent::CK_CompleteDtorPointer:
    439       case clang::VTableComponent::CK_DeletingDtorPointer:
    440       case clang::VTableComponent::CK_UnusedFunctionPointer:
    441         {
    442           const clang::CXXMethodDecl *method_decl =
    443               vtable_component.getFunctionDecl();
    444           assert(method_decl != nullptr);
    445           switch (clang_component_kind) {
    446             case clang::VTableComponent::CK_FunctionPointer:
    447               kind =  abi_dump::VTableComponent_Kind_FunctionPointer;
    448               mangled_component_name = GetMangledNameDecl(method_decl,
    449                                                           mangle_contextp_);
    450               break;
    451             case clang::VTableComponent::CK_CompleteDtorPointer:
    452               kind =  abi_dump::VTableComponent_Kind_CompleteDtorPointer;
    453               mangle_contextp_->mangleCXXDtor(
    454                   vtable_component.getDestructorDecl(),
    455                   clang::CXXDtorType::Dtor_Complete, ostream);
    456               ostream.flush();
    457 
    458               break;
    459             case clang::VTableComponent::CK_DeletingDtorPointer:
    460               kind =  abi_dump::VTableComponent_Kind_DeletingDtorPointer;
    461               mangle_contextp_->mangleCXXDtor(
    462                   vtable_component.getDestructorDecl(),
    463                   clang::CXXDtorType::Dtor_Deleting, ostream);
    464               ostream.flush();
    465               break;
    466             case clang::VTableComponent::CK_UnusedFunctionPointer:
    467               kind =  abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
    468             default:
    469               break;
    470           }
    471         }
    472         break;
    473       default:
    474         return false;
    475     }
    476   added_vtable_component->set_kind(kind);
    477   added_vtable_component->set_component_value(value);
    478   added_vtable_component->set_mangled_component_name(mangled_component_name);
    479   return true;
    480 }
    481 
    482 bool RecordDeclWrapper::SetupTemplateInfo(
    483     abi_dump::RecordDecl *record_declp,
    484     const clang::CXXRecordDecl *cxx_record_decl) const {
    485   assert(cxx_record_decl != nullptr);
    486   if (cxx_record_decl->isTemplateDecl()) {
    487     clang::ClassTemplateDecl *template_decl =
    488         cxx_record_decl->getDescribedClassTemplate();
    489     if (template_decl) {
    490       clang::TemplateParameterList *template_parameter_list =
    491           template_decl->getTemplateParameters();
    492       if (template_parameter_list &&
    493           !SetupTemplateParamNames(record_declp->mutable_template_info(),
    494                                    template_parameter_list)) {
    495         return false;
    496       }
    497     }
    498   } else {
    499     const clang::ClassTemplateSpecializationDecl *specialization_decl =
    500         clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(
    501             cxx_record_decl);
    502     if(specialization_decl) {
    503       const clang::TemplateArgumentList *arg_list =
    504           &specialization_decl->getTemplateArgs();
    505       if (arg_list &&
    506           !SetupTemplateArguments(record_declp->mutable_template_info(),
    507                                   arg_list)) {
    508         return false;
    509       }
    510     }
    511   }
    512   return true;
    513 }
    514 
    515 bool RecordDeclWrapper::SetupRecordInfo(abi_dump::RecordDecl *record_declp,
    516                                         const std::string &source_file) const {
    517   std::string qualified_name = GetTagDeclQualifiedName(record_decl_);
    518   const clang::Type *basic_type = nullptr;
    519   if (!(basic_type = record_decl_->getTypeForDecl())) {
    520     return false;
    521   }
    522   std::string mangled_name = ABIWrapper::GetTypeLinkageName(basic_type);
    523   clang::QualType type = basic_type->getCanonicalTypeInternal();
    524   std::string linker_key = (mangled_name == "") ? qualified_name : mangled_name;
    525   if (!SetupBasicNamedAndTypedDecl(record_declp->mutable_basic_abi(),
    526                                    type, qualified_name,
    527                                    record_decl_->getAccess(), linker_key,
    528                                    true)) {
    529     return false;
    530   }
    531   record_declp->set_mangled_record_name(mangled_name);
    532   record_declp->set_source_file(source_file);
    533   return true;
    534 }
    535 
    536 bool RecordDeclWrapper::SetupCXXRecordInfo(
    537     abi_dump::RecordDecl *record_declp) const {
    538   const clang::CXXRecordDecl *cxx_record_decl =
    539       clang::dyn_cast<clang::CXXRecordDecl>(record_decl_);
    540   if (!cxx_record_decl) {
    541     return true;
    542   }
    543   return SetupTemplateInfo(record_declp, cxx_record_decl) &&
    544       SetupCXXBases(record_declp, cxx_record_decl) &&
    545       SetupRecordVTable(record_declp, cxx_record_decl);
    546 }
    547 
    548 std::unique_ptr<abi_dump::RecordDecl> RecordDeclWrapper::GetRecordDecl() const {
    549   std::unique_ptr<abi_dump::RecordDecl> abi_decl(new abi_dump::RecordDecl());
    550   std::string source_file = GetDeclSourceFile(record_decl_, cip_);
    551   abi_dump::RecordDecl *record_declp = abi_decl.get();
    552   if (!SetupRecordInfo(record_declp, source_file) ||
    553       !SetupRecordFields(record_declp) ||
    554       !SetupCXXRecordInfo(abi_decl.get())) {
    555     llvm::errs() << "Setting up CXX Bases / Template Info failed\n";
    556     return nullptr;
    557   }
    558   return abi_decl;
    559 }
    560 
    561 EnumDeclWrapper::EnumDeclWrapper(
    562     clang::MangleContext *mangle_contextp,
    563     clang::ASTContext *ast_contextp,
    564     const clang::CompilerInstance *compiler_instance_p,
    565     const clang::EnumDecl *decl)
    566   : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
    567     enum_decl_(decl) { }
    568 
    569 bool EnumDeclWrapper::SetupEnumFields(abi_dump::EnumDecl *enump) const {
    570   clang::EnumDecl::enumerator_iterator enum_it = enum_decl_->enumerator_begin();
    571   while (enum_it != enum_decl_->enumerator_end()) {
    572     abi_dump::EnumFieldDecl *enum_fieldp = enump->add_enum_fields();
    573     std::string name = enum_it->getQualifiedNameAsString();
    574     uint64_t field_value = enum_it->getInitVal().getExtValue();
    575     if (!enum_fieldp ||
    576         !SetupBasicNamedAndTypedDecl(enum_fieldp->mutable_basic_abi(),
    577                                      enum_it->getType(), name,
    578                                      enum_it->getAccess(),
    579                                      std::to_string(field_value), true)) {
    580       return false;
    581     }
    582     enum_fieldp->set_enum_field_value(field_value);
    583     enum_it++;
    584   }
    585   return true;
    586 }
    587 
    588 bool EnumDeclWrapper::SetupEnum(abi_dump::EnumDecl *enump,
    589                                 const std::string &source_file) const {
    590   std::string enum_name = GetTagDeclQualifiedName(enum_decl_);
    591   clang::QualType enum_type = enum_decl_->getIntegerType();
    592   if (!SetupBasicNamedAndTypedDecl(enump->mutable_basic_abi(), enum_type,
    593                                    enum_name, enum_decl_->getAccess(),
    594                                    enum_name, true) ||
    595       !SetupEnumFields(enump)) {
    596     return false;
    597   }
    598   enump->set_source_file(source_file);
    599   return true;
    600 }
    601 
    602 std::unique_ptr<abi_dump::EnumDecl> EnumDeclWrapper::GetEnumDecl() const {
    603   std::unique_ptr<abi_dump::EnumDecl> abi_decl(new abi_dump::EnumDecl());
    604   std::string source_file = GetDeclSourceFile(enum_decl_, cip_);
    605 
    606   if (!SetupEnum(abi_decl.get(), source_file)) {
    607     llvm::errs() << "Setting up Enum fields failed\n";
    608     return nullptr;
    609   }
    610   return abi_decl;
    611 }
    612 
    613 GlobalVarDeclWrapper::GlobalVarDeclWrapper(
    614     clang::MangleContext *mangle_contextp,
    615     clang::ASTContext *ast_contextp,
    616     const clang::CompilerInstance *compiler_instance_p,
    617     const clang::VarDecl *decl)
    618   : ABIWrapper(mangle_contextp, ast_contextp, compiler_instance_p),
    619     global_var_decl_(decl) { }
    620 
    621 bool GlobalVarDeclWrapper::SetupGlobalVar(
    622     abi_dump::GlobalVarDecl *global_varp,
    623     const std::string &source_file) const {
    624   // Temporary fix : clang segfaults on trying to mangle global variable which
    625   // is a dependent sized array type.
    626   std::string qualified_name = global_var_decl_->getQualifiedNameAsString();
    627   std::string mangled_name =
    628       GetMangledNameDecl(global_var_decl_, mangle_contextp_);
    629   if (!SetupBasicNamedAndTypedDecl(
    630       global_varp->mutable_basic_abi(),global_var_decl_->getType(),
    631       qualified_name, global_var_decl_->getAccess(),
    632       mangled_name, true)) {
    633     return false;
    634   }
    635   global_varp->set_source_file(source_file);
    636   return true;
    637 }
    638 
    639 std::unique_ptr<abi_dump::GlobalVarDecl>
    640 GlobalVarDeclWrapper::GetGlobalVarDecl() const {
    641   std::unique_ptr<abi_dump::GlobalVarDecl>
    642       abi_decl(new abi_dump::GlobalVarDecl);
    643   std::string source_file = GetDeclSourceFile(global_var_decl_, cip_);
    644   if (!SetupGlobalVar(abi_decl.get(), source_file)) {
    645     return nullptr;
    646   }
    647   return abi_decl;
    648 }
    649