#include #include #include #include "ConstructValues.hh" //==================================================================================== bool ConstructValues::ContainerClass::extractTemplateArgType(const clang::TemplateArgument& ta) { clang::QualType qt = ta.getAsType() ; const clang::Type * t = qt.getTypePtrOrNull() ; if ( t != NULL ) { ContainerClass inner_cc ; if (t->getTypeClass() == clang::Type::Record and t->getAsCXXRecordDecl()) { clang::CXXRecordDecl * crd = t->getAsCXXRecordDecl() ; if ( clang::isa(crd) ) { // template argument is a template specialization if (!inner_cc.extractType(clang::cast(crd))) { return false ; } } else { // template argument record type, but not a template specialization inner_cc.name = qt.getAsString() ; } } else { // template argument not a record type. inner_cc.name = qt.getAsString() ; } template_args.push_back(inner_cc) ; } return true ; } bool ConstructValues::ContainerClass::extractType(const clang::RecordDecl * rd) { if (! rd->getIdentifier()) { return false ; } // Set the name of this type. name = rd->getName().str() ; // If this type is a template specialization we need to save the template argument types. if (const clang::ClassTemplateSpecializationDecl *ctsd = clang::dyn_cast(rd)) { for (const clang::TemplateArgument& ta : ctsd->getTemplateArgs().asArray()) { if ( ta.getKind() == clang::TemplateArgument::Type ) { // Class types and intrinsic types if ( !extractTemplateArgType(ta) ) { return false ; } } else if ( ta.getKind() == clang::TemplateArgument::Pack ) { // a Pack is the variables in a variadric template for (const clang::TemplateArgument& pack_ta : ta.getPackAsArray()) { if ( pack_ta.getKind() == clang::TemplateArgument::Type ) { if ( !extractTemplateArgType(pack_ta) ) { return false ; } } } } else { // This template argument is not a clang::TemplateArgument::Type. We don't currently handle these. return false ; } } } // if we reach the end then we can deal with the class name, return true. return true ; } static void mangle_template_param(std::string &work_string, const std::string & delimiter) { if ( !delimiter.compare("__") ) { std::replace( work_string.begin(), work_string.end(), '*', '_') ; std::replace( work_string.begin(), work_string.end(), '[', '_') ; std::replace( work_string.begin(), work_string.end(), ']', '_') ; std::replace( work_string.begin(), work_string.end(), ':', '_') ; work_string.erase(std::remove_if(work_string.begin(), work_string.end(), (int(*)(int))std::isspace), work_string.end()) ; } } void ConstructValues::ContainerClass::printTemplateList(std::ostream& ostream, const std::string& delimiter) { if ( template_args.size() ) { std::string obracket("<"), comma(","), cbracket(">"), work_string ; if ( !delimiter.compare("__") ) { obracket = comma = cbracket = "_" ; } ostream << obracket ; unsigned int arg_size = template_args.size() - 1 ; for (unsigned int ii = 0 ; ii < arg_size ; ii++ ) { work_string = template_args[ii].name ; mangle_template_param(work_string, delimiter) ; ostream << work_string ; template_args[ii].printTemplateList(ostream, delimiter); ostream << comma ; } work_string = template_args[arg_size].name ; mangle_template_param(work_string, delimiter) ; ostream << work_string ; template_args[arg_size].printTemplateList(ostream, delimiter); ostream << cbracket ; } } void ConstructValues::ContainerClass::printContainerClass(std::ostream& ostream, const std::string& delimiter) { ostream << name ; printTemplateList(ostream, delimiter) ; ostream << delimiter ; } //==================================================================================== ConstructValues::ConstructValues() {} void ConstructValues::setName(std::string in_name) { name = in_name ; } std::string ConstructValues::getName() { return name ; } void ConstructValues::setFileName(std::string in_name) { file_name = in_name ; } std::string ConstructValues::getFileName() { return file_name ; } void ConstructValues::clearNamespacesAndClasses() { namespaces.clear() ; container_classes.clear() ; } bool ConstructValues::getNamespacesAndClasses( const clang::DeclContext * Ctx ) { // Save container namespaces and classes. typedef clang::SmallVector ContextsTy; ContextsTy Contexts; // Collect contexts. while (Ctx && clang::isa(Ctx)) { Contexts.push_back(Ctx); Ctx = Ctx->getParent(); }; for (ContextsTy::reverse_iterator I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) { if (const clang::NamespaceDecl *nd = clang::dyn_cast(*I)) { if (! nd->isAnonymousNamespace()) { //std::cout << "namespace " << nd->getIdentifier()->getName().str() << std::endl ; std::string temp_name = nd->getIdentifier()->getName().str() ; if ( temp_name.compare("std") and temp_name.compare("__1")) { namespaces.push_back(nd->getIdentifier()->getName().str()) ; } } } else if (const clang::RecordDecl *rd = clang::dyn_cast(*I)) { ContainerClass cc ; if (!cc.extractType(rd)) { return false ; } container_classes.push_back(cc) ; } } return true ; } std::string ConstructValues::getFullyQualifiedName(const std::string& delimiter) { std::ostringstream oss; printNamespaces(oss, delimiter); printContainerClasses(oss, delimiter); oss << name; return oss.str(); } bool ConstructValues::isNameOrFileNameEmpty() { return name.empty() or file_name.empty(); } void ConstructValues::printOpenNamespaceBlocks(std::ostream& ostream) { for (auto name : namespaces) { ostream << "namespace " << name << " {" << std::endl; } } void ConstructValues::printCloseNamespaceBlocks(std::ostream& ostream) { for (auto name : namespaces) { ostream << "}" << std::endl; } } void ConstructValues::printNamespaces(std::ostream& ostream, const std::string& delimiter) { for (auto name : namespaces) { ostream << name << delimiter; } } void ConstructValues::printContainerClasses(std::ostream& ostream, const std::string& delimiter) { for (auto c : container_classes) { c.printContainerClass(ostream, delimiter); } } void ConstructValues::printNamespacesAndContainerClasses(std::ostream& ostream, const std::string& delimiter) { printNamespaces(ostream, delimiter); printContainerClasses(ostream, delimiter); } std::string ConstructValues::getNamespacesAndContainerClasses(const std::string& delimiter) { std::string result = ""; for (auto name : namespaces) { result += name + delimiter; } for (auto c : container_classes) { std::stringstream ss ; c.printContainerClass(ss, delimiter); result += ss.str() ; } return result; } std::string ConstructValues::getFullyQualifiedTypeName(const std::string& delimiter) { std::ostringstream oss ; printNamespacesAndContainerClasses(oss, delimiter) ; oss << name ; return oss.str() ; }