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