ATTRIBUTES for a member whose type is typedef'd in a template are wrong

I found that in ICG I have access to the canonical type of a variable which
in most cases is the type I should process.  Doing this eliminates the
need for some of the code that resolved typedefs because the canonical type
has already done that.

refs #200
This commit is contained in:
Alex Lin 2016-03-16 13:24:59 -05:00
parent 26dfb3a000
commit ce3ae67633
7 changed files with 80 additions and 293 deletions

View File

@ -393,9 +393,12 @@ class ClassOfEverything {
static double const sdc ; static double const sdc ;
// These need to be ignored by ICG // These need to be ignored by ICG
// ICG is now compiler based. Thse are ignored properly.
/*
static const double scdi = 42.0 ; static const double scdi = 42.0 ;
const static double csdi = 42.0 ; const static double csdi = 42.0 ;
static double const sdci = 42.0 ; static double const sdci = 42.0 ;
*/
typedef enum { typedef enum {
ONE , TWO ONE , TWO

View File

@ -110,7 +110,7 @@ bool CXXRecordVisitor::TraverseDecl(clang::Decl *d) {
bool CXXRecordVisitor::VisitDecl(clang::Decl *d) { bool CXXRecordVisitor::VisitDecl(clang::Decl *d) {
if ( debug_level >=2 ) { if ( debug_level >=2 ) {
std::cout << "\nCXXRecordVisitor Decl = " << d->getDeclKindName() << std::endl ; std::cout << "\n\033[34mCXXRecordVisitor VisitDecl Decl = " << d->getDeclKindName() << "\033[0m" << std::endl ;
} }
return true ; return true ;
} }

View File

@ -36,8 +36,6 @@ FieldDescription::FieldDescription(
is_enum(0) , is_enum(0) ,
is_record(0) , is_record(0) ,
is_static(0) , is_static(0) ,
has_type(0) ,
has_dims(0) ,
num_dims(0) , num_dims(0) ,
array_sizes() {} ; array_sizes() {} ;
@ -378,22 +376,6 @@ bool FieldDescription::isStatic() {
return is_static ; return is_static ;
} }
void FieldDescription::setHasType( bool yes_no ) {
has_type = yes_no ;
}
bool FieldDescription::hasType() {
return has_type ;
}
void FieldDescription::setHasDims( bool yes_no ) {
has_dims = yes_no ;
}
bool FieldDescription::hasDims() {
return has_dims ;
}
unsigned int FieldDescription::getNumDims() { unsigned int FieldDescription::getNumDims() {
return num_dims ; return num_dims ;
} }
@ -446,7 +428,6 @@ std::ostream & operator << (std::ostream & os , FieldDescription & fdes ) {
os << " is_enum = " << fdes.is_enum << std::endl ; os << " is_enum = " << fdes.is_enum << std::endl ;
os << " is_record = " << fdes.is_record << std::endl ; os << " is_record = " << fdes.is_record << std::endl ;
os << " is_static = " << fdes.is_static << std::endl ; os << " is_static = " << fdes.is_static << std::endl ;
os << " has_type = " << fdes.has_type << std::endl ;
return os ; return os ;
} }

View File

@ -75,10 +75,6 @@ class FieldDescription : public ConstructValues {
bool getAccessSpecFound() ; bool getAccessSpecFound() ;
bool isInherited() ; bool isInherited() ;
bool isVirtualInherited() ; bool isVirtualInherited() ;
void setHasType( bool yes_no ) ;
bool hasType() ;
void setHasDims( bool yes_no ) ;
bool hasDims() ;
void setAccess( clang::AccessSpecifier in_val ) ; void setAccess( clang::AccessSpecifier in_val ) ;
clang::AccessSpecifier getAccess() ; clang::AccessSpecifier getAccess() ;
@ -157,12 +153,6 @@ class FieldDescription : public ConstructValues {
/** is this field declared static */ /** is this field declared static */
bool is_static ; bool is_static ;
/** Have we resolved the type for this parameter? */
bool has_type ;
/** Have we resolved the dimensions for this parameter? */
bool has_dims ;
/** map of strings to io numbers. One copy for all fields */ /** map of strings to io numbers. One copy for all fields */
static std::map<std::string , unsigned int> io_map ; static std::map<std::string , unsigned int> io_map ;

View File

@ -34,7 +34,7 @@ FieldVisitor::FieldVisitor(clang::CompilerInstance & in_ci ,
bool FieldVisitor::VisitDecl(clang::Decl *d) { bool FieldVisitor::VisitDecl(clang::Decl *d) {
if ( debug_level >= 4 ) { if ( debug_level >= 4 ) {
std::cout << "\nFieldVisitor Decl = " << d->getDeclKindName() << std::endl ; std::cout << "\n\033[32mFieldVisitor VisitDecl Decl = " << d->getDeclKindName() << "\033[00m" << std::endl ;
d->dump() ; d->dump() ;
} }
return true ; return true ;
@ -42,7 +42,7 @@ bool FieldVisitor::VisitDecl(clang::Decl *d) {
bool FieldVisitor::VisitType(clang::Type *t) { bool FieldVisitor::VisitType(clang::Type *t) {
if ( debug_level >= 4 ) { if ( debug_level >= 4 ) {
std::cout << "\nFieldVisitor Type = " << t->getTypeClassName() << std::endl ; std::cout << "FieldVisitor VisitType Type = " << t->getTypeClassName() << std::endl ;
t->dump() ; t->dump() ;
} }
// If this type is a reference, set IO to 0 // If this type is a reference, set IO to 0
@ -57,10 +57,10 @@ bool FieldVisitor::VisitType(clang::Type *t) {
bool FieldVisitor::VisitBuiltinType(clang::BuiltinType *bt) { bool FieldVisitor::VisitBuiltinType(clang::BuiltinType *bt) {
fdes->setTypeName(bt->desugar().getAsString()) ;
if ( debug_level >= 3 ) { if ( debug_level >= 3 ) {
std::cout << "FieldVisitor::VisitBuiltinType " << fdes->getTypeName() << std::endl ; std::cout << "FieldVisitor::VisitBuiltinType " << bt->desugar().getAsString() << std::endl ;
} }
fdes->setTypeName(bt->desugar().getAsString()) ;
if ( fdes->isBitField() ) { if ( fdes->isBitField() ) {
if ( bt->isUnsignedInteger() ) { if ( bt->isUnsignedInteger() ) {
fdes->setEnumString("TRICK_UNSIGNED_BITFIELD") ; fdes->setEnumString("TRICK_UNSIGNED_BITFIELD") ;
@ -124,15 +124,12 @@ bool FieldVisitor::VisitBuiltinType(clang::BuiltinType *bt) {
break ; break ;
} }
} }
fdes->setHasType(true) ;
return true; return true;
} }
bool FieldVisitor::VisitConstantArrayType(clang::ConstantArrayType *cat) { bool FieldVisitor::VisitConstantArrayType(clang::ConstantArrayType *cat) {
//cat->dump() ; std::cout << std::endl ; //cat->dump() ; std::cout << std::endl ;
if ( ! fdes->hasDims() ) { fdes->addArrayDim(cat->getSize().getZExtValue()) ;
fdes->addArrayDim(cat->getSize().getZExtValue()) ;
}
return true; return true;
} }
@ -164,8 +161,8 @@ bool FieldVisitor::VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) {
if ( debug_level >= 3 ) { if ( debug_level >= 3 ) {
if ( ! ci.getSourceManager().isInSystemHeader(dd_range.getEnd()) ) { if ( ! ci.getSourceManager().isInSystemHeader(dd_range.getEnd()) ) {
std::cout << "\nFieldVisitor VisitDeclaratorDecl" << std::endl ; std::cout << "FieldVisitor VisitDeclaratorDecl" << std::endl ;
dd->dump() ; std::cout << std::endl ; //dd->dump() ;
std::cout << " public/private = " << fdes->getAccess() << std::endl ; std::cout << " public/private = " << fdes->getAccess() << std::endl ;
} }
} }
@ -195,15 +192,10 @@ bool FieldVisitor::VisitEnumType( clang::EnumType *et ) {
fdes->setTypeName(enum_type_name) ; fdes->setTypeName(enum_type_name) ;
fdes->setEnumString("TRICK_ENUMERATED") ; fdes->setEnumString("TRICK_ENUMERATED") ;
fdes->setEnum(true) ; fdes->setEnum(true) ;
fdes->setHasType(true) ;
return true ; return true ;
} }
bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) { bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) {
if ( debug_level >= 3 ) {
std::cout << "\nFieldVisitor VisitFieldDecl" << std::endl ;
field->dump() ; std::cout << std::endl ;
}
fdes->setBitField(field->isBitField()) ; fdes->setBitField(field->isBitField()) ;
if ( fdes->isBitField() ) { if ( fdes->isBitField() ) {
fdes->setBitFieldWidth(field->getBitWidthValue(field->getASTContext())) ; fdes->setBitFieldWidth(field->getBitWidthValue(field->getASTContext())) ;
@ -212,44 +204,51 @@ bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) {
fdes->setBitFieldByteOffset((field_offset_bits / 32) * 4 ) ; 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
// Template type specializations are marked non canonical.
// Do not process template specialization types here, allow normal processing to continue in that case.
clang::QualType qt = field->getType() ; clang::QualType qt = field->getType() ;
// If the current type is not canonical because of typedefs, traverse the canonical type if ( debug_level >= 3 ) {
if ( !qt.isCanonical() ) { std::cout << "FieldVisitor VisitFieldDecl" << std::endl ;
std::cout << " is_bitfield = " << fdes->isBitField() << std::endl ;
std::cout << " is_canonical = " << qt.isCanonical() << std::endl ;
std::cout << " is_a_template_specialization = " <<
clang::TemplateSpecializationType::classof(qt.getTypePtr()) << std::endl ;
//field->dump() ;
}
if ( !qt.isCanonical() and !clang::TemplateSpecializationType::classof(qt.getTypePtr()) ) {
clang::QualType ct = qt.getCanonicalType() ; clang::QualType ct = qt.getCanonicalType() ;
TraverseType(ct) ; std::string tst_string = ct.getAsString() ;
// Traversing the canonical type will set the has_type flag. Set the has_dims flag too so // Do not process standard template library specializations except strings
// when we continue parsing the AST and the non-canonical type, we don't double add dimensions. if ( (! tst_string.compare( 0 , 9 , "class std") or ! tst_string.compare( 0 , 10 , "struct std")) and
fdes->setHasDims(true) ; tst_string.compare( 0, 23 , "class std::basic_string") ) {
// This is a standard template library type. don't process any further.
fdes->setIO(0) ;
} else {
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 ;
}
bool FieldVisitor::VisitElaboratedType(clang::ElaboratedType *et) {
if ( debug_level >= 4 ) {
std::cout << "FieldVisitor VisitElaboratedType" << std::endl ;
}
//et->dump() ; std::cout << std::endl ;
return true ; return true ;
} }
bool FieldVisitor::VisitPointerType(clang::PointerType *p) { bool FieldVisitor::VisitPointerType(clang::PointerType *p) {
if ( ! fdes->hasDims() ) { fdes->addArrayDim(-1) ;
fdes->addArrayDim(-1) ;
}
return true; return true;
} }
bool FieldVisitor::VisitRecordType(clang::RecordType *rt) { bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
if ( debug_level >= 3 ) { if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitRecordType" << std::endl ; std::cout << "FieldVisitor VisitRecordType" << std::endl ;
rt->dump() ; std::cout << std::endl ; rt->dump() ;
}
/* An array parameter may be a value within a record type. In this case we
may end up here multiple times for a field. The first
visitor is field type. Other visits are for the array parameters.
Return if we have already set the type for this field. */
if ( fdes->hasType() ) {
return true ;
} }
/* Test to see if we have an embedded anonymous struct/union. e.g. SB is anonymous below. /* Test to see if we have an embedded anonymous struct/union. e.g. SB is anonymous below.
struct SA { struct SA {
@ -266,8 +265,8 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
if ( ! type_name.compare("std::basic_string") || !type_name.compare("std::__1::basic_string")) { if ( ! type_name.compare("std::basic_string") || !type_name.compare("std::__1::basic_string")) {
fdes->setEnumString("TRICK_STRING") ; fdes->setEnumString("TRICK_STRING") ;
fdes->setTypeName("std::string") ; fdes->setTypeName("std::string") ;
fdes->setHasType(true) ; //fdes->setHasType(true) ;
return true ; return false ;
} else { } else {
//std::cout << "getDeclName " << type_name << std::endl ; //std::cout << "getDeclName " << type_name << std::endl ;
fdes->setTypeName(type_name) ; fdes->setTypeName(type_name) ;
@ -277,7 +276,6 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
fdes->setTypeName(rt->getDecl()->getTypedefNameForAnonDecl()->getQualifiedNameAsString()) ; fdes->setTypeName(rt->getDecl()->getTypedefNameForAnonDecl()->getQualifiedNameAsString()) ;
} }
} else { } else {
//rt->getDecl()->dump() ; std::cout << std::endl ;
// io_src code not possible for anonymous struct/unions. Set the I/O to 0 to ignore it. // io_src code not possible for anonymous struct/unions. Set the I/O to 0 to ignore it.
if ( debug_level >= 3 ) { if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitRecordType found anonymous type, setIO = 0" << std::endl ; std::cout << "FieldVisitor VisitRecordType found anonymous type, setIO = 0" << std::endl ;
@ -287,39 +285,11 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setEnumString("TRICK_STRUCTURED") ;
fdes->setRecord(true) ; fdes->setRecord(true) ;
fdes->setHasType(true) ; // We have our type, return false to stop processing this AST branch
return true; return false;
} }
/* std::map < std::string , std::string > processed_templates ;
In a template, this is the type that is defined by one of the incoming parameters.
template < class T > class A {
T var ;
} ;
In the above example this visitor is the resolved "T" class on the line "T var ;"
*/
bool FieldVisitor::VisitSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType *sttpt) {
if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitSubstTemplateTypeParmType" << std::endl ;
sttpt->dump() ; std::cout << std::endl ;
}
if ( fdes->hasType() ) {
if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitSubstTemplateTypeParmType field has type already" << std::endl ;
}
return true ;
}
if ( sttpt->isBuiltinType() ) {
VisitBuiltinType((clang::BuiltinType *)sttpt->getAs<clang::BuiltinType>()) ;
} else if ( sttpt->isEnumeralType() ) {
VisitEnumType((clang::EnumType *)sttpt->getAs<clang::EnumType>()) ;
} else if ( sttpt->isRecordType() ) {
VisitRecordType((clang::RecordType *)sttpt->getAs<clang::RecordType>()) ;
}
return true;
}
std::map < std::string , ClassValues * > processed_templates ;
/* This code handles handles class fields that define a new template type, /* This code handles handles class fields that define a new template type,
"my_var" in the below example. "my_var" in the below example.
@ -331,15 +301,12 @@ class T {
class B { class B {
T<int> my_var ; 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) { bool FieldVisitor::VisitTemplateSpecializationType(clang::TemplateSpecializationType *tst) {
std::string tst_string = tst->desugar().getAsString() ; std::string tst_string = tst->desugar().getAsString() ;
if ( debug_level >= 3 ) { if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitTemplateSpecializationType " << tst_string << std::endl ; std::cout << "FieldVisitor VisitTemplateSpecializationType " << tst_string << std::endl ;
tst->dump() ; std::cout << std::endl ; //tst->dump() ;
} }
if ( ! tst_string.compare( 0 , 9 , "class std") or ! tst_string.compare( 0 , 10 , "struct std") ) { if ( ! tst_string.compare( 0 , 9 , "class std") or ! tst_string.compare( 0 , 10 , "struct std") ) {
@ -384,8 +351,6 @@ bool FieldVisitor::VisitTemplateSpecializationType(clang::TemplateSpecialization
// Check to see if we've created a class that matches this template // Check to see if we've created a class that matches this template
if ( processed_templates.find(tst_string) == processed_templates.end() ) { 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 // Use the current template type name, tst_string, as part of the mangled type name
// Some characters have to converted to underscores. // Some characters have to converted to underscores.
@ -397,212 +362,46 @@ bool FieldVisitor::VisitTemplateSpecializationType(clang::TemplateSpecialization
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(), '*', '_') ;
CXXRecordVisitor template_spec_cvis(ci , cs, hsd , pa, false, false, true) ;
/*
template_spec_cvis.get_class_data()->setMangledTypeName(fdes->getContainerClass() + "_" + template_spec_cvis.get_class_data()->setMangledTypeName(fdes->getContainerClass() + "_" +
fdes->getName() + "_" + mangled_name) ; fdes->getName() + "_" + mangled_name) ;
*/
template_spec_cvis.get_class_data()->setMangledTypeName(mangled_name) ;
template_spec_cvis.TraverseCXXRecordDecl(clang::cast<clang::CXXRecordDecl>(td)) ; template_spec_cvis.TraverseCXXRecordDecl(clang::cast<clang::CXXRecordDecl>(td)) ;
/*
fdes->setMangledTypeName(fdes->getContainerClass() + "_" + fdes->getName() + "_" + mangled_name) ; fdes->setMangledTypeName(fdes->getContainerClass() + "_" + fdes->getName() + "_" + mangled_name) ;
*/
fdes->setMangledTypeName(mangled_name) ;
template_spec_cvis.get_class_data()->setName(tst_string) ; template_spec_cvis.get_class_data()->setName(tst_string) ;
template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ; template_spec_cvis.get_class_data()->setFileName(fdes->getFileName()) ;
pa.printClass(template_spec_cvis.get_class_data()) ; 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. // save off the mangled name of this template to be used if another variable is the same template type
ClassValues * cval = new ClassValues(*(template_spec_cvis.get_class_data())) ; processed_templates[tst_string] = template_spec_cvis.get_class_data()->getMangledTypeName() ;
processed_templates[tst_string] = cval ;
fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setEnumString("TRICK_STRUCTURED") ;
fdes->setRecord(true) ; fdes->setRecord(true) ;
fdes->setHasType(true) ;
if ( debug_level >= 4 ) { if ( debug_level >= 4 ) {
std::cout << "Added template class from FieldVisitor VisitTemplateSpecializationType " ; std::cout << "Added template class from FieldVisitor VisitTemplateSpecializationType " ;
std::cout << tst_string << std::endl ; std::cout << tst_string << std::endl ;
std::cout << *fdes << std::endl ; std::cout << *fdes << std::endl ;
} }
} else { } else {
ClassValues * cval = processed_templates[tst_string] ; // reuse the name of the template already processed.
fdes->setMangledTypeName(cval->getMangledTypeName()) ; fdes->setMangledTypeName(processed_templates[tst_string]) ;
fdes->setEnumString("TRICK_STRUCTURED") ; fdes->setEnumString("TRICK_STRUCTURED") ;
fdes->setRecord(true) ; fdes->setRecord(true) ;
fdes->setHasType(true) ;
} }
} }
} }
return true ; // We have either extracted the template type or have marked this field I/O = 0.
} // We can return false to stop processing of this AST branch
return false ;
bool FieldVisitor::VisitTemplateTypeParmType(clang::TemplateTypeParmType *ttp) {
fdes->setTypeName(ttp->getDecl()->getNameAsString()) ;
return true ;
}
class IgnoreTypes {
public:
IgnoreTypes() {
types.insert("basic_ostringstream<char>") ;
}
std::set< std::string > types ;
} ;
IgnoreTypes ignore_types ;
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() ) {
if ( debug_level >= 4 ) {
std::cout << "FieldVisitor isRecordType" << std::endl ;
}
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;
} }
bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) { bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) {
if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitVarDecl " << fdes->getName() << std::endl ;
v->dump() ; std::cout << std::endl ;
}
fdes->setStatic(v->isStaticDataMember()) ; fdes->setStatic(v->isStaticDataMember()) ;
/* If we have a static const integer type with an initializer value, this variable will /* If we have a static const integer type with an initializer value, this variable will
not be instantiated by the compiler. The compiler substitutes in the value internally. not be instantiated by the compiler. The compiler substitutes in the value internally.
@ -618,6 +417,14 @@ bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) {
capabilities by taking current io specification & 1 */ capabilities by taking current io specification & 1 */
fdes->setIO(fdes->getIO() & 1) ; fdes->setIO(fdes->getIO() & 1) ;
} }
if ( debug_level >= 3 ) {
std::cout << "FieldVisitor VisitVarDecl " << fdes->getName() << std::endl ;
std::cout << " is static = " << fdes->isStatic() << std::endl ;
std::cout << " is const = " << v->getType().isConstQualified() << std::endl ;
std::cout << " has initializer value = " << v->hasInit() << std::endl ;
std::cout << " IO = " << fdes->getIO() << std::endl ;
//v->dump() ; std::cout << std::endl ;
}
return true ; return true ;
} }

View File

@ -43,15 +43,15 @@ class FieldVisitor : public clang::RecursiveASTVisitor<FieldVisitor> {
bool VisitBuiltinType(clang::BuiltinType *bt); bool VisitBuiltinType(clang::BuiltinType *bt);
bool VisitConstantArrayType(clang::ConstantArrayType *a) ; bool VisitConstantArrayType(clang::ConstantArrayType *a) ;
bool VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) ; bool VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) ;
bool VisitElaboratedType( clang::ElaboratedType *et ) ; //bool VisitElaboratedType( clang::ElaboratedType *et ) ;
bool VisitEnumType( clang::EnumType *et ) ; bool VisitEnumType( clang::EnumType *et ) ;
bool VisitFieldDecl( clang::FieldDecl *field ) ; bool VisitFieldDecl( clang::FieldDecl *field ) ;
bool VisitPointerType(clang::PointerType *p); bool VisitPointerType(clang::PointerType *p);
bool VisitRecordType(clang::RecordType *rt); bool VisitRecordType(clang::RecordType *rt);
bool VisitSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType *sttpt); //bool VisitSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType *sttpt);
bool VisitTemplateSpecializationType(clang::TemplateSpecializationType *tst); bool VisitTemplateSpecializationType(clang::TemplateSpecializationType *tst);
bool VisitTemplateTypeParmType(clang::TemplateTypeParmType *ttp); //bool VisitTemplateTypeParmType(clang::TemplateTypeParmType *ttp);
bool VisitTypedefType(clang::TypedefType *tt); //bool VisitTypedefType(clang::TypedefType *tt);
bool VisitVarDecl( clang::VarDecl *v ) ; bool VisitVarDecl( clang::VarDecl *v ) ;
/** Returns the field data */ /** Returns the field data */

View File

@ -3,6 +3,7 @@
#include <libgen.h> #include <libgen.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
@ -175,6 +176,11 @@ int main( int argc , char * argv[] ) {
input_file_full_path = almostRealPath( os.str().c_str() ) ; input_file_full_path = almostRealPath( os.str().c_str() ) ;
//std::cout << input_file_full_path << std::endl ; //std::cout << input_file_full_path << std::endl ;
struct stat buffer ;
if ( stat ( input_file_full_path , &buffer) != 0 ) {
std::cerr << "Could not open file " << input_file_full_path << std::endl ;
exit(-1) ;
}
// Open up the input file and parse it. // Open up the input file and parse it.
const clang::FileEntry *pFile = ci.getFileManager().getFile(input_file_full_path); const clang::FileEntry *pFile = ci.getFileManager().getFile(input_file_full_path);
#if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 5)) #if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 5))