예제 #1
0
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 ;
}
예제 #2
0
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;
}