Пример #1
0
bool FieldVisitor::ProcessTemplate(std::string in_name , clang::CXXRecordDecl * crd ) {

    // Save container namespaces and classes.
    fdes->getNamespacesAndClasses(crd->getDeclContext()) ;

    size_t pos ;

    // Check to see if we've processed this template before
    // If not we need to create attributes for this template
    if ( processed_templates.find(in_name) == processed_templates.end() ) {
        std::string mangled_name = mangle_string(in_name) ;

        // save off the mangled name of this template to be used if another variable is the same template type
        processed_templates[in_name] = fdes->getContainerClass() + "_" +
         fdes->getName() + "_" + mangled_name ;

        // Traverse the template declaration
        CXXRecordVisitor template_spec_cvis(ci , cs, hsd , pa, false, false, true) ;
        template_spec_cvis.get_class_data()->setMangledTypeName(processed_templates[in_name]) ;
        template_spec_cvis.TraverseCXXRecordDecl(crd) ;

        // Set the actual type name and file name. Print the attributes for this template type
        template_spec_cvis.get_class_data()->setName(in_name) ;
        template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ;
        pa.printClass(template_spec_cvis.get_class_data()) ;

        if ( debug_level >= 4 ) {
            std::cout << "Added template class from FieldVisitor ProcessTemplate " ;
            std::cout << in_name << std::endl ;
            std::cout << *fdes << std::endl ;
        }
    }

    fdes->setMangledTypeName(processed_templates[in_name]) ;
    fdes->setEnumString("TRICK_STRUCTURED") ;
    fdes->setRecord(true) ;

    // processing the template will process the type, return false to stop processing
    return false ;
}
Пример #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() ) {
        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("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() ) {
        const clang::BuiltinType * bt = tt->getAs<clang::BuiltinType>() ;
        VisitBuiltinType((clang::BuiltinType *)bt) ;
    }
    return true;
}
Пример #3
0
/* This code handles handles class fields that define a new template type,
"my_var" in the below example.

template< class A>
class T {
    A a ;
} ;

class B {
    T<int> my_var ;
} ;

TODO:  We need to save all of the parts of the template separately.  There is code in
       PrintFilecontents10 that I want to fix, but I would need the template info stored differently.
*/
bool FieldVisitor::VisitTemplateSpecializationType(clang::TemplateSpecializationType *tst) {
    std::string tst_string = tst->desugar().getAsString() ;
    if ( debug_level >= 3 ) {
        std::cout << "FieldVisitor VisitTemplateSpecializationType " << tst_string << std::endl ;
        tst->dump() ; std::cout << std::endl ;
    }

    if ( ! tst_string.compare( 0 , 9 , "class std") or ! tst_string.compare( 0 , 10 , "struct std") ) {
        // This is a standard template library type.  Set the io field to 0.
        fdes->setIO(0) ;
    } else if ( ! tst_string.compare( 0 , 11 , "class Trick") or ! tst_string.compare( 0 , 12 , "struct Trick") ) {
        // This is a Trick standard template library type.  Set the io field to 0.
        fdes->setIO(0) ;
    } else if ( fdes->getIO() != 0 ) {
        // Continue processing only if we haven't set the IO spec to 0.
        // This is a user template type. We'll need the expanded template class definition
        clang::CXXRecordDecl *trec = tst->getAsCXXRecordDecl() ;

        // If we cannot get a definition, ignore this parameter and return with no further processing.
        if ( trec == NULL ) {
            fdes->setIO(0) ;
            return false ;
        }

        clang::TagDecl * td = trec->getDefinition() ;

        if ( td != NULL ) {
            size_t pos ;
            if ( debug_level >= 3 ) {
                std::cout << "FieldVisitor VisitTemplateSpecializationType CXXRecordDecl " << std::endl ;
                td->dump() ; std::cout << std::endl ;
            }
            if ((pos = tst_string.find("class ")) != std::string::npos ) {
                tst_string.erase(pos , 6) ;
            }
            // clang changes bool to _Bool.  We need to change it back
            if ((pos = tst_string.find("<_Bool")) != std::string::npos ) {
                tst_string.replace(pos , 6, "<bool") ;
            }
            while ((pos = tst_string.find(" _Bool")) != std::string::npos ) {
                tst_string.replace(pos , 6, " bool") ;
            }
            // NOTE: clang also changes FILE * to struct _SFILE *.  We may need to change that too.

            // Save container namespaces and classes.
            fdes->getNamespacesAndClasses(td->getDeclContext()) ;

            // Check to see if we've created a class that matches this template
            if ( processed_templates.find(tst_string) == processed_templates.end() ) {
                CXXRecordVisitor template_spec_cvis(ci , cs, hsd , pa, false, false, true) ;
                processed_templates.insert(std::pair< std::string , ClassValues * >(tst_string , template_spec_cvis.get_class_data())) ;

                // Use the current template type name, tst_string, as part of the mangled type name
                // Some characters have to converted to underscores.
                std::string mangled_name = tst_string ;
                std::replace( mangled_name.begin(), mangled_name.end(), '<', '_') ;
                std::replace( mangled_name.begin(), mangled_name.end(), '>', '_') ;
                std::replace( mangled_name.begin(), mangled_name.end(), ' ', '_') ;
                std::replace( mangled_name.begin(), mangled_name.end(), ',', '_') ;
                std::replace( mangled_name.begin(), mangled_name.end(), ':', '_') ;
                std::replace( mangled_name.begin(), mangled_name.end(), '*', '_') ;


                template_spec_cvis.get_class_data()->setMangledTypeName(fdes->getContainerClass() + "_" +
                 fdes->getName() + "_" + mangled_name) ;
                template_spec_cvis.TraverseCXXRecordDecl(clang::cast<clang::CXXRecordDecl>(td)) ;
                fdes->setMangledTypeName(fdes->getContainerClass() + "_" + fdes->getName() + "_" + mangled_name) ;
                template_spec_cvis.get_class_data()->setName(tst_string) ;
                template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ;

                pa.printClass(template_spec_cvis.get_class_data()) ;

                // template_spec_cvis is going to go out of scope.  We need to make a copy of the ClassValues.
                ClassValues * cval = new ClassValues(*(template_spec_cvis.get_class_data())) ;
                processed_templates[tst_string] = cval ;

                fdes->setEnumString("TRICK_STRUCTURED") ;
                fdes->setRecord(true) ;
                fdes->setHasType(true) ;
                if ( debug_level >= 4 ) {
                    std::cout << "Added template class from FieldVisitor VisitTemplateSpecializationType " ;
                    std::cout << tst_string << std::endl ;
                    std::cout << *fdes << std::endl ;
                }
            } else {
                ClassValues * cval = processed_templates[tst_string] ;
                fdes->setMangledTypeName(cval->getMangledTypeName()) ;
                fdes->setEnumString("TRICK_STRUCTURED") ;
                fdes->setRecord(true) ;
                fdes->setHasType(true) ;
            }
        }
    }
    return true ;
}