• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ABIWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * cip)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 
GetDeclSourceFile(const clang::Decl * decl,const clang::CompilerInstance * cip)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 
AccessClangToDump(const clang::AccessSpecifier sp) const56 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
SetupBasicTypeAbi(abi_dump::BasicTypeAbi * type_abi,const clang::QualType type,bool dump_size) const77 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 
SetupBasicNamedAndTypedDecl(abi_dump::BasicNamedAndTypedDecl * basic_named_and_typed_decl,const clang::QualType type,const std::string & name,const clang::AccessSpecifier & access,std::string key,bool dump_size) const102 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 
ShouldDumpSize(clang::QualType qt)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 
GetTypeLinkageName(const clang::Type * typep) const129 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 
GetMangledNameDecl(const clang::NamedDecl * decl,clang::MangleContext * mangle_contextp)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 
SetupTemplateParamNames(abi_dump::TemplateInfo * tinfo,clang::TemplateParameterList * pl) const148 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 
GetTagDeclQualifiedName(const clang::TagDecl * decl) const176 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 
SetupTemplateArguments(abi_dump::TemplateInfo * tinfo,const clang::TemplateArgumentList * tl) const184 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 
QualTypeToString(const clang::QualType & sweet_qt) const211 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 
FunctionDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::FunctionDecl * decl)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 
SetupFunctionParameters(abi_dump::FunctionDecl * functionp) const230 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 
SetupFunction(abi_dump::FunctionDecl * functionp,const std::string & source_file) const257 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 
SetupTemplateInfo(abi_dump::FunctionDecl * functionp) const272 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>
GetFunctionDecl() const307 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 
RecordDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::RecordDecl * decl)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 
SetupRecordFields(abi_dump::RecordDecl * recordp) const325 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 
SetupCXXBases(abi_dump::RecordDecl * cxxp,const clang::CXXRecordDecl * cxx_record_decl) const344 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 
SetupRecordVTable(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const370 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 
SetupRecordVTableComponent(abi_dump::VTableComponent * added_vtable_component,const clang::VTableComponent & vtable_component) const404 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 
SetupTemplateInfo(abi_dump::RecordDecl * record_declp,const clang::CXXRecordDecl * cxx_record_decl) const482 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 
SetupRecordInfo(abi_dump::RecordDecl * record_declp,const std::string & source_file) const515 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 
SetupCXXRecordInfo(abi_dump::RecordDecl * record_declp) const536 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 
GetRecordDecl() const548 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 
EnumDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::EnumDecl * decl)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 
SetupEnumFields(abi_dump::EnumDecl * enump) const569 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 
SetupEnum(abi_dump::EnumDecl * enump,const std::string & source_file) const588 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 
GetEnumDecl() const602 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 
GlobalVarDeclWrapper(clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::VarDecl * decl)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 
SetupGlobalVar(abi_dump::GlobalVarDecl * global_varp,const std::string & source_file) const621 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>
GetGlobalVarDecl() const640 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