bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) { fdes->setBitField(field->isBitField()) ; if ( fdes->isBitField() ) { fdes->setBitFieldWidth(field->getBitWidthValue(field->getASTContext())) ; unsigned int field_offset_bits = field->getASTContext().getFieldOffset(field) + fdes->getBaseClassOffset() * 8 ; fdes->setBitFieldStart( 32 - (field_offset_bits % 32) - fdes->getBitFieldWidth()) ; fdes->setBitFieldByteOffset((field_offset_bits / 32) * 4 ) ; } // If the current type is not canonical because of typedefs or template parameter substitution, // traverse the canonical type clang::QualType qt = field->getType() ; if ( debug_level >= 3 ) { std::cout << "FieldVisitor VisitFieldDecl" << std::endl ; std::cout << " is_bitfield = " << fdes->isBitField() << std::endl ; std::cout << " is_canonical = " << qt.isCanonical() << std::endl ; //field->dump() ; } if ( !qt.isCanonical() ) { fdes->setNonCanonicalTypeName(qt.getAsString()) ; clang::QualType ct = qt.getCanonicalType() ; std::string tst_string = ct.getAsString() ; if ( debug_level >= 3 ) { std::cout << "\033[33mFieldVisitor VisitFieldDecl: Processing canonical type\033[00m" << std::endl ; ct.dump() ; } TraverseType(ct) ; // We have extracted the canonical type and everything else we need // return false so we cut off processing of this AST branch return false ; } return true ; }
bool FieldVisitor::VisitTypedefType(clang::TypedefType *tt) { size_t pos ; if ( debug_level >= 3 ) { std::cout << "FieldVisitor VisitTypedefType " << fdes->getName() << std::endl ; tt->dump() ; std::cout << std::endl ; } // return if we have set a typename if ( fdes->hasType() ) { return true ; } if ( tt->isEnumeralType() ) { if ( debug_level >= 4 ) { std::cout << " FieldVisitor VisitTypedefType enumerated" << std::endl ; } fdes->setEnumString("TRICK_ENUMERATED") ; fdes->setEnum(true) ; std::string enum_type_name = tt->desugar().getAsString() ; if ((pos = enum_type_name.find("enum ")) != std::string::npos ) { enum_type_name.erase(pos , 5) ; } //std::cout << "enum name " << enum_type_name << std::endl ; fdes->setTypeName(enum_type_name) ; // Save container namespaces and classes. const clang::TypedefNameDecl * tnd = tt->getDecl() ; fdes->getNamespacesAndClasses(tnd->getDeclContext()) ; fdes->setHasType(true) ; } else if ( tt->isRecordType() ) { std::string type_name = tt->desugar().getAsString() ; if ((pos = type_name.find("class ")) != std::string::npos ) { type_name.erase(pos , 6) ; } if ((pos = type_name.find("struct ")) != std::string::npos ) { type_name.erase(pos , 7) ; } if ((pos = type_name.find("union ")) != std::string::npos ) { type_name.erase(pos , 6) ; } // Typedefs of STL containers are ignored. if ((pos = type_name.find("std::")) != std::string::npos ) { fdes->setIO(0) ; return true ; } else if (ignore_types.types.find(type_name) != ignore_types.types.end() ) { // Ignore other system types that do not start with std:: fdes->setIO(0) ; return true ; } if ( ! type_name.compare(0, 17, "basic_string<char") ) { fdes->setEnumString("TRICK_STRING") ; type_name = "std::string"; } else if ( ! type_name.compare("_IO_FILE") ) { fdes->setEnumString("TRICK_FILE_PTR") ; } else if ( ! type_name.compare("__sFILE") ) { fdes->setEnumString("TRICK_FILE_PTR") ; } else { fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setRecord(true) ; const clang::TypedefNameDecl * tnd = tt->getDecl() ; fdes->getNamespacesAndClasses(tnd->getDeclContext()) ; // If this typedef resolves to a class/template in std namespace, don't process it. if ( fdes->namespace_begin() != fdes->namespace_end() ) { std::string first_ns = *(fdes->namespace_begin()) ; if ( ! first_ns.compare("std") ) { fdes->setIO(0) ; return true ; } } // test to see if the typedef name is a template type we have processed. std::map < std::string , ClassValues * >::iterator mit ; mit = processed_templates.find(type_name) ; if ( mit != processed_templates.end() ) { if ( debug_level >= 4 ) { std::cout << "templated type has been processed before " << (*mit).second->getMangledTypeName() << std::endl ; } type_name = (*mit).second->getMangledTypeName() ; } else { // TODO: Is there a better way to determine if this is a template or not? Right now we're // checking if the typename has a "<" character. if ( type_name.find("<") != std::string::npos ) { clang::CXXRecordDecl *trec = tt->getAsCXXRecordDecl() ; unsigned int before_enum_size ; if ( debug_level >= 4 ) { std::cout << "templated type unprocessed! " << type_name << std::endl ; trec->dump() ; std::cout << std::endl ; } CXXRecordVisitor template_spec_cvis(ci , cs, hsd , pa, false, false, true) ; template_spec_cvis.get_class_data()->setMangledTypeName(fdes->getName() + "_" + clang::cast<clang::CXXRecordDecl>(trec)->getNameAsString()) ; template_spec_cvis.TraverseCXXRecordDecl(trec) ; fdes->setMangledTypeName(fdes->getName() + "_" + template_spec_cvis.get_class_data()->getName()) ; template_spec_cvis.get_class_data()->setName(type_name) ; template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ; ClassValues * cval = new ClassValues(*(template_spec_cvis.get_class_data())) ; processed_templates.insert(std::pair< std::string , ClassValues * >(type_name , cval)) ; pa.printClass(template_spec_cvis.get_class_data()) ; fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setRecord(true) ; fdes->setHasType(true) ; if ( debug_level >= 4 ) { std::cout << "Added template class from typedeffed field " << type_name << std::endl ; std::cout << " fdes->getMangledTypeName " << fdes->getMangledTypeName() << std::endl ; std::cout << *cval << std::endl ; } } } } fdes->setTypeName(type_name) ; fdes->setHasType(true) ; } else if ( tt->isBuiltinType() ) { if ( debug_level >= 4 ) { std::cout << " FieldVisitor VisitTypedefType builtintype" << std::endl ; } const clang::BuiltinType * bt = tt->getAs<clang::BuiltinType>() ; VisitBuiltinType((clang::BuiltinType *)bt) ; } else if ( tt->isArrayType() || tt->isPointerType()) { clang::QualType qt = tt->desugar() ; if ( debug_level >= 4 ) { std::cout << "Typedef to constant array type" << std::endl ; qt->dump() ; } // Calling visit type recursively with the typedeffed type TraverseType(qt) ; if ( debug_level >= 4 ) { std::cout << "After TraverseType" << std::endl ; std::cout << *fdes << std::endl ; } } else { if ( debug_level >= 4 ) { std::cout << "Typedef to something we don't handle yet" << std::endl ; } } return true; }