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