mirror of
https://github.com/nasa/trick.git
synced 2024-12-21 22:17:51 +00:00
d875f837f2
When saving the list of namespaces and classes a particular type is contained in we have to save the class name and any template args it includes separately. This allows us to mangle the names easier. And we now search for type names to see if they follow this pattern template_name<template_args>::embedded_class. If we are using a template embedded class we need to create attributes for the embedded class.
217 lines
7.8 KiB
C++
217 lines
7.8 KiB
C++
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <clang/AST/DeclTemplate.h>
|
|
|
|
#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<clang::ClassTemplateSpecializationDecl>(crd) ) {
|
|
// template argument is a template specialization
|
|
if (!inner_cc.extractType(clang::cast<clang::ClassTemplateSpecializationDecl>(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<clang::ClassTemplateSpecializationDecl>(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(), ']', '_') ;
|
|
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<const clang::DeclContext *, 8> ContextsTy;
|
|
ContextsTy Contexts;
|
|
// Collect contexts.
|
|
while (Ctx && clang::isa<clang::NamedDecl>(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<clang::NamespaceDecl>(*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<clang::RecordDecl>(*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();
|
|
}
|
|
|
|
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() ;
|
|
}
|