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