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 ;
|
||||
|
||||
// These need to be ignored by ICG
|
||||
// ICG is now compiler based. Thse are ignored properly.
|
||||
/*
|
||||
static const double scdi = 42.0 ;
|
||||
const static double csdi = 42.0 ;
|
||||
static double const sdci = 42.0 ;
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
ONE , TWO
|
||||
|
@ -110,7 +110,7 @@ bool CXXRecordVisitor::TraverseDecl(clang::Decl *d) {
|
||||
|
||||
bool CXXRecordVisitor::VisitDecl(clang::Decl *d) {
|
||||
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 ;
|
||||
}
|
||||
|
@ -36,8 +36,6 @@ FieldDescription::FieldDescription(
|
||||
is_enum(0) ,
|
||||
is_record(0) ,
|
||||
is_static(0) ,
|
||||
has_type(0) ,
|
||||
has_dims(0) ,
|
||||
num_dims(0) ,
|
||||
array_sizes() {} ;
|
||||
|
||||
@ -378,22 +376,6 @@ bool FieldDescription::isStatic() {
|
||||
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() {
|
||||
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_record = " << fdes.is_record << std::endl ;
|
||||
os << " is_static = " << fdes.is_static << std::endl ;
|
||||
os << " has_type = " << fdes.has_type << std::endl ;
|
||||
|
||||
return os ;
|
||||
}
|
||||
|
@ -75,10 +75,6 @@ class FieldDescription : public ConstructValues {
|
||||
bool getAccessSpecFound() ;
|
||||
bool isInherited() ;
|
||||
bool isVirtualInherited() ;
|
||||
void setHasType( bool yes_no ) ;
|
||||
bool hasType() ;
|
||||
void setHasDims( bool yes_no ) ;
|
||||
bool hasDims() ;
|
||||
void setAccess( clang::AccessSpecifier in_val ) ;
|
||||
clang::AccessSpecifier getAccess() ;
|
||||
|
||||
@ -157,12 +153,6 @@ class FieldDescription : public ConstructValues {
|
||||
/** is this field declared 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 */
|
||||
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) {
|
||||
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() ;
|
||||
}
|
||||
return true ;
|
||||
@ -42,7 +42,7 @@ bool FieldVisitor::VisitDecl(clang::Decl *d) {
|
||||
|
||||
bool FieldVisitor::VisitType(clang::Type *t) {
|
||||
if ( debug_level >= 4 ) {
|
||||
std::cout << "\nFieldVisitor Type = " << t->getTypeClassName() << std::endl ;
|
||||
std::cout << "FieldVisitor VisitType Type = " << t->getTypeClassName() << std::endl ;
|
||||
t->dump() ;
|
||||
}
|
||||
// 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) {
|
||||
|
||||
fdes->setTypeName(bt->desugar().getAsString()) ;
|
||||
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 ( bt->isUnsignedInteger() ) {
|
||||
fdes->setEnumString("TRICK_UNSIGNED_BITFIELD") ;
|
||||
@ -124,15 +124,12 @@ bool FieldVisitor::VisitBuiltinType(clang::BuiltinType *bt) {
|
||||
break ;
|
||||
}
|
||||
}
|
||||
fdes->setHasType(true) ;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FieldVisitor::VisitConstantArrayType(clang::ConstantArrayType *cat) {
|
||||
//cat->dump() ; std::cout << std::endl ;
|
||||
if ( ! fdes->hasDims() ) {
|
||||
fdes->addArrayDim(cat->getSize().getZExtValue()) ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -164,8 +161,8 @@ bool FieldVisitor::VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) {
|
||||
|
||||
if ( debug_level >= 3 ) {
|
||||
if ( ! ci.getSourceManager().isInSystemHeader(dd_range.getEnd()) ) {
|
||||
std::cout << "\nFieldVisitor VisitDeclaratorDecl" << std::endl ;
|
||||
dd->dump() ; std::cout << std::endl ;
|
||||
std::cout << "FieldVisitor VisitDeclaratorDecl" << std::endl ;
|
||||
//dd->dump() ;
|
||||
std::cout << " public/private = " << fdes->getAccess() << std::endl ;
|
||||
}
|
||||
}
|
||||
@ -195,15 +192,10 @@ bool FieldVisitor::VisitEnumType( clang::EnumType *et ) {
|
||||
fdes->setTypeName(enum_type_name) ;
|
||||
fdes->setEnumString("TRICK_ENUMERATED") ;
|
||||
fdes->setEnum(true) ;
|
||||
fdes->setHasType(true) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
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()) ;
|
||||
if ( fdes->isBitField() ) {
|
||||
fdes->setBitFieldWidth(field->getBitWidthValue(field->getASTContext())) ;
|
||||
@ -212,44 +204,51 @@ bool FieldVisitor::VisitFieldDecl( clang::FieldDecl *field ) {
|
||||
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() ;
|
||||
// If the current type is not canonical because of typedefs, traverse the canonical type
|
||||
if ( !qt.isCanonical() ) {
|
||||
clang::QualType ct = qt.getCanonicalType() ;
|
||||
TraverseType(ct) ;
|
||||
// Traversing the canonical type will set the has_type flag. Set the has_dims flag too so
|
||||
// when we continue parsing the AST and the non-canonical type, we don't double add dimensions.
|
||||
fdes->setHasDims(true) ;
|
||||
if ( debug_level >= 3 ) {
|
||||
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() ;
|
||||
}
|
||||
return true ;
|
||||
if ( !qt.isCanonical() and !clang::TemplateSpecializationType::classof(qt.getTypePtr()) ) {
|
||||
clang::QualType ct = qt.getCanonicalType() ;
|
||||
std::string tst_string = ct.getAsString() ;
|
||||
// Do not process standard template library specializations except strings
|
||||
if ( (! tst_string.compare( 0 , 9 , "class std") or ! tst_string.compare( 0 , 10 , "struct std")) and
|
||||
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 ;
|
||||
}
|
||||
|
||||
bool FieldVisitor::VisitElaboratedType(clang::ElaboratedType *et) {
|
||||
if ( debug_level >= 4 ) {
|
||||
std::cout << "FieldVisitor VisitElaboratedType" << std::endl ;
|
||||
}
|
||||
//et->dump() ; std::cout << std::endl ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool FieldVisitor::VisitPointerType(clang::PointerType *p) {
|
||||
if ( ! fdes->hasDims() ) {
|
||||
fdes->addArrayDim(-1) ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
|
||||
if ( debug_level >= 3 ) {
|
||||
std::cout << "FieldVisitor VisitRecordType" << std::endl ;
|
||||
rt->dump() ; std::cout << std::endl ;
|
||||
}
|
||||
/* 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 ;
|
||||
rt->dump() ;
|
||||
}
|
||||
/* Test to see if we have an embedded anonymous struct/union. e.g. SB is anonymous below.
|
||||
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")) {
|
||||
fdes->setEnumString("TRICK_STRING") ;
|
||||
fdes->setTypeName("std::string") ;
|
||||
fdes->setHasType(true) ;
|
||||
return true ;
|
||||
//fdes->setHasType(true) ;
|
||||
return false ;
|
||||
} else {
|
||||
//std::cout << "getDeclName " << type_name << std::endl ;
|
||||
fdes->setTypeName(type_name) ;
|
||||
@ -277,7 +276,6 @@ bool FieldVisitor::VisitRecordType(clang::RecordType *rt) {
|
||||
fdes->setTypeName(rt->getDecl()->getTypedefNameForAnonDecl()->getQualifiedNameAsString()) ;
|
||||
}
|
||||
} 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.
|
||||
if ( debug_level >= 3 ) {
|
||||
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->setRecord(true) ;
|
||||
fdes->setHasType(true) ;
|
||||
return true;
|
||||
// We have our type, return false to stop processing this AST branch
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
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 ;
|
||||
std::map < std::string , std::string > processed_templates ;
|
||||
/* This code handles handles class fields that define a new template type,
|
||||
"my_var" in the below example.
|
||||
|
||||
@ -331,15 +301,12 @@ class T {
|
||||
class B {
|
||||
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) {
|
||||
std::string tst_string = tst->desugar().getAsString() ;
|
||||
if ( debug_level >= 3 ) {
|
||||
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") ) {
|
||||
@ -384,8 +351,6 @@ bool FieldVisitor::VisitTemplateSpecializationType(clang::TemplateSpecialization
|
||||
|
||||
// Check to see if we've created a class that matches this template
|
||||
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
|
||||
// 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(), '*', '_') ;
|
||||
|
||||
|
||||
CXXRecordVisitor template_spec_cvis(ci , cs, hsd , pa, false, false, true) ;
|
||||
/*
|
||||
template_spec_cvis.get_class_data()->setMangledTypeName(fdes->getContainerClass() + "_" +
|
||||
fdes->getName() + "_" + mangled_name) ;
|
||||
*/
|
||||
template_spec_cvis.get_class_data()->setMangledTypeName(mangled_name) ;
|
||||
template_spec_cvis.TraverseCXXRecordDecl(clang::cast<clang::CXXRecordDecl>(td)) ;
|
||||
/*
|
||||
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()->setFileName(fdes->getFileName()) ;
|
||||
|
||||
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.
|
||||
ClassValues * cval = new ClassValues(*(template_spec_cvis.get_class_data())) ;
|
||||
processed_templates[tst_string] = cval ;
|
||||
// save off the mangled name of this template to be used if another variable is the same template type
|
||||
processed_templates[tst_string] = template_spec_cvis.get_class_data()->getMangledTypeName() ;
|
||||
|
||||
fdes->setEnumString("TRICK_STRUCTURED") ;
|
||||
fdes->setRecord(true) ;
|
||||
fdes->setHasType(true) ;
|
||||
if ( debug_level >= 4 ) {
|
||||
std::cout << "Added template class from FieldVisitor VisitTemplateSpecializationType " ;
|
||||
std::cout << tst_string << std::endl ;
|
||||
std::cout << *fdes << std::endl ;
|
||||
}
|
||||
} else {
|
||||
ClassValues * cval = processed_templates[tst_string] ;
|
||||
fdes->setMangledTypeName(cval->getMangledTypeName()) ;
|
||||
// reuse the name of the template already processed.
|
||||
fdes->setMangledTypeName(processed_templates[tst_string]) ;
|
||||
fdes->setEnumString("TRICK_STRUCTURED") ;
|
||||
fdes->setRecord(true) ;
|
||||
fdes->setHasType(true) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
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;
|
||||
// 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::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()) ;
|
||||
/* 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.
|
||||
@ -618,6 +417,14 @@ bool FieldVisitor::VisitVarDecl( clang::VarDecl *v ) {
|
||||
capabilities by taking current io specification & 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 ;
|
||||
}
|
||||
|
||||
|
@ -43,15 +43,15 @@ class FieldVisitor : public clang::RecursiveASTVisitor<FieldVisitor> {
|
||||
bool VisitBuiltinType(clang::BuiltinType *bt);
|
||||
bool VisitConstantArrayType(clang::ConstantArrayType *a) ;
|
||||
bool VisitDeclaratorDecl( clang::DeclaratorDecl *dd ) ;
|
||||
bool VisitElaboratedType( clang::ElaboratedType *et ) ;
|
||||
//bool VisitElaboratedType( clang::ElaboratedType *et ) ;
|
||||
bool VisitEnumType( clang::EnumType *et ) ;
|
||||
bool VisitFieldDecl( clang::FieldDecl *field ) ;
|
||||
bool VisitPointerType(clang::PointerType *p);
|
||||
bool VisitRecordType(clang::RecordType *rt);
|
||||
bool VisitSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType *sttpt);
|
||||
//bool VisitSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType *sttpt);
|
||||
bool VisitTemplateSpecializationType(clang::TemplateSpecializationType *tst);
|
||||
bool VisitTemplateTypeParmType(clang::TemplateTypeParmType *ttp);
|
||||
bool VisitTypedefType(clang::TypedefType *tt);
|
||||
//bool VisitTemplateTypeParmType(clang::TemplateTypeParmType *ttp);
|
||||
//bool VisitTypedefType(clang::TypedefType *tt);
|
||||
bool VisitVarDecl( clang::VarDecl *v ) ;
|
||||
|
||||
/** Returns the field data */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.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() ) ;
|
||||
//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.
|
||||
const clang::FileEntry *pFile = ci.getFileManager().getFile(input_file_full_path);
|
||||
#if (__clang_major__ >= 6) || ((__clang_major__ == 3) && (__clang_minor__ >= 5))
|
||||
|
Loading…
Reference in New Issue
Block a user