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 
ABIWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * cip)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 
GetDeclSourceFile(const clang::Decl * decl,const clang::CompilerInstance * cip)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 
AccessClangToDump(const clang::AccessSpecifier sp) const55 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 
SetupBasicTypeAbi(abi_dump::BasicTypeAbi * type_abi,const clang::QualType type) const73 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 
SetupBasicNamedAndTypedDecl(abi_dump::BasicNamedAndTypedDecl * basic_named_and_typed_decl,const clang::QualType type,const std::string & name,const clang::AccessSpecifier & access,std::string key) const97 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 
GetMangledNameDecl(const clang::NamedDecl * decl) const114 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 
SetupTemplateParamNames(abi_dump::TemplateInfo * tinfo,clang::TemplateParameterList * pl) const127 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 
GetTagDeclQualifiedName(const clang::TagDecl * decl) const155 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 
SetupTemplateArguments(abi_dump::TemplateInfo * tinfo,const clang::TemplateArgumentList * tl) const163 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 
QualTypeToString(const clang::QualType & sweet_qt) const189 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 
FunctionDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::FunctionDecl * decl)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 
SetupFunctionParameters(abi_dump::FunctionDecl * functionp) const208 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 
SetupFunction(abi_dump::FunctionDecl * functionp,const std::string & source_file) const232 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 
SetupTemplateInfo(abi_dump::FunctionDecl * functionp) const248 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>
GetFunctionDecl() const283 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 
RecordDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::RecordDecl * decl)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 
SetupRecordFields(abi_dump::RecordDecl * recordp) const301 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 
SetupCXXBases(abi_dump::RecordDecl * cxxp,const clang::CXXRecordDecl * cxx_record_decl) const320 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 
SetupRecordVTable(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const346 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 
SetupRecordVTableComponent(abi_dump::VTableComponent * added_vtable_component,const clang::VTableComponent & vtable_component) const380 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 
SetupTemplateInfo(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const445 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 
SetupRecordInfo(abi_dump::RecordDecl * record_declp,const std::string & source_file) const478 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 
SetupCXXRecordInfo(abi_dump::RecordDecl * record_declp) const498 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 
GetRecordDecl() const510 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 
EnumDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::EnumDecl * decl)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 
SetupEnumFields(abi_dump::EnumDecl * enump) const531 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 
SetupEnum(abi_dump::EnumDecl * enump,const std::string & source_file) const550 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 
GetEnumDecl() const565 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 
GlobalVarDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::VarDecl * decl)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 
SetupGlobalVar(abi_dump::GlobalVarDecl * global_varp,const std::string & source_file) const584 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>
GetGlobalVarDecl() const604 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