mirror of
https://github.com/nasa/trick.git
synced 2025-01-18 02:40:08 +00:00
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:
parent
26dfb3a000
commit
ce3ae67633
@ -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
|
||||||
|
@ -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 ;
|
||||||
}
|
}
|
||||||
|
@ -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 ;
|
||||||
}
|
}
|
||||||
|
@ -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 ;
|
||||||
|
|
||||||
|
@ -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 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user