This commit is contained in:
John M. Penn 2016-11-02 14:22:08 -05:00
commit 1f75034da2
9 changed files with 200 additions and 126 deletions

View File

@ -280,14 +280,10 @@ std::ostream & operator << (std::ostream & ostream, ClassValues & cv) {
ostream << " mangled_name = " << cv.mangled_type_name << std::endl ;
ostream << " file_name = " << cv.file_name << std::endl ;
ostream << " namespaces =" ;
for (auto& name : cv.getNamespaces()) {
ostream << " " << name ;
}
cv.printNamespaces(ostream) ;
ostream << std::endl ;
ostream << " parent classes =" ;
for (auto& clazz : cv.getContainerClasses()) {
ostream << " " << clazz ;
}
cv.printContainerClasses(ostream) ;
ostream << std::endl ;
ostream << " has_init_attr_friend = " << cv.has_init_attr_friend << std::endl ;
ostream << " is_pod = " << cv.is_pod << std::endl ;

View File

@ -161,6 +161,11 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
cval.setCompat15(hsd.isPathInCompat15(rp)) ;
free(rp) ;
// If we have trouble determining the containing namespace and classes skip this variable.
if ( !cval.getNamespacesAndClasses(rec->getDeclContext())) {
return false ;
}
// If this class needs a default constructor, then the complier will generate one and we can call it.
if ( rec->needsImplicitDefaultConstructor() ) {
cval.setHasDefaultConstructor(true) ;
@ -187,10 +192,10 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
cval.setSize(rec->getASTContext().getASTRecordLayout(rec).getSize().getQuantity()) ;
clang::CXXRecordDecl::base_class_iterator bcii ;
//std::cout << "parsing " << cval.getName() << std::endl ;
//std::cout << " processing inheritance " << rec->getNumBases() << " " << rec->getNumVBases() << "" << std::endl ;
clang::CXXRecordDecl::base_class_iterator bcii ;
for ( bcii = rec->bases_begin() ; bcii != rec->bases_end() ; bcii++ ) {
if ( !bcii->isVirtual() ) {
const clang::Type * temp = bcii->getType().getTypePtr() ;
@ -279,8 +284,6 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
}
}
cval.getNamespacesAndClasses(rec->getDeclContext()) ;
// clears obscured inherited variables caused by diamond inheritance
cval.clearAmbiguousVariables() ;

View File

@ -5,6 +5,107 @@
#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) {
@ -28,7 +129,7 @@ void ConstructValues::clearNamespacesAndClasses() {
container_classes.clear() ;
}
void ConstructValues::getNamespacesAndClasses( const clang::DeclContext * Ctx ) {
bool ConstructValues::getNamespacesAndClasses( const clang::DeclContext * Ctx ) {
// Save container namespaces and classes.
typedef clang::SmallVector<const clang::DeclContext *, 8> ContextsTy;
ContextsTy Contexts;
@ -43,40 +144,18 @@ void ConstructValues::getNamespacesAndClasses( const clang::DeclContext * Ctx )
//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")) {
addNamespace(nd->getIdentifier()->getName().str()) ;
namespaces.push_back(nd->getIdentifier()->getName().str()) ;
}
}
} else if (const clang::RecordDecl *rd = clang::dyn_cast<clang::RecordDecl>(*I)) {
if (rd->getIdentifier()) {
//std::cout << "in class " << rd->getName().str() << std::endl ;
if (const clang::ClassTemplateSpecializationDecl *td = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(*I)) {
std::string text;
llvm::raw_string_ostream stream(text);
stream << td->getName().str() << "<";
const clang::TemplateArgumentList& arguments = td->getTemplateArgs();
unsigned end = arguments.size() - 1;
for (unsigned i = 0; i < end; ++i) {
arguments[i].print(printingPolicy, stream);
stream << ", ";
}
arguments[end].print(printingPolicy, stream);
stream << ">";
addContainerClass(stream.str());
}
else {
addContainerClass(rd->getName().str()) ;
}
ContainerClass cc ;
if (!cc.extractType(rd)) {
return false ;
}
container_classes.push_back(cc) ;
}
}
}
void ConstructValues::addNamespace( std::string in_name ) {
namespaces.push_back(in_name) ;
}
void ConstructValues::addContainerClass( std::string in_name ) {
container_classes.push_back(in_name) ;
return true ;
}
std::string ConstructValues::getFullyQualifiedName(const std::string& delimiter) {
@ -106,8 +185,8 @@ void ConstructValues::printNamespaces(std::ostream& ostream, const std::string&
}
void ConstructValues::printContainerClasses(std::ostream& ostream, const std::string& delimiter) {
for (auto clazz : container_classes) {
ostream << clazz << delimiter;
for (auto c : container_classes) {
c.printContainerClass(ostream, delimiter);
}
}
@ -121,8 +200,10 @@ std::string ConstructValues::getNamespacesAndContainerClasses(const std::string&
for (auto name : namespaces) {
result += name + delimiter;
}
for (auto clazz : container_classes) {
result += clazz + delimiter;
for (auto c : container_classes) {
std::stringstream ss ;
c.printContainerClass(ss, delimiter);
result += ss.str() ;
}
return result;
}

View File

@ -21,10 +21,25 @@
@date July 2012
*/
class ConstructValues {
public:
/*
A ContainerClass may be a regular class (zero template_args) or a templated class
The same routines are used to extract the names of the classes from the clang::RecordDecl
data and the to print the class name with or without template arguments.
*/
class ContainerClass {
public:
bool extractType(const clang::RecordDecl * rd) ;
void printTemplateList(std::ostream& ostream, const std::string & delimiter) ;
void printContainerClass(std::ostream& ostream, const std::string & delimiter) ;
private:
bool extractTemplateArgType(const clang::TemplateArgument& ta) ;
std::string name ;
std::vector<ContainerClass> template_args ;
} ;
ConstructValues() ;
void setName(std::string in_name) ;
@ -36,22 +51,15 @@ class ConstructValues {
/** Clears current namespaces and classes */
void clearNamespacesAndClasses() ;
/** Gets all of the container namespaces and classes this construct resides in */
void getNamespacesAndClasses( const clang::DeclContext * Ctx ) ;
void addNamespace(std::string in_name) ;
/** Gets all of the container namespaces and classes this construct resides in
returns true if namespaces and classes were succsssfully retrieved.
*/
bool getNamespacesAndClasses( const clang::DeclContext * Ctx ) ;
const std::vector<std::string>& getNamespaces() {
return namespaces;
}
void addContainerClass(std::string in_name) ;
const std::vector<std::string>& getContainerClasses() {
return container_classes;
}
std::string getFullyQualifiedName(const std::string& delimiter = "::") ;
void printOpenNamespaceBlocks(std::ostream& ostream);
@ -71,7 +79,7 @@ class ConstructValues {
std::vector<std::string> namespaces ;
/** List of container classes this construct is contained within */
std::vector<std::string> container_classes ;
std::vector<ContainerClass> container_classes ;
/** File where construct is defined */
std::string file_name ;

View File

@ -22,14 +22,10 @@ std::ostream & operator << (std::ostream & ostream , EnumValues & ev ) {
ostream << " name = " << ev.name << std::endl ;
ostream << " file_name = " << ev.file_name << std::endl ;
ostream << " namespaces =" ;
for (auto& name : ev.getNamespaces()) {
ostream << " " << name ;
}
ev.printNamespaces(ostream) ;
ostream << std::endl ;
ostream << " parent classes =" ;
for (auto& clazz : ev.getContainerClasses()) {
ostream << " " << clazz ;
}
ev.printContainerClasses(ostream) ;
ostream << std::endl ;
for (auto& pair : ev.getPairs()) {

View File

@ -62,27 +62,7 @@ bool EnumVisitor::VisitEnumType(clang::EnumType *et) {
//std::cout << "\nReplaced Enum name = " << eval->getName() << "" << std::endl ;
}
const clang::DeclContext * Ctx = td->getDeclContext() ;
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 ;
eval.addNamespace(nd->getIdentifier()->getName().str()) ;
}
} else if (const clang::RecordDecl *rd = clang::dyn_cast<clang::RecordDecl>(*I)) {
if (rd->getIdentifier()) {
//std::cout << "in class " << rd->getName().str() << std::endl ;
eval.addContainerClass(rd->getName().str()) ;
}
}
}
eval.getNamespacesAndClasses(td->getDeclContext()) ;
return true ;
}

View File

@ -529,14 +529,10 @@ std::ostream & operator << (std::ostream & ostream , FieldDescription & fieldDes
ostream << " name = " << fieldDescription.name << std::endl ;
ostream << " file_name = " << fieldDescription.file_name << std::endl ;
ostream << " namespaces =" ;
for (auto& name : fieldDescription.getNamespaces()) {
ostream << " " << fieldDescription ;
}
fieldDescription.printNamespaces(ostream) ;
ostream << std::endl ;
ostream << " parent classes =" ;
for (auto& clazz : fieldDescription.getContainerClasses()) {
ostream << " " << clazz ;
}
fieldDescription.printContainerClasses(ostream) ;
ostream << std::endl ;
ostream << " line_no = " << fieldDescription.line_no << std::endl ;
ostream << " container_class = " << fieldDescription.container_class << std::endl ;

View File

@ -262,6 +262,9 @@ static std::string mangle_string( std::string in_name ) {
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(), '[', '_') ;
return mangled_name ;
}
@ -270,7 +273,11 @@ std::map < std::string , std::string > FieldVisitor::processed_templates ;
bool FieldVisitor::ProcessTemplate(std::string in_name , clang::CXXRecordDecl * crd ) {
// Save container namespaces and classes.
fdes->getNamespacesAndClasses(crd->getDeclContext()) ;
// If we have trouble getting the namespaces and classes immediately return.
if ( !fdes->getNamespacesAndClasses(crd->getDeclContext())) {
fdes->setIO(0) ;
return false ;
}
size_t pos ;
@ -481,20 +488,35 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
will be typed as a record. We test if we have a template specialization type.
If so process the template type and return */
clang::RecordDecl * rd = rt->getDecl()->getDefinition() ;
if ( rd != NULL and clang::ClassTemplateSpecializationDecl::classof(rd) ) {
if ( checkForPrivateTemplateArgs( clang::cast<clang::ClassTemplateSpecializationDecl>(rd)) ) {
fdes->setIO(0) ;
if ( debug_level >= 3 ) {
std::cout << " template using private/protected class as argument, not processing" << std::endl ;
if ( rd != NULL ) {
if ( clang::ClassTemplateSpecializationDecl::classof(rd) ) {
if ( checkForPrivateTemplateArgs( clang::cast<clang::ClassTemplateSpecializationDecl>(rd)) ) {
fdes->setIO(0) ;
if ( debug_level >= 3 ) {
std::cout << " template using private/protected class as argument, not processing" << std::endl ;
}
return false ;
}
return false ;
if ( debug_level >= 3 ) {
rd->dump() ;
std::cout << " tst_string = " << tst_string << std::endl ;
std::cout << " is_a_template_specialization" << std::endl ;
}
return ProcessTemplate(tst_string, clang::cast<clang::CXXRecordDecl>(rd)) ;
} else if (tst_string.find(">::") != std::string::npos) {
/* Hacky check to see if we are using an embedded class within a template definition.
template <class T> class A {
public: class B { T t ;} ;
};
class C {
public: A<int>::B ab ; // This is the pattern we are looking for.
} ;
There must be a better way to determine this condition
We need to make attributes for th A<int>::B class.
*/
return ProcessTemplate(tst_string, clang::cast<clang::CXXRecordDecl>(rd)) ;
}
if ( debug_level >= 3 ) {
rd->dump() ;
std::cout << " tst_string = " << tst_string << std::endl ;
std::cout << " is_a_template_specialization" << std::endl ;
}
return ProcessTemplate(tst_string, clang::cast<clang::CXXRecordDecl>(rd)) ;
}
/* Test to see if we have an embedded anonymous struct/union. e.g. SB is anonymous below.
@ -562,7 +584,7 @@ bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) {
clang::QualType ct = qt.getCanonicalType() ;
std::string tst_string = ct.getAsString() ;
if ( debug_level >= 3 ) {
std::cout << "\033[33mFieldVisitor VisitVarDecl: Processing canonical type\033[00m" << std::endl ;
std::cout << "\033[33mFieldVisitor VisitVarDecl: Processing canonical type " << tst_string << "\033[00m" << std::endl ;
ct.dump() ;
}
TraverseType(ct) ;

View File

@ -40,38 +40,30 @@ int Trick::MemoryManager::add_attr_info( const std::string & user_type_string ,
return 0 ;
}
spos = user_type_name.find("<") ;
if ( spos != std::string::npos ) {
std::replace( user_type_name.begin(), user_type_name.end(), '*', ' ') ;
spos = user_type_name.find("[") ;
if ( spos != std::string::npos ) {
user_type_name.erase( spos ) ;
}
user_type_name.erase(std::remove_if(user_type_name.begin(), user_type_name.end(), (int(*)(int))std::isspace), user_type_name.end()) ;
mit = template_name_map.find(user_type_name) ;
if ( mit != template_name_map.end() ) {
user_type_name = template_name_map[user_type_name] ;
}
}
std::replace( user_type_name.begin(), user_type_name.end(), ':', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '<', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), ',', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '*', ' ') ;
// The user type name may start as const Foo<int>::Bar[4]. We need to convert that to Foo_int___Bar
// remove const from the typename if it exists
spos = user_type_name.find("const ") ;
if ( spos != std::string::npos ) {
user_type_name.erase( spos , spos + 6) ;
}
// remove any brackets
/*
spos = user_type_name.find("[") ;
if ( spos != std::string::npos ) {
user_type_name.erase( spos ) ;
}
spos = user_type_name.find(">") ;
if ( spos != std::string::npos ) {
user_type_name.erase( spos ) ;
}
*/
// replace ":<>,*[]" with '_'
std::replace( user_type_name.begin(), user_type_name.end(), ':', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '<', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '>', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), ',', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '*', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), '[', '_') ;
std::replace( user_type_name.begin(), user_type_name.end(), ']', '_') ;
// remove spaces
user_type_name.erase(std::remove_if(user_type_name.begin(), user_type_name.end(), (int(*)(int))std::isspace), user_type_name.end()) ;
// Attempt to find an io_src_sizeof function for the named user type.
size_func_name = "io_src_sizeof_" + user_type_name ;
for ( ii = 0 ; ii < dlhandles.size() && size_func == NULL ; ii++ ) {
@ -83,7 +75,7 @@ int Trick::MemoryManager::add_attr_info( const std::string & user_type_string ,
if ( size_func == NULL) {
std::stringstream message;
message << "(" << file_name << ":" << line_num
message << "(" << file_name << ":" << line_num
<< "): Couldn't find an io_src_sizeof_ function for type "
<< user_type_string.c_str() << "[" << size_func_name.c_str() << "()].";
emitWarning(message.str());